进程管理
进程、线程、协程的区别:
资源分配的基本单位 资源调度的基本单位 轻量级的线程
切换 页表、栈等 程序计数器、栈、寄存器等 栈和寄存器 切换代价越来越小
协程不用进入内核态,在用户态。它两陷入内核态的原因:进入内核态保存上下文信息。
进程的通信方式
管道:通信方式是效率低的,因此管道不适合进程间频繁地交换数据。
- 管道类型
- 有名管道:
mkfifo myPipe
- 匿名管道:
int pipe(int fd[2])
,这里只创建了一个管道,一个是管道的读取端描述符 fd[0],另一个是管道的写入端描述符 fd[1]。
fd[2]一般用于父子进程之间的通信。ps auxf | grep mysql
:shell创建了两个子进程,然后使用管道来在子进程中传递消息。
- 有名管道:
- 管道传输数据是单向的,如果想相互通信,我们需要创建两个管道才行。写入管道以后,数据就保存在管道中,等待读取。
- 所谓的管道,就是内核里面的一串缓存。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。
消息队列:
- 消息队列是保存在内核中的消息链表,消息体是用户自定义的数据类型。
- 与管道通信的区别:
- 管道通信为无格式的字节流,消息队列为自定义数据类型。
- 消息队列可以为非阻塞,在消息队列为空或已满时进行等待,也可以选择立即返回。如果管道中没有数据则会阻塞。
- 如果没有释放消息队列或者没有关闭操作系统,消息队列会一直存在。管道数据随着进程的消失而消失。
- 缺点:队列有大小限制、存在用户态与内核态之间的数据拷贝开销。
共享内存:消息队列和管道都会有发生用户态与内核态之间的消息拷贝过程。
- 共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。
信号量:信号量用于防止多进程竞争共享资源,如共享内存。
- P操作:减一
- V操作:加一
- 信号量小于零代表有阻塞进程。
- 信号量可以用于互斥访问资源,以及控制进程的执行顺序(同步)。
信号:如ctrl+c杀死进程。当然我们可以自定义信号的处理函数。
socket:用于不同机器上进程之间的通信。
死锁
死锁的四个条件(必要条件):
- 互斥条件:同一时间资源只能被一个线程拥有。
- 持有并等待条件:持有一个资源,等待另一个资源
- 不可剥夺条件:只能等待其他线程释放资源,不能直接剥夺其他线程资源
- 环路等待条件:形成了等待环路,在两个线程中就是互相等待。
破坏上述必要条件就可以防止死锁,常用的方法有使用资源有序分配法,来破环环路等待条件