一、系统调用fork函数
1、fork返回值及内核操作
2、fork前后区别
3、为什么返回值pid_t id的变量可以存储多个值--写时拷贝
对于代码段,页表中直接标识只读属性,不能修改。
对于数据段,子进程继承时,OS默认先改为只读(暂时)
父子进程先共享数据区,当子进程要进行w时,触发了页表的权限问题(能否写入)
此时页表不触发异常处理机制,反而重新映射物理地址,进行写时拷贝。(同时去掉只读属性)
谁先写入谁就触发权限问题,谁进行写时拷贝。
一个问题:为什么代码段会触发异常处理,数据段不会,反而OS进行写时拷贝?(底层如何区分? )
二、进程终止
循环创建10个子进程,执行runChild后exit退出
为了防止子进程变成孤儿进程,循环创建后让父进程sleep(20)
循环创建5个进程,然后都进入S(sleep)浅度睡眠状态
然后5个子进程退出,但此时父进程仍为S,没有回收子进程,于是子进程变为Z僵尸状态
然后父进程退出,子进程被OS回收。
1、进程退出场景
![](https://i-blog.csdnimg.cn/blog_migrate/42da45ff8889c5a5d807726da0073eb8.png)
2、strerror将错误码转换为错误信息描述(父进程接收返回值)
循环打印退出码及对应的退出信息(部分)
一个例子:
3、C语言的全局变量errno(库函数和系统调用)
errno是库函数和系统调用错误时进行修改的全局变量,当出现错误(非异常退出)时,将返回值修改为对应的错误码,可以让父进程得到错误退出信息,统一了父进程和库函数/系统调用。
修改完ret后,可以直接exit(ret)。
4、关于异常退出
异常退出时就不关心退出码了。
进程退出场景:1、先看是否出异常。 2、看退出码-->是否正确退出
异常退出是通过发送信号来完成的
进程出现异常:本质是收到了信号
模拟除0错误。
5、怎样进行进程退出?(方法)
1、exit
return只表示退出当前函数(在main函数return时表示进程退出),例如在exit前直接return,最后进程的退出码仍为1
2、_exit
3、对比
加\n时会立即刷新缓冲区,不加时printf的内容不会打印到屏幕上。
使用exit退出,会刷新缓冲区,显示内容。
使用_exit退出,进程会直接终止,不刷新缓冲区。
![](https://i-blog.csdnimg.cn/blog_migrate/d9d482fc86470e6283bbb6cc40204f11.png)