fork
创建子进程
- pid_t fork (void)
- 让进程在运行时调用fork创建一个新进程,该新进程称为子进程;
fork函数没有参数
对fork理解:
- 有一个程序,里面有一个fork函数,该程序运行后成为进程;
- 这个函数会告诉操作系统将这个进程所有的东西都拷贝一份(这是fork函数自己的功能);
并不是完全拷贝- 也就是去拷贝父进程的PCB(因为一个进程里的所有信息都在PCB中),这样就产生了一个新进程;
进程如何被运行(pcb可以放到其它结构中)
- Linux内核中存在一个运行队列,里面放的都是一个pcb,每个pcb指向自己的代码和数据
- 父子进程代码相同但是数据不同 。
- 子进程pcb创建好后,执行代码后并返回一个值
fork函数有两个返回值
创建失败 | 返回值小于0 |
---|---|
创建成功 | 返回值等于0,并返回给子进程 |
创建成功 | 返回值大于0,并返回给父进程,值为子进程的PID |
父子进程代码相同的原因:
- 这个新进程就是子进程,原进程称为父进程;
- 在代码部分父进程和子进程是一模一样的(因为在PCB中有一个变量叫内存指针,该指针指向了一块虚拟地址,在该地址组成之一就是代码段)
- 父子进程代码相同但是数据不同 。子进程pcb创建好后,执行代码返回一个值
子进程被父进程创建出来运行次序:
- 子进程被父进程创建出来后,在内核中是一个PCB,该PCB就会被挂在双向链接中组织起来;
- 父进程和子进程谁先运行不确定,取决于操作系统的调度(操作系统通过双向链表调度)
- 父子进程二者是抢占式执行
- 子进程被创建出来后,子进程的运行和父进程无关
- 子进程被创建出来后,从fork函数之后开始运行
为什么给父进程返回子进程pid,给子进程返回0
- 父进程必须有标识子进程的方案
- 子进程最重要的是要知道自己被创建成功了
子进程的父亲是唯一的,类似二叉树的父节点
fork为什么有两个返回值
- 如何做到:通过不同的返回值执行不同的代码
(重点)
- 父进程调用fork完毕后,在父进程的PCB中,
- 程序计数器保存了调用fork完毕后的下一条汇编指令;
- 上下文信息保存了调用fork完毕后的寄存器指令,
- 然后子进程拷贝了父进程的PCB后,会读取程序计数器和上下文信息中的内容
- 此时就指定了子程序应该从哪运行汇编指令
gitpid()函数 | 谁调用返回谁的进程号 |
---|---|
gitppid()函数 | 谁调返回谁的父进程的进程号 |
- Linux命令行叫命令行解释器,也是一个进程,大部分的命令行解释器叫bash,可以称为bash进程;
- 输入ls命令时(ls命令时一个可执行程序,运行起来就是一个进程),bash进程就会启动ls进程去完成相应的操作;
- 也就是说在命令行解释器中启动一个进程,该进程的父进程是bash。
僵尸进程:
指先于父进程退出的子进程程序已经不再运行
但是因为保存退出原因,因此资源没有完全释放的进程,因此不会自动退出释放资源
此时子进程的状态就变成僵尸状态(该子进程称为僵尸进程)
- 对于用户来说,这个子进程已经退出了,
- 对于操作系统而言操作系统内核还在维护着该子进程的PCB资源。
1.产生僵尸进程的原因:
- 子进程在退出的时候会向父进程发送一个信号
- 父进程忽略该信号
导致子进程在退出的时候没有进程来回收子进程的资源(PCB资源)
子进程变成了僵尸进程。
2.僵尸进程模拟:
- 在代码中创建一个子进程;
- 模拟让子进程先于父进程退出:通过fork函数让父子进程走不同的分支逻辑(子进程退出,父进程不退出);
3.僵尸进程的危害:
Kill +pid
Kill -9+pid:强杀命令
- 僵尸进程不能用上述两个命令结束;
- 造成内存泄漏
该进程的PCB并未释放,还存在于内存中,也就是不能从操作系统内核中释放该进程,使用强杀命令也不行。
4.解决方案:
- 重启操作系统;
- 进程等待;
- 将僵尸进程的父进程干掉变成孤儿进程变成Z状态的进程,可以称为僵尸进程,也可以说这种进程状态是僵尸状态
孤儿进程:
父进程创建一个子进程,父进程先于子进程退出,子进程就是孤儿进程
孤儿进程模拟:
- 子进程代码中写一个死循环
- 父进程直接退出
孤儿进程的父进程变成了1号进程,当子进程的父进程先退出,子进程会被1号进程所领养;孤儿进程被1号进程领养后,子进程就会变成后台进程
父进程没有变成Z的原因
- 父进程也有父进程,父进程的父进程是bash
- bash会自动回收它的子进程的PCB
- 如果给自己的子进程写回收代码,那么也会被bash回收
1号进程:
- 又称为init号进程,操作系统启动的第一个进程就是1号进程;
- 1号进程会fork出很多进程去完成操作系统内核的工作;
- 如果子进程父进程是1号进程,该子进程不一定是孤儿进程
在bash中执行一个程序(bash进程也有fork函数):
- bash会创建一个子进程去完成g_fork命令,(bash子进程中也有fork函数);
- g_fork代码中有fork函数再创建一个子进程(这个子进程相对于我们写的代码来说就是父进程);
- 然后原bash进程会被阻塞(这个子进程对于bash而言就是一个前台进程,从而阻塞bash)。
僵尸进程与孤儿进程:
Kill掉僵尸进程的父进程,该僵尸进程就会变成孤儿进程,被1号进程领养
1号进程会回收僵尸进程的PCB资源。
进程优先级
什么是优先级
优先级是进程获取资源的先后顺序
什么是权限
进程有没有获取资源的权限
为什么存在优先级
资源不够
查看优先级:ps -l
Linux下用priority+nice值确定
nice值进程优先级的修正数据(-20~19)
数字越小,优先级越高
更改进程优先级需要改nice,而不是pri
每次设置优先级前,优先级都先会被恢复成80
用top命令或者系统调用函数修改,系统不允许用户无节制设计
Linux共140个优先级
分时操作系统
实时操作系统