【Linux】--- Linux中进程的创建与终止
一、进程的创建
1、fork函数重识
进程=内核数据结构(task_struct + mm_struct + 页表)+ 代码和数据
1、在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
2、关于fork的返回值:
#include<unistd.h>
pid_t fork(void);
//返回值:对于子进程中返回0,对于父进程就返回子进程的id,出错就返回-1
3、为什么父进程返回的是子进程的pid,子进程返回的是0?
为了便于父进程对子进程进行更好地管理!
2、写时拷贝
当子进程刚刚被创建时,子进程和父进程的数据和代码是共享的,即父子进程的代码和数据通过页表映射到物理内存的同一块空间。只有当父进程或子进程需要修改数据时,才将父进程的数据在内存当中拷贝一份,然后再进行修改。
这种在需要进行数据修改时再进行拷贝的技术,称为写时拷贝技术
1、为什么数据要进行写时拷贝?
因为进程之间都是具有独立性的,而且父子进程指向同一块物理内存的时候,其中任意一方进行修改的话,都会影响另外一个,所以必须要用写时拷贝!
2、为什么不在创建子进程的时候就进行数据的拷贝?
因为写时拷贝是针对于修改的一方的,如果子进程不进行数据修改,我就不需要对子进程来进行数据拷贝。这不就是纯纯的浪费空间吗?
3、代码会不会进行写时拷贝?
90%的情况下是不会的,但这并不代表代码不能进行写时拷贝,例如在进行进程替换的时候,则需要进行代码的写时拷贝
3、fork常规用法
1、一个进程希望复制自己,使子进程同时执行不同的代码段。例如父进程等待客户端请求,生成子进程来处理请求。
2、一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。
4、fork调用失败的原因
fork函数创建子进程也可能会失败,有以下两种情况:
1、系统中有太多的进程,内存空间不足,子进程创建失败。
2、实际用户的进程数超过了限制,子进程创建失败。
二、进程的终止
1、进程退出场景
1、代码运行完毕,结果正确。
2、代码运行完毕,结果不正确。
3、代码异常终止(进程崩溃)。
2、进程的退出码
我们都知道main函数是代码的入口,但实际上main函数只是用户级别代码的入口,main函数也是被其他函数调用的,是间接性被操作系统所调用的。
既然main函数是间接性被操作系统所调用的,那么当main函数调用结束后就应该给操作系统返回相应的退出信息,而这个所谓的退出信息就是以退出码的形式作为main函数的返回值返回,我们一般以0表示代码成功执行完毕,以非0表示代码执行过程中出现错误,这就是为什么我们都在main函数的最后返回0的原因。
我们可以使用echo $?命令查看最近一次进程退出的退出码信息。
这时便可以确定main函数是顺利执行完毕了。
因为代码执行成功只有一种情况,成功了就是成功了,而代码执行错误却有多种原因,例如内存空间不足、非法访问以及栈溢出等等,我们就可以用这些非0的数字分别表示代码执行错误的原因。
C语言当中的strerror函数可以通过错误码,获取该错误码在C语言当中对应的错误信息:
运行代码后我们就可以看到各个错误码所对应的错误信息:
实际上Linux中的ls、pwd等命令都是可执行程序,使用这些命令后我们也可以查看其对应的退出码。
可以看到,这些命令成功执行后,其退出码也是0。
但是命令执行错误后,其退出码就是非0的数字,该数字具体代表某一错误信息
注意: 退出码都有对应的字符串含义,帮助用户确认执行失败的原因,而这些退出码具体代表什么含义是人为规定的,不同环境下相同的退出码的字符串含义可能不同。
3、进程正常退出
1、return退出
在main函数中使用return退出进程是我们常用的方法。
例如,在main函数最后使用return退出进程。
2、exit函数
使用exit函数退出进程也是我们常用的方法,exit函数可以在代码中的任何地方退出进程,但是:exit函数在退出进程前会做一系列收尾工作:
(1)执行用户通过atexit或on_exit定义的清理函数。
(2)关闭所有打开的流,所有的缓存数据均被写入。
(3)调用_exit函数终止进程。
3、_exit函数
使用_exit函数退出进程的方法我们并不经常使用,_exit函数也可以在代码中的任何地方退出进程,但是_exit函数会直接终止进程,并不会在退出进程前会做任何收尾工作。
4、return、exit和_exit之间的区别与联系
(1)return 与exit的区别!!!
只有在main函数当中的return才能起到退出进程的作用,子函数当中return不能退出进程,而exit函数和_exit函数在代码中的任何地方使用都可以起到退出进程的作用。
(2)exit和_exit的区别:
- 使用exit函数退出进程前,会做一系列收尾工作:(执行用户定义的清理函数、冲刷缓冲,关闭流等操作),
- 而_exit函数直接终止进程!
原文地址:https://blog.csdn.net/weixin_75128035/article/details/145155372
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!