浅度睡眠可以接收信号,而深度睡眠不可以接收信号
2.4 进程队列进程队列:
操作系统为每一类进程建立一个或多个队列
队列元素为PCB
伴随进程状态的改变,其PCB从一个队列进入另一个队列
等待态队列,多个等待队列等待的条件不同
就绪态队列也可以是多个
进程控制操作完成进程各状态之间的转换,由具有特定功能的原语完成。
原语(Primitive)
完成某种特定功能的一段程序,具有不可分割或不可中断性。即原语的执行必须是连续的,在执行过程中不允许被中断。----原子操作(atomic)
给新进程分配一个唯一标识以及进程控制块
为进程分配地址空间
初始化进程控制块
设置默认值(如:状态为New,...)
设置相应的队列指针
如:把新进程加到就绪队列链表中
收回进程所占有的资源
关闭打开的文件、断开网络连接、回收分配的内存
撤销该进程的PCB
3.3 进程阻塞处于运行状态的进程,在其运行过程中期待某一时间发生,如等待键盘输入、等待磁盘数据传输完成、等待其他进程发送消息。当被等待的事件未发生时,由进程自己执行阻塞原语,使自己由运行态变为阻塞态。
wait();
3.4 Unix的几个进程控制操作fork() 通过复制调用进程(父进程)来建立新的进程,是最基本的进程建立过程
exec() 包括一系列系统调用,它们都是通过用一段新的程序代码覆盖原来的地址空间,实现进程执行代码的转换
wait() 提供初级进程同步操作,能使一个进程等待另外一个进程的结束
exit() 用来终止一个进程的运行
3.5 Unix的fork()实现为子进程分配一个空闲的进程描述符
proc结构
分配给子进程唯一标识pid
以一次一页的方式复制父进程地址空间
弊端:Unix中从父进程复制到子进程的内容,好多都不需要。Linux采用了写时复制技术COW加快创建进程 Copy-On-Write
从父进程处继承共享资源,如打开的文件和当前工作目录等
将子进程的状态设为就绪,插入到就绪队列
对子进程返回标识符0
向父进程返回子进程的pid
#include <sys/types.h> #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { pid_t pid; pid = fork(); // 创建一个子进程 if (pid < 0) { // 出错 fprintf(stderr, "fork failed\n"); exit(-1); } else if (pid == 0) { // 子进程 execlp("/bin/ls", "ls", NULL); } else { wait(NULL); // 父进程等待子进程结束 printf("Child process complete\n"); exit(0); } return 0; }父进程空间fork()返回的是子进程的PID号。
子进程空间fork()返回的是0
进程的分类
系统进程:操作系统为管理一些资源而设定的进程,特点是优先级比较高,相对于用户进程优先被调度 用户进程 前台进程:用户打交道的进程 后台进程:操作系统初始化后设定的进程,在后台为客户提供服务 CPU密集型进程:需要大量计算的进程,如:游戏、画面渲染等 I/O密集型进程:经常需要输入输出、读盘等操作进程层次结构
Unix进程家族树:init为根 4.2 进程与程序的区别进程更能准确刻画并发,而程序不能
程序是静态的,进程是动态的
进程有生命周期,有诞生有消亡,是短暂的;而程序是相对长久的
一个程序可对应多个进程
进程具有创建其他进程的功能,而程序没有
操作系统给每个进程都分配了一个地址空间
每个进程有自己独立的地址空间,不同的地址空间的地址是虚拟地址
对进程执行活动全过程的静态描述:
由进程地址空间内容、硬件寄存器内容及与该进程相关的内核数据结构、内核栈组成。