再谈写时拷贝
-
创建子进程操作系统做了什么?
答:进程PCB、创建维护进程的数据结构:进程控制块PCB、地址空间mm_struct、页表。创建进程也可能失败,因为空间不是无限的。此外,操作系统会去管理进程,防止恶意进程。
答:缺页中断:进程要写入,操作系统让别急,操作系统申请一片空间,修改页表:即修改页表映射关系,父子进程都不知道。
-
fork一般怎么用?
-
C/C++为什么main()写个0?
答:main()的renturn值是进程的退出码。 -
进程终止是什么?
答:把曾经申请的资源都释放。 -
进程退出的状态:
运行完毕结果正确、运行完毕结果不正确、异常终止。
退出码反映程序运行最终的情况。常用查看退出码:echo$?
退出码Linux上,我查看有133个,且会不断变,0是success、之后都是错误。 -
进程退出:
答:exit()在任意地方调用,都表示终止进程,参数是退出码。头文件是
阻塞的本质:进程的PCB被放入了等待队列,并将进程的状态改为PS状态。
返回的本质:进程PCB从等待队列拿到R队列,从而被CPU调度。
非阻塞等待的优点是可以一定程度提高CPU效率。
- 基于检测的轮训非阻塞等待,设置了NoHang后的waitpid三种情况:
答:waitpid返回值==0,waitpid等待成功,但是子进程还没退出,需要父进程重复进行等待。
waitpid>0,子进程退出了,waitpid也正常,返回值是获取到了想要的子进程pid。
waitpid<0,等待失败,典型原因是:可能不存在子进程,也可能选择等待的子进程pid错误。
进程替换
- 前言:fork之后父子代码共享,但是如果想让子进程不执行父进程代码而是去执行一个全新的程序呢?
-
什么是进程的程序替换?
答:进程不变,仅仅替换进程的代码和数据的技术,叫做进程程序替换。构建新的映射关系,把新的代码和数据加载到特定进程的上下文中。
将硬盘程序加载到内存,让指定进程去运行它。
【回忆】:文件 = 程序代码+程序数据 -
进程替换是把磁盘上的程序加载到内存上,如何加载?
答:exec()系列系统提供的函数,这类以exec()开头,共有6个。exec()可以理解为加载器。 -
对C/C++程序要运行,必须加载到内存中的理解:
答:蕴含两个意思,第一是程序要运行,先得变成进程,再是加载程序,如何加载?通过加载器,加载的底层原理是调用exec。 -
exec()如何使用?
答:exec(‘/dir/dir1/xxx’, “ls”, “-a”, “-l”, null) 。系统提供的接口,让程序执行ls的结果中的代码。 此外,exec如果正常,没有返回值,执行失败,才有返回值。,此外。如果exec()有返回值,说明调用失败。 -
为什么子进程中做进程程序替换,不会影响父进程?
答:如果子进程中做程序替换,不会执行后续代码。但父进程也可以继续等待子进程的结束。
各个进程替换函数
其实这些都是系统提供的execve()的包装。
如果exec()返回了,就是程序替换失败了。
6. execl():
参数:路径、可变参数列表为参数(数量可变的参数列表 const char* arg,以“”分割,必须以NULL结尾)。
7. execv()
const char* path, char* cosnt argv[]
第二个参数是指针数组。
execv()函数传一个自写字符串数组。
- 遇到了错误,C++11规范过于严格。
结果:
进程替换成功且发现进程替换后,不会执行原来的代码。
- execlp()
带p:不用写文件全路径,不带v,所以不需要自己写数组参数。
第一个参数直接给名就行,不需要全路径,因为会自己去找。
- execvp()
v:使用自写数组。
p:直接用命令名。
和execv比起来,使用更简洁。 - execl()
e:表示自己维护环境变量,即:自己写全路径名。
这个执行的是自己的文件,而不是Linux命令。
使用:写入你要调用的文件路径,文件,NULL结尾。
代码:
mycode.c:
myload.c:
注意这里涉及了makefile同时编译多个文件的操作
如下:需要多写个ALL
效果:
此外,这个函数还可以传变量给被调用文件,第三个参数env,被调用方可以通过extern方式,获取该值。如下:
之后通过./myload会打印mycode传入的env值。
而如果直接执行mycode中execl(),会打印真实环境的env值。
- 关于其它:
l、e、v、p含义通用。
总结exec()系列:
l:带列表,即在命令行上怎么传,就怎么写入但是要每个以“”分开,因为命令行上就是一个个的字符串像:-a -l 其实都是分开的字符串。注意以NULL结尾。
v:参数用自写数组,传入自写数组参数
p:用p自动搜path
e:自己维护环境变量,自己写全路径
- 模拟shell
2.04 父子转换、有问题 ,exec是让当前进程去执行XXX