Linux->进程终止和等待
创始人
2024-05-27 13:08:31
0

目录

1. 进程终止场景

1.1 进程退出码

1.2 进程常见退出方式

 2. 进程等待

2.1 进程等待的必要性

2.2 进程等待的方式

wait()方式

waitpid()方式

options参数

status参数


1. 进程终止场景

代码运行完毕,结果正确
代码运行完毕,结果不正确
代码异常终止

         进程终止也就是我们通常理解的进程退出了,但是我们又怎样理解上面的三句话呢?什么叫做代码运行完毕结果正确或者不正确?难道是我们每一次都需要自己去调试?有或则是每一个都需要通过IO接口,将程序结果调试出来然后在判断程序是否正确?答案很明显不是的,往下将会给你结果。

1.1 进程退出码

        首先,咱们得明白一个概念,判断是一个代码运行完毕结果是否正确,肯定不会是我们之前所想的那样,将程序以printf、cout或者调试的方法用认为的方式判断是否正确,因为对于计算机而言,我们判断是否正确根本没有意义,因为它的运行速度太快了,如果有其它进程需要这个进程的退出信息,难道它会等我们告知一个答案吗?不会的。所以编程语言出现了——进程退出码

        大家第一次看到进程退出码可能会认为这是一个很厉害,很牛逼的东西,其实不是,我们平时练习C语言和C++时都有用到它,只是大伙不知道到底是干嘛的罢了。如下:

 int main()
 {
      return 0;                                                                                                                  
 } 

        上方代码的0就是进程退出码之一,表示程序正确执行,是否感到了一丝丝无语伙伴们,是不是以为是什么呢?哈哈。不过无语归无语,这个知识点却是很多知识点的桥梁,还是得认真了解的。

        0表示程序执行完了结果正确,其余数字都表示结果不正确,为什么?就因为C语言规定了?这玩意你不说谁会懂?我举一个例子:

        假如你和你女朋友说话,你女朋友问你“你爱不爱我”,你说“0”,然后你女朋友就觉得莫名其妙,然后再问你“你是不是有病?我问你话呢”,然后你又回了“3”,你女朋友气不过,她认为你在耍她,最后就气跑了。你冤不冤枉,你有好好回答哇,只是她不懂哇。

        上面这个故事就表明了,我不管你是啥,我问你东西,你就必须得用我知道的方式来回答,否则我生气,然后把你踢了。所以对于计算机而言,我们就是这个女朋友,他需要用我们知道的方式来回答,所以string.h库中有一个strerror函数,可以将我们的进程退出码的信息以文字方式表示出来。如下:

  1 #include  2 #include  3 #include  4 #include  5 #include  6 7 int main()8 {9   int i = 0;10   for(i = 0;i<130;++i)11   {12     printf("我的进程退出码是:%d,退出信息是:%s\n",i,strerror(i));13   }14 15   return 0;16 }

         上述为进程退出码的部分信息,可以看到0的退出信息是Success,我没骗人吧。我相信大家好好看一下是能看出某些信息自己在写Linux时是看到过的,比如说退出码2,退出码13。我以退出码为例,如下:

         看到了没?知识串起来了,以前只是听过Linux是用C语言写的,但是不知道是怎么写的,但是这里有没有感觉?

1.2 进程常见退出方式

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

         进程退出从main返回的意思就是通过return返回,注意,只有main函数的返回值才被称为进程退出,其它函数的return只是表示这个函数的功能结束了,并带回了一个返回值,接收到这个返回值的地方依旧是这个进程。

        而我们的exit和_exit函数则没有这个限制了,它们能够在任意函数结束进程,使用方法如下:

exit("退出码");

_exit("退出码");

        这样看起来,好像exit函数和_exit函数没有什么区别呢? 

        在大多数情况下,这两个函数并没有什么区别,但是还是有一定的区别的,请先看下图:

         区别就是_exit是一个系统接口,而exit是stdio.h库提供的一个库函数,并且exit函数内部调用的_exit函数,且exit函数调用没有_exit函数暴力,它会先将前面执行的代码运行完了才结束进程,而_exit会直接退出进程,不管缓冲区的数据等。

 int main()                                                                                                        
 {
      printf("hello world");
      exit(0);                                                                                                                                   }   

int main()

