操作系统
什么是线程与进程?§
- 进程
- 资源分配最小单位,是能拥有资源和独立运行的最小单位
- 有自己的独立地址空间,系统会建立数据表来维护代码段、堆栈段和数据段
- 进程间的通信需要以通信的方式(IPC)进行
- 多进程程序更健壮
- 同步:无名管道、有名管道、信号、共享内存、消息队列、信号量
- 僵尸进程:子进程退出时父进程没有获取其最新状态的子进程(ps 命令的 defunct 京城状态)
- 孤儿进程:父进程运行结束时子进程还在运行时
- 线程
- CPU 调度的最小单位,线程是建立在进程的基础上的一次程序运行单位,一个进程中可以有多个线程
- 是共享中的数据,使用相同的地址空间(开销小)
- 同一进程下的线程间共享全局变量、静态变量等数据
- 多线程见需要处理好同步和互斥,否则一个线程死掉整个进程死掉
- 同步:互斥量、读写锁、自旋锁、线程信号、条件变量
属性 | 多进程 | 多线程 | 比较 |
---|---|---|---|
数据 | 数据共享复杂,需要用IPC;数据是分开的,同步简单 | 因为共享进程数据,数据共享简单,同步复杂 | 各有千秋 |
CPU、内存 | 占用内存多,切换复杂,CPU利用率低 | 占用内存少,切换简单,CPU利用率高 | 多线程更好 |
销毁、切换 | 创建销毁、切换复杂,速度慢 | 创建销毁、切换简单,速度很快 | 多线程更好 |
coding | 编码简单、调试方便 | 编码、调试复杂 | 多进程更好 |
可靠性 | 进程独立运行,不会相互影响 | 线程同呼吸共命运 | 多进程更好 |
分布式 | 可用于多机多核分布式,易于扩展 | 只能用于多核分布式 | 多进程更好 |
进程/线程通信的具体方式有哪些?§
- 进程:
- 管道(包括管道和命名管道) 内存中类似于文件的模型,多进程可读写
- 信号及信号量通信
- 消息队列 内核中的队列
- 共享内存
- socket
- 线程:
- 共享内存
- 管道
如何管理进程?§
如何实现线程同步?§
- 互斥锁
- 信号量(Semaphore)、事件对象(Event):事件对象是以通知的方式进行控制,主要用于同步控制
如何理解管道/信号量?§
- 信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送数据为主要目的,它主要是用来保护共享资源(信号量也属于临界资源),使得资源在一个时刻只有一个进程独享。
什么是 CPU 和 GPU?§
- CPU:每个核心可以处理多个任务
- GPU:图形处理,每个单元只能处理有限的任务,可以工作在多个核心之间
线程和协程如何对比?§
- 在计算机科学中还有一个概念叫做 Fiber,英文含义就是“纤维”,意指比 Thread 更细的线,也就是比线程(Thread)控制得更精密的并发处理机制。
并行和并发的机制和区别?§
- 并行可以是并发,而并发不一定是并行。并行一般需要物理层面的支持。
- 并发的关键是你有处理多个任务的能力,不一定要同时。
- 并行的关键是你有同时处理多个任务的能力。
- 最关键的点就是:是否是『同时』。
- 并发和并行都可以是很多个线程,就看这些线程会不会同时被多个 CPU 执行,如果可以说明是并行,而并发是多个线程被一个 CPU 轮流切换着运行。
BSD UNIX 的进程通信机制?§
Socket的英文原义是“孔”或“插座”。作为BSD UNIX的进程通信机制,取后一种意思。通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。Socket正如其英文原义那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。—— 百度百科
- Socket API 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC (Inter-Process Communication)机制,就是 UNIX Domain Socket 也称为本地域。虽然网络 socket 也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是 UNIX Domain Socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket 也提供面向流和面向数据包两种 API 接口,类似于 TCP 和 UDP,但是面向消息的 UNIX Domain Socket 也是可靠的,消息既不会丢失也不会顺序错乱。
如何区分用户态和内核态?§
- 行在内核态的程序可以访问的资源多,但可靠性、安全性要求高,维护管理都较复杂;
- 用户态程序访问的资源受限,但可靠性、安全性要求低,自然编写维护起来都较简单。
- 一个程序到底应该运行在内核态还是用户态取决于其对资源和效率的需求。
- 用户态切换到内核态的3种方式:
- 系统调用:这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
- 异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
- 外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。