学习系统编程No.7【进程替换】

这篇具有很好参考价值的文章主要介绍了学习系统编程No.7【进程替换】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言:

北京时间:2023/3/21/7:17,这篇博客本来昨天晚上就能开始写的,但是由于笔试强训的原因,导致时间用在了做题上,通过快2个小时的垂死挣扎,我充分意识到了自己做题能力的缺陷和运用新知识的缺陷,所以我需要把重心给转移一下了,以后做题才是我的头号目标,虽然我在很久以前可能就说过这样的话,但是这次我是认真的,就算我做题不行,但是我看代码还是行的,所以我每天必看一些做题代码,来加深自己对知识的运用,希望不久之后,能有所进步吧!哪怕只是一丝丝!所以今天我们就来学习上篇博客剩下的有关进程控制的内容,和有关进程程序替换的知识吧!

pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux

复习进程等待

昨天已经浅浅的了解了什么是进程等待,进程等待的目的就是为了终止僵尸进程,回收僵尸进程所占的资源,并且获得进程的退出码和退出信号,并且我们了解了进行进程等待的两个接口函数wait/waitpid,通过这两个接口,我们就可以去调用操作系统提供给我们的系统调用,这样就可以利用系统调用的形式来完成进程等待了;我们昨天已经知道使用wait接口就是用来等待一个进程的子进程,并且有代码演示,这里不多做理解,昨天我们也了解了waitpid这个接口,发现该接口有三个参数,并且其中第一个参数pid,它的作用和wait的参数差不多,本质就是为了等待一个进程,pid=0等待的是该进程的子进程,pid>0,等待的则是任意一个pid相等的进程,和第二个参数status,我们了解到,该参数是一个位图结构的参数,不单单是整形类型,本质为位图结构就是为了可以同时从一个参数上获取退出码和退出信号两个码值,第三个参数options,就是用于判断子进程是否正常终止,父进程是否继续等待的问题,所以接下来,我们就承接这上篇博客,把剩下的有关位图结构,也就是有关status参数的知识再深入学习一下,如下:

继续谈status

上篇博客,我们了解到status是一个位图结构,可以同时返回退出码和退出信号,并且退出码是由32个比特位中的后16个比特位中的次第8位构成的,退出信号是由最后7个比特位构成的(core down先不谈),所以按照这个逻辑,此时我们想要拿到,status中的退出信号和退出码是有办法的,没错,就是使用我们在C语言中所学的位运算的概念,具体这里不多做讲解(具体就是左移和右移),左移以为表示的就是该值乘2,右移一位表示的就是除2,并且还涉及到了按位或、按位与、按位异或的知识,如下图:
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux

通过上述的 (status >> 8)& 0xFF、status & 0x7F 此时我们就可以获得该进程的退出码和退出信号了,但是要知道,上述获取子进程退出码和退出信号的方式,是我们自己通过位图结构的概念,通过位运算获得的,但是注意,在Linux操作系统内部,它本身是为我们提供了获取子进程退出码和退出信号的方式,如下图:
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux

所以按照我们上述所说,父进程就可以通过使用waitpid接口,来调用系统调用,从而获取子进程的退出码和退出信号,但是具体在调用系统调用接口的时候,本质上这些工作还是由我们的操作系统来完成了,因为只有操作系统才有获取进程退出码和退出信号的资格,所以此时就有一个问题,就是父进程具体是如何通过操作系统来获取子进程的退出码和退出信号呢?

首先明白,无论是父进程还是子进程,它们都是一个独立的进程,所以每个进程都拥有自己的地址空间,进程pcb、页表和物理内存等资源;并且明白,子进程pcb内不仅有从父进程pcb中继承的相关属性,而且还有两个和子进程退出码和退出信号至关重要的属性 (int exit_code ,int exit_signal) ,从该属性的名字就可以看出,这两个子进程pcb属性代表的就是进程退出码和退出信号,表示的仅仅就是两个整数而已;
明白了这些之后,此时就可以回答该问题了,如下:
当子进程执行完毕之时,操作系统会将main函数对应的返回值写到该进程pcb的int exit_code当中,如果该进程异常,则将对应的退出信号写到该进程pcb的int exit_signal当中,并且最后在进程退出之后,操作系统会将该进程的pcb维护起来,所以当该子进程pcb被操作系统维护起来之后,此时父进程就可以通过调用系统接口 wait/waitpid 通过操作系统来去找到该退出进程对应的进程pcb,可以找到子进程pcb的具体原理是因为,父进程在调用waitpid接口的时候,已经把子进程的pid告诉了父进程(也就是传参的时候已经把进程子pid给给了waitpid接口),所以最后通过子进程pid,进而找到该子进程的pcb,进而找到pcb中的该子进程的退出码 int exit_code 和退出信号 int exit_signal,最后再利用waitpid中的第二个参数status(输出型参数)将退出码和退出信号返回给父进程(当然也就是上述的ret_id变量)