{

        printf("hello world");
        _exit(0);     
}

 exit();运行结果:

 _exit()运行结果:

 2. 进程等待

        进程等待一般出现在父子进程之间,父进程等待子进程运行完毕,父进程在执行自己的代码。一般是在网络通信连接时有用。

2.1 进程等待的必要性

1. 子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
2. 另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。
3. 最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。
4. 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

         上述的概念已经为我们清晰的解释了进程等待的必要性,关于僵尸进程就是子进程退出,但是父进程没有对它的资源做回收,也就是获取进程退出信息,那么子进程的进程状态就会变为Z,并且一直保持这个状态,没有谁能干掉它,它就一直占用系统资源。

2.2 进程等待的方式

wait()方式

        wait()是一个在sys/wait.h库里面的函数,函数声明为:

pid_t wait(int*status);

         返回值正确为被等待进程pid,不正确为-1,status参数为输出型参数,当我们不关心子进程的退出状态,那么就可以将其设置能为NULL。如下:

代码:

  1 #include2 #include3 #include4 #include5 #include6 7 void test1()8 {9   int cnt = 5;10   while(1)11   {12     printf("我是子进程,我还能活%dS\n",cnt);13     sleep(1);14     --cnt;15     if(cnt == 0)16       exit(110);17   }18 }19 20 21 int main()22 {23   pid_t id = fork();24   if(id == 0)25   {                                                                                                                          26     test1();27   }28   pid_t subid = wait(NULL);29   printf("我是父进程,我等待子进程%d完毕\n",subid);30 31   return 0;32 }

结果:

         从代码中能够看到父进程的printf语句在子进程被执行完毕之后才执行了,也就表示父进程使用wait函数之后确实处于等待状态,也回收了子进程的信息,因为wait返回了正确的pid。

waitpid()方式

        waitpid()是在sys/types.h库和sys/wait.h库中的函数,声明为:

pid_t waitpid(pid_t pid, int *status, int options);

返回值:
当正常返回的时候waitpid返回收集到的子进程的进程ID;
如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
pid:
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真(查看进程是否是正常退出)
WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

        该函数的使用方式和wait函数基本一致,但是它的参数options、和两个函数都有的status输出型参数我需要为大家讲解一下。

options参数

        当我们将其输入为0时,此时函数的功能就是进程等待模式,也就是上述图中的模式,但是如果我们将其输入为WNOHANG,那么函数的功能就会变为轮询式等待,什么意思呢,先看代码:

    1 #include2 #include3 #include4 #include5 #include6 7 void test1()8 {9   int cnt = 5;10   while(1)11   {12       printf("我是子进程,我还能活%dS\n",cnt);13     sleep(1);14     --cnt;15     if(cnt == 0)16       exit(110);17   }18 }19 20 21 int main()22 {23   pid_t id = fork();24   if(id == 0)25   {                                                                                                                        26     test1();27   }28   int status = 0;29   pid_t subid = waitpid(id,&status,WNOHANG);30   printf("我是父进程,我不想等子进程了,先运行了,之后在回收资源\n");31   return 0;32 }

         上图中可以看出,我们通过WNOHANG参数,父进程就没有等到子进程执行完了再执行代码,而是先运行着自己的代码,子进程自己跑。我将一个故事,大家大概就能懂了。

        小明和小芳是一对好朋友,一天小明想要邀请小芳一起出去玩,然后呢,他就打电话给小芳问她现在能不能出去?小芳说:等等我,我在洗澡呢,小明说:好,我等你,电话别挂。然后电话就一直打着,15分钟后,小芳说:我好了。然后挂断了电话,小明和小芳就一起出去了。——————进程等待

         还是小明和小芳,同样小明想要邀请小芳出去玩,小芳也还在洗澡,小明打电话问:还在洗吗?小芳说:嗯。然后电话挂了,小明洗了个脸,大概一分钟又问:还在洗?小芳说:嗯。如此循环,直到小芳说出洗完了,才不会继续打电话问了。——————轮询式等待

         上述的两个故事就对应了我们进程的等待方式。小明就是父进程、小芳就是子进程。

status参数

         什么叫做输出型参数呢?输出型参数就是指,我们只需要传一个地址进入就行,然后其它函数拿到这一个空间,对其进行数值修改,在原函数就能拿到这个值了。

        status是一个整型变量,他也是一个位图,意思就是他用一个变量存了进程退出码和异常信息的值,它的高16位没有被使用,次高8位用于存进程退出码,低7位用于存异常信息,还有第8位用于存core dump信息。如下:

