进程状态
- 创建状态:初始化进程控制块PCB,分配进程运行需要的资源。
- 就绪状态:进程已拥有除CPU以外所有资源,进入就绪队列,等待CPU调度。
- 运行状态:已获得CPU,正处于执行的状态。
- 阻塞状态:由于发生某些事件(IO请求、缓冲区申请失败等)暂时无法执行,进入阻塞状态。
- 终止状态:进行进程的清理工作,回收PCB。
僵尸进程
- 进程结束后没有被完全销毁,而是留下了成为僵尸进程的数据结构。
- 进程结束后仍然会保留包括进程号、退出状态、运行时间的信息,占用进程号不释放。
- 避免方法:
- 通过wait/waitpid等待子进程结束。
- 注册SIGGHLD信号处理函数。
- 忽略SIGGHLD信号,内核自动回收僵尸进程。
孤儿进程
- 父进程退出后还在运行的子进程成为孤儿进程。
- 孤儿进程会由init进程(1号进程)接管,不会变成僵尸进程。
进程调度方法
-
先来先服务(FCFS)调度算法:按照请求的顺序进行调度。有利于长作业,但不利于短作业。
-
短作业(进程)优先调度算法:按估计运行时间最短的顺序进行调度。如果一直有短作业,那么长作业可能永远得不到调度。
-
高优先权优先调度算法:为每个进程分配一个优先级,按优先级进行调度。
-
高响应比优先调度算法: 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 \frac{等待时间+要求服务时间}{要求服务时间} 要求服务时间等待时间+要求服务时间
-
时间片的轮转调度算法:计时器发出时钟中断信号,调度程序通过中断信号来终止进程的执行,并调度下一个进程。
-
多级反馈队列调度算法:
- 多个不同优先级的就绪队列。
- 就绪队列中按照FCFS调度,超过时间片的长作业(进程)会进入低优先级队列。
- 当高优先级队列空闲之后才能调度第优先级队列。
进程调度
-
保存上下文到内核栈。
-
将要调度的进程上下文拷贝到寄存器。
-
切换虚拟地址空间。
进程和线程调度的区别
- 同一个进程中的线程公用进程的资源,线程切换时资源不变,对CPU Cache和TLB影响不大,仅需要多寄存器,方法栈的进行切换。
- 进程调度时或者不同进程中的线程切换时,因为使用的资源不同,所有的大量缓存会失效。
进程栈和线程栈的区别
- 进程栈起始地址和大小保存在task_struct的mm_struct->mm中,内存分配在进程虚拟地址空间的栈区。
- 线程栈的的起始地址和大小保存在pthread_attr_t中,内存分配在进程虚拟地址空间的堆区。
进程间通信方式
- 信号量:它是一个计数器,用来控制多个进程对共享资源的访问。
- 共享内存:多个进程共享同一资源,数据不需要在进程之间复制,所以是最快的通信方式。
- TCP/IP 套接字的方式(socket) :用于不同机器间的进程通信。这种方式在 TCP/IP 连接上建立一个基于网络的连接请求,不同机器通过 TCP/IP 网络进行连接和通信。
- 消息队列:它是消息的链表,存放在内核中并由消息队列标识符标识。
- 管道:支持半双工通信,数据单向流动,只能用于父子进程和兄弟进程。
- 命名管道 FIFO:也具有管道的性质,但它允许无亲缘关系的进程进行通信。
共享内存通信的实现
- 内存映射(mmap)
- 后备文件共享映射:映射内存的修改对**其他进程(不限制于父子进程)**可见,且修改会写回后备文件,用于大文件读写,进程间共享内存。
- 后备文件私有映射:映射内存写时复制,用于共享只读文件。
- 匿名文件共享映射:映射内存的修改对其他进程可见,用于父子进程共享内存通信。
- 匿名文件私有映射:映射内存写时复制,用于分配内存,例如malloc分配大内存。
- shm,纯粹的内存共享方案,本质是在
/data/shm/
目录下创建了一个(内存)文件。