总:父进程获取子进程的退出码和退出信号的本质就是通过操作系统读取子进程的内核数据结构(pcb)

并且有的同学非常的好奇,就是有没有一种可能,就是父进程在等待的时候,子进程一直没有退出呢?或者说父进程在等待的时候具体是在干什么呢?

所以此时我们就借着上述问题来谈一谈,什么是阻塞等待和非阻塞轮询等待

首先我们要明白,当子进程没有退出的时候,父进程在干什么呢?
谈到这个,此时又不得不谈谈waitpid的第三个参数,options,上篇博客我们说了,这个参数的作用就是用于判断子进程是否正常终止,父进程是否继续等待问题,并且该参数我们默认给给的是一个叫 WNOHANG 的参数,具体意思:就是用于判断该子进程是否终止,如果该子进程未终止,那么此时waitpid()函数就返回0,如果该子进程终止,则返回该子进程的pid,此时就可以很好的通过这第三个参数来判断一个进程的子进程是否处于终止状态,所以明白了这点,此时就可以明白父进程是可以通过该参数来控制自己的行为,也就是上述所说的阻塞等待和非阻塞轮询等待!

谈谈父进程的阻塞等待

从上述的知识,我们可以知道,如果waitpid()函数返回0,表示的就是该子进程没有结束,子进程没有结束,那么父进程此时可以干什么呢?首先第一种情况,父进程一直在调用waitpid进行等待 ,此时的一直进行等待,本质上表示的就是阻塞等待,也就是表示父进程此时从本来的正常运行状态变成了一个阻塞状态,变成了一个等待子进程的状态;所以我们可以明白,当父进程处于阻塞状态之时,父进程是不在CPU的运行队列之中,而是在某一个阻塞队列之中;并且此时再深入理解,还可以明白,父进程处于阻塞等待之时,子进程处于运行状态,那么等子进程执行完之后呢?父进程如何从阻塞状态重新变成运行状态来为子进程收尸呢? 谈到这个问题,此时就又涉及到了,子进程的进程pcb,在子进程pcb内部,我们可以理解存在一个指向父进程的指针,所以当子进程一但退出(注意此时父进程肯定是不在运行队列,而是在阻塞队列的),此时子进程就可以利用pcb中指向父进程的指针,重新找到父进程(唤醒),此时父进程检测到之后(被唤醒),就又会从阻塞状态变成运行状态,然后被操作系统又重新链接到运行队列之中,最后父进程继续执行 wait/waitpid,最终就将子进程给回收

所以上述就是父进程阻塞等待全过程

谈谈父进程的非阻塞轮询等待

搞懂了上述父进程的阻塞等待,此时就可以明白父进程肯定还有一种非阻塞等待(毕竟我是父进程,你是小子,我才是老子,我凭什么一定要等你呢?)所以,此时还是同理,当我们通过waitpid()函数的返回值,判断出该子进程还没有结束时,我们就可以让父进程不需要一直进行等待(不需要一直处于阻塞状态),具体代码如下:
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux
所以此时通过上述的代码,我们就可以很好的理解什么是父进程的阻塞等待和非阻塞轮询等待了,并且可以将其很好的抽象成一个生活中场景,如下:

场景一:
周末出去玩,李四打电话给张三,问张三去不去,此时张三说去,但是要准备一下(子进程未终止),李四说好,我等你(父进程等待),但是电话别挂(阻塞等待
场景二:
如法炮制,还是周末出去玩,李四打电话给张三,问张三去不去,张三还是去,并且也还是需要准备一下,此时李四还是说好,但是此时李四却把电话给挂断了,在电话挂断之后,李四想了想也去准备了一下,过了一会之后,李四准备的差不多了,就又打电话给张三,张三却还是没有准备好,此时李四就又把电话挂了,又去准备东西了,同理,李四一直打电话问张三好了没有(非阻塞轮询等待),而张三却一直没好,直到最后好了(子进程终止)

所以上述的两种情况(李四给张三打电话,表示的就是父进程使用waitpid()等待子进程,)第一种情况电话不挂表示的就是父进程处于阻塞队列,这种情况也就是阻塞调用;第二种情况,表示我打完电话,问完情况,我们把电话挂掉,此时表示的就是父进程不处于阻塞等待,也就是表示该调用,此时是属于非阻塞调用,(非阻塞调用的好处,就是父进程可以干自己想干的事情,例:准备自己的东西)

所以上述的两种场景就是父进程阻塞等待和非阻塞等待的两个现实生活抽象场景,可以非常好的凸显出父进程等待的两种情况

总:父进程可以通过参数进行判断,然后来控制自己的行为,也就是上述所说的阻塞等待和非阻塞轮询等待!

总结:进程控制的三个话题:进程创建、进程等待、进程终止此时就算告一段落啦!现在让我们呢一起开始新知识的学习吧!

进程替换

搞定了上述的知识,此时我们就进入今天的正菜,什么是进程替换,在弄懂什么是进程替换之前,我们引入一个问题,就是为什么要创建子进程?所以我们要明白,我们创建子进程的目的:就是为了让子进程帮我执行某些特定的任务,但是此时让子进程去执行某些代码的时候,就会出现如下两种情况:

1. 让子进程执行父进程的部分代码,也就是一个可执行文件中的部分代码(这些代码本质都是属于父进程)
2. 子进程想要执行一个全新的属于自己的代码(本质就是不想执行父进程的代码)

所以碰到上述第二种情况,此时就可以引出我们的新概念:进程程序替换

如下图:就是一个最简单的进程程序替换demo
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux
所以使用execl接口的本质就是进行进程的切换,让该可执行文件形成的进程去执行Linux操作系统中bin目录下的ls指令(ls可执行文件),也就是表明,当我们使用了进程替换函数时,我们可以在任意一个可执行文件中执行任意的指令,本质是进程替换

总:进程程序替换,就是让一个进程去执行另一个在磁盘(Linux操作系统下的bin目录)当中的程序(可执行文件),把一个新的程序运行起来

程序替换的原理

首先明白,创建一个进程,该进程肯定是有对应的pcb、页表、地址空间和物理内存,所以我们就从这些进程的必要条件入手,来看看进程替换到底是什么,如下图:
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux

从图中,我们可以了解到以下知识:
当前进程的代码等数据是需要通过页表映射到物理内存的特定区域,所以当一个进程执行了部分代码后,当其执行到了系统调用接口(execl等……),进程此时就会根据我所传入的程序的路径(Linux操作系统下的bin目录)和我要执行的程序的名称和选项(“ls” “a”),然后把磁盘当中(通过对应的路径找到bin)的其它的程序的代码和数据加载到内存,最后用新程序的代码来替换我们原程序中的代码,用新程序的数据来替换原程序中的数据(这个过程不是在地址空间完成的,是在物理内存中完成的);所以总的来说: 程序在替换时,就相当于原进程的内核数据结构不变,把原进程在物理内存中的代码和数据替换为新进程的代码和数据(从磁盘中加载),此时这个行为的发生就叫做程序替换

并且要明白,进程在进行程序替换的时候,是没有创建新的进程的,本质还是程序替换的本质。

并且此时明白,可以进行进程程序替换的接口一共有7个,此时我们已学其一,剩下的6个都是同理,只是在使用上不同而已,所以我们今天浅浅的摸了一下程序替换就行了(明天要晨跑),今天博客就这样吧!撤了!

补充小知识点:

fork函数的两个返回值浅显理解:一个是父进程返回子进程的pid,一个是子进程没有子进程所以返回0,感兴趣的同学,可以参看下面这个链接;为什么fork有两个返回值

北京时间:2023/3/21/22:45
pcb exit_signal什么意思,深入理解计算机系统,学习,网络,linux文章来源地址https://www.toymoban.com/news/detail-831581.html

总结:像程序替换(execl)这样的系统接口,等我们学到了文件操作和网络的时候,我们就经常会谈到,并且会用到更多,所以革命还未胜利,挑战任在继续,加油吧,少年!

到了这里,关于学习系统编程No.7【进程替换】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习系统编程No.24【深入学习信号】

    北京时间:2023/6/13/19:07,伴随着期末考的来临,最近停课啦!无论是线上课,还是学校的课,开心,那这不是咱持续更文的好时候嘛,但是今天在学习相关C++知识时,涉及到了线程相关知识,虽然能听,但是听起来就比较费劲,所以我们要先暂停C++相关知识的学习,转而投向

    2024年02月09日
    浏览(36)
  • 学习系统编程No.23【信号实战】

    北京时间:2023/4/23,最近学习状态不怎么好,总是犯困,没精力的感觉,可能是病没有好彻底的原因,也可能是我内心因为生病而认为摆烂理所应当,反正最后导致摆烂,课现在越来越跟不上了,并且刚刚蓝桥杯出成绩了,我肯定不是帮我自己看的,好奇看看而已,哈哈哈!

    2024年02月03日
    浏览(39)
  • Linux系统编程——进程间通信的学习

    学习参考博文: 进程间的五种通信方式介绍 Linux 信号介绍 Linux系统编程学习相关博文 Linux系统编程——文件编程的学习 Linux系统编程——进程的学习 Linux系统编程——线程的学习 Linux系统编程——网络编程的学习 常规学习Linux系统编程的内容是复杂且繁多的,不推荐刚开始

    2024年02月08日
    浏览(35)
  • 学习系统编程No.33【生产消费模型】

    北京时间:2023/7/22/14:27,现实和预期往往相差是巨大的,哈哈哈!白天睡不醒,晚上睡不着,就像一个夜猫子一样。熬夜耍手机,我真的是专业的,已经连续好久没有正常睡过觉了。怀念学校里的日子,每天都有人激励我早睡和早起,此处@谢xx,不知他最近的学习状态如何,

    2024年02月14日
    浏览(36)
  • 学习系统编程No.12【基础IO】

    北京时间:2023/3/28/7:19,周二,早八的一天,难过!终于进入C站周创作榜啦!开心!给大家推荐一首歌《盛夏的果实》,给我的感觉非常的放松,劳逸结合,音乐非它莫属,为了下周周榜可以继续前进, 今天我们就来学习一下基础IO的知识吧! 从上篇博客,我们明白,重定向

    2023年04月21日
    浏览(54)
  • 学习系统编程No.25【核心转储实战】

    北京时间:2023/6/16/8:39,实训课中,大一下学期最后有课的一天,还有两天就要期末考啦!目前什么都还没有复习,不到星期天晚上,咱不慌,小小挂科,岂能拦得住我补考,哈哈哈!小事,莫慌,该篇博客出炉之时,就是我复习之日,临阵磨枪不快也光,这方面我是专业的

    2024年02月11日
    浏览(44)
  • 学习系统编程No.32【线程互斥实战】

    北京时间:2023/7/19/15:22,昨天更新完博客,和舍友下了一会棋,快乐就是这么简单,哈哈哈!总体来说,摆烂程度得到一定的改善,想要达到以前的水准,需要一定的契机,毕竟人生在世,快乐最重要是吧!更文带给我的快乐已经没有那么多了,虽然欠了非常多的作业,非常

    2024年02月16日
    浏览(35)
  • 学习系统编程No.14【动静态库】

    北京时间:2023/4/3/7:06,刚刚晨跑回来,为了摆脱困意,刷了一下视屏,哈哈哈!我发现我每次刷视屏都是被迫的,都是看到某个感兴趣的标题,然后点进去一看,就不能自拔了,所以我下次得把消息提醒给全部关掉,烦人;并且全宿舍英文4级都报上了,就我没报上,真的是

    2023年04月09日
    浏览(49)
  • 学习系统编程No.17【vscode实战】

    北京时间:2023/4/11/7:25,昨天11点洗澡,洗完直接睡,导致现在头发愈发不能看,So,平头时刻将要来临,头发太长真的很不方便,昨天已经更文啦!这个星期一定要实现日更,因为我发现,不日更,或者说更文不积极,根本上不了热榜,所以今天又有新文章和大家见面哦!

    2023年04月14日
    浏览(81)
  • 学习系统编程No.26【信号处理实战】

    北京时间:2023/6/26/13:35,昨天12点左右睡觉,本以为能和在学校一样,7点左右起床,设置了7点到8点30时间段内的4个闹钟,可惜没想到啊,没醒,直接睡到了12点,看来下次不能给自己太高的期望,哈哈哈!在家没办法呀,习惯睡到12点了,想要解决这个问题,最好的方法就是

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包