printf("我是父进程,子进程的退出码为%d,异常信息为%d\n",(status>>8)&0xFF,status&0x7F);  

        该方式就是我们的位图,使用方式就是位运算。 

        值得一提的是,当子进程有一个错误,那么就不会有退出码,也就是说——程序无异常->程序执行是否正确

n /= 0;   错误语句

         程序崩溃,子进程没有成功运行,退出码为0,异常信息为8。


        以上就是我对进程终止和进程等待的全部理解了,还请大家多多支持哇,谢谢。

相关内容

热门资讯

社会能见度-初一-议论文(精... 社会能见度-初一-议论文 篇一社会能见度,是指一个人在社会中被他人所关注和认可的程度。在人们的成长过...
月亮升起来时初中作文【实用6... 月亮升起来时初中作文 篇一月亮升起来时初中作文当夜幕降临,星星点点的光芒开始闪烁,而其中最亮的是那皎...
低到尘埃的美好作文【精彩3篇... 低到尘埃的美好作文 篇一夏日的午后,阳光透过树叶的缝隙洒在地面上,形成斑驳的光斑。我慵懒地躺在草地上...
菜园小记初一作文【精彩3篇】 菜园小记初一作文 篇一菜园小记春天,是一个万物复苏的季节。初一的时候,我开始在家的菜园里种植各种蔬菜...
买飞轮斗士记初一作文【精简3... 买飞轮斗士记初一作文 篇一买飞轮斗士记初一作文我是一个初一的学生,最近我买了一本名叫《飞轮斗士记》的...
初中生作文(优质6篇) 初中生作文 篇一:我的暑假计划暑假即将来临,我已经迫不及待地开始计划怎样度过这个难得的假期了。今年的...
雨后初一作文800字通用13... 雨后初一作文800字 第一篇平日里的小城总是“死气沉沉”,没有一丝的活力,但是在一场小雨的装饰下,平...
今夜难眠【实用5篇】 今夜难眠 篇一今夜难眠,心里充满了烦躁和不安。躺在床上,一遍又一遍地翻来覆去,无法入眠。或许是生活的...
一粥一饭当思来之不易初中作文... 一粥一饭当思来之不易初中作文 篇一粮食是人类赖以生存的基本生活资源,而一粥一饭则是构成粮食的最基本单...
我的愿望小学生作文500字(... 篇一:我的愿望我的愿望小学生作文500字 篇一我是一个小学生,生活在一个美丽的世界里。我有很多愿望,...
秋天的作文600字初中(精简... 秋天的作文600字初中 篇一秋天的美丽秋天是一年四季中最美丽的季节之一。当秋天来临,大自然开始变得五...
努力的作文素材(优质5篇) 努力的作文素材 篇一第一篇内容在我们的生活中,努力是一种非常重要的品质。努力可以帮助我们实现目标,克...
印象武隆初一作文【优秀5篇】 印象武隆初一作文 篇一初一暑假期间,我有幸和家人一起来到了美丽的武隆。这个小县城位于重庆,以其壮丽的...
七年级新生第一次作文800字... 篇一:我的初中生活七年级新生第一次作文800字 篇一初中生活即将开始,我感到既兴奋又紧张。我将开始进...
初一优秀作文一切都不会过去(... 初一优秀作文一切都不会过去 篇一一切都不会过去时间总是在不停地流逝,无论是快乐还是痛苦,都会成为过去...
借物喻理初中作文(经典6篇) 借物喻理初中作文 篇一《蚂蚁与草hopper的故事》在一个美丽的小村庄里,住着一只懒散的草hoppe...
我的家初一作文800字【经典... 我的家初一作文800字 篇一我们家是一个温馨而幸福的小家庭。爸爸是一个高大而慈祥的人,他是家里的顶梁...
照亮作文600字【优选5篇】 照亮作文600字 篇一照亮作文现代社会,写作已经成为了我们生活中不可或缺的一部分。无论是在学校还是在...
办好G20做好东道主初一作文... 办好G20做好东道主初一作文 篇一G20峰会是全球最重要的经济论坛之一,举办这一峰会对于中国来说是一...
团结的力量初一作文(经典5篇... 团结的力量初一作文 篇一团结的力量团结的力量是一种强大的力量,它能够将不同的个体聚集在一起,从而共同...