Linux进程控制/进程终止

一、系统调用fork函数

1、fork返回值及内核操作

#include
pid_t fork(void);
返回值:自进程中返回 0 ,父进程返回子进程 id ,出错返回 -1
进程调用fork,当控制转移到内核中的fork代码后,内核做:
1、分配新的内存块和内核数据结构给子进程
2、将父进程部分数据结构内容拷贝至子进程
3、添加子进程到系统进程列表当中
4、fork返回,开始调度器调度

2、fork前后区别

Linux进程控制/进程终止_第1张图片Linux进程控制/进程终止_第2张图片

3、为什么返回值pid_t id的变量可以存储多个值--写时拷贝

Linux进程控制/进程终止_第3张图片

对于代码段,页表中直接标识只读属性,不能修改。

对于数据段,子进程继承时,OS默认先改为只读(暂时)

父子进程先共享数据区,当子进程要进行w时,触发了页表的权限问题(能否写入)

此时页表不触发异常处理机制,反而重新映射物理地址,进行写时拷贝。(同时去掉只读属性)

谁先写入谁就触发权限问题,谁进行写时拷贝。

一个问题:为什么代码段会触发异常处理,数据段不会,反而OS进行写时拷贝?(底层如何区分? )

二、进程终止

循环创建10个子进程,执行runChild后exit退出

Linux进程控制/进程终止_第4张图片

为了防止子进程变成孤儿进程,循环创建后让父进程sleep(20)

Linux进程控制/进程终止_第5张图片

循环创建5个进程,然后都进入S(sleep)浅度睡眠状态

然后5个子进程退出,但此时父进程仍为S,没有回收子进程,于是子进程变为Z僵尸状态

然后父进程退出,子进程被OS回收。

1、进程退出场景

1、代码运行完毕,结果正确
2、代码运行完毕,结果不正确
3、代码异常终止
1、main函数的退出码,return 0代表运行完毕且结果正确。(成功只有一个退出码)
这里的0会被上一层父进程拿到,即创建main函数进程的 bash拿到。
2、结果不正确有多种退出码,return 1,2,3... 来表征 不同的出错原因
Linux进程控制/进程终止_第6张图片
$?  查看?中存的内容, 最近一次进程退出的退出码
再次查看,结果为0,因为最近一次命令变为echo了

2、strerror将错误码转换为错误信息描述(父进程接收返回值)

Linux进程控制/进程终止_第7张图片

Linux进程控制/进程终止_第8张图片

循环打印退出码及对应的退出信息(部分)

Linux进程控制/进程终止_第9张图片

一个例子:

Linux进程控制/进程终止_第10张图片

3、C语言的全局变量errno(库函数和系统调用)

Linux进程控制/进程终止_第11张图片

Linux进程控制/进程终止_第12张图片

errno是库函数和系统调用错误时进行修改的全局变量,当出现错误(非异常退出)时,将返回值修改为对应的错误码,可以让父进程得到错误退出信息,统一了父进程和库函数/系统调用。

Linux进程控制/进程终止_第13张图片

修改完ret后,可以直接exit(ret)。

4、关于异常退出

异常退出时就不关心退出码了。

进程退出场景:1、先看是否出异常。 2、看退出码-->是否正确退出

异常退出是通过发送信号来完成的

进程出现异常:本质是收到了信号

Linux进程控制/进程终止_第14张图片模拟除0错误。

5、怎样进行进程退出?(方法)

1. main返回
2. 调用exit
3. _exit

1、exit

Linux进程控制/进程终止_第15张图片

return只表示退出当前函数(在main函数return时表示进程退出),例如在exit前直接return,最后进程的退出码仍为1

2、_exit

Linux进程控制/进程终止_第16张图片

3、对比

Linux进程控制/进程终止_第17张图片

加\n时会立即刷新缓冲区,不加时printf的内容不会打印到屏幕上。

使用exit退出,会刷新缓冲区,显示内容。

使用_exit退出,进程会直接终止,不刷新缓冲区。

Linux进程控制/进程终止_第18张图片

Linux进程控制/进程终止_第19张图片

你可能感兴趣的:(Linux,is,not,unix,--,系统,linux,运维,服务器)