Linux

您所在的位置:网站首页 exit在linux的用法 Linux

Linux

2023-05-23 21:05| 来源: 网络整理| 查看: 265

再谈fork()

1.png

进程调用fork,当控制转移到内核中的fork代码后,内核做:

分配新的内存块和内核数据结构给子进程

将父进程部分数据结构内容拷贝至子进程

添加子进程到系统进程列表当中

fork返回(当return的时候),开始调度器调度

创建子进程,给子进程分配对应的内核结构,这个结构必须子进程自己独有,因为具有独立性,理论上子进程也要有自己的代码和数据,可是一般而言,我们没有加载的过程,也就是说子进程没有自己的代码和数据。所以,子进程只能使用父进程的代码和数据

代码:都是不可被写的,只能读取,父子共享没问题

数据:可能被修改,所以,必须分离。

对于数据而言创建进程的时候,就直接拷贝分,这种情况可能会拷贝一些不会用到的空间,即使用到了,也只能读取

2.png3.png

编译器编译程序的时候,尚且知道节省空间。创建子进程,不需要将不会被访问的,或者只会读取的数据,拷贝一份。将来被父或子进程写入得数据会被拷贝。一般而言即便是OS,也无法提前知道哪些空间可能会被写入。所以操作系统选择了,写时拷贝技术,将父子进程的数据分离。

4.png

fork之后代码共享,共享的是所有的代码

我们的代码汇编之后,会有很多行代码,而且每行代码加载到内存之后,都有对应的地址

当进程没执行完时候,可能被切换,下次回来,还会从之前切换的位置继续运行,所以CPU要记住这个位置,CPU中有对应的寄存器数据来记录这个当前位置

5.png

pc指针存的是当前正在执行代码的下一行代码的地址,寄存器在CPU内只有一份,但寄存器内的数据(进程的上下文数据)可以有多份

父子进程可以各自调度上下文数据,各自会修改EIP,但是已经不重要了,子进程认为自己的EIP起始值,就是fork之后的代码,子进程从after开始跑,不代表fork之前的代码它看不到

fork常规用法和调用失败原因

一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。

一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数

系统中有太多的进程

实际用户的进程数超过了限制

进程终止

1. 进程终止,操作系统都做了什么?

释放进程申请的相关内核数据结构和对应的数据和代码,本质就是释放系统资源

2.进程终止常见的方式有哪些?

a.代码跑完,结果正确           b.代码跑完,结果不正确          c.代码没有跑完,程序崩溃了(下面例子)

6.png

程序崩溃

7.png

main函数返回值

main函数的返回值并不总是0,return 后面跟的数字是进程退出码,进程退出码表示进程是否正确返回,如果返回0则运行结果正确,如果非0,则结果不正确

查看退出码:echo $?

8.png

我们把进程退出码修改为10,第一次查看退出码结果是10,之后查看结果就会是0,这是因为echo $?获取的是最近一个进程执行完毕后的退出码

main函数返回值的意义,返回给上一级进程(如父进程),用来评判该进程执行结果用的,可以忽略。

我们可以通过退出码判断出运行错误的原因,不同的退出码代表着不同的出错信息

strerror可把一个整数转换成字符串

9.png

查看退出码

10.png

我们可以看到0代表成功

11.png12.png

我们可以自己使用这些退出码和含义,我们也可以自己定义退出码和推出含义,如return 10,我们可认为10是File exists

程序崩溃的时候,退出码无意义,一般而言程序还没执行到return就会崩溃,只有main函数里的return是进程退出,其它函数return起返回作用

exit和_exit 相同点

exit

13.png

_exit

14.png

测试exit

15.png

退出码 111,说明exit在代码的任何地方调用都是直接终止进程

16.png

测试_eixt

17.png

说明exit和_exit共同之处,一执行就退出

18.png

不同点

19.png

正常运行

20.png

去掉\n,由于没了\n,就无法刷新缓冲区,也就是说要打印的内容此时存在了输出缓冲区当中,但exit此时也正常运行

21.png

我们换成_exit

22.png

此时没有打印出来,也就是_exit不会刷新缓冲区

23.png

加上\n之后,正常运行

24.png

总结

25.png

exit最后也会调用_exit, 但在调用_exit之前,还做了其他工作

1. 执行用户通过 atexit或on_exit定义的清理函数。

2. 关闭所有打开的流,所有的缓存数据均被写入

3. 调用_exit

26.png

printf不加\n数据保存在“缓冲区”当中,这个缓冲区一定不在操作系统内部,如果是操作系统维护的,缓冲区_eixt也能刷新,该缓冲区只能在库函数,如C标准库



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3