linux c :系统调用-凯发k8官方网
fork():创建子进程,并返回进程id。
wait(&status):等待子进程终止。如果成功则会返回僵尸子进程的pid,status的值会是子进程的exitcode。
exit(value):进程正常退出,并返回退出值value
prctl(pr_set_child_subreaper):设置当前进程为subreaper进程。
零、示例代码即可能的输出结果
目录
一、fork()
二、wait()
三、subreaper
四、解读上述代码和输出结果
#include
运行结果:(每次运行可能顺序不一样)
在linux 中,每个用户在同一时间只能有一定数量的进程。用户资源限制文件通常在/etc/security/limits.conf 文件中设置。进程有两种执行状态,一种是内核态,一种是用户态。每个进程都在内核中下产生并开始执行,想调用硬件设备例如操作cpu,键盘,或者想执行系统调用都是在内核态下完成的。修改状态寄存器的值就可以从内核态转化为用户态。一旦转为用户态,那么就无法直接访问硬件相关的设备,想要重新转为内核态只有3种方式:硬件中断,异常,系统调用。 可以说,内核是操作系统之下的部分,用户是操作系统之上的部分。用户只需关心操作系统为用户提供了哪些可访问内核的接口就行。
在内核模式中,每个进程都有完全相同的代码段,数据段和堆,但是每个进程都有只属于自己的栈。
一、fork()
创建子进程并返回子进程的pid , int pid = fork(); 如果fork失败则为-1。当创建了子进程后,子进程和父进程在用户态的映像完全相同,但是在内核态下的映像只有栈有区别,意味着子进程和父进程有相同的代码和数据。因为创建子进程时用户态的栈也是一样的,意味着栈帧情况也是一样的。创建完后子进程和父进程都从fork()后继续执行.fork()方法调用了内核中kfork()函数,它对创建出来的子进程返回是0,父进程返回值是子进程的进程号;
int pid =fork(); if(pid=-1){//父进程创建子进程失败的分支 }else if(pid ==0){//子进程执行的分支,因为子进程返回的pid是0 }else {//父进程执行的分支,pid是子进程的id }二、wait()
等待僵尸子进程。所谓的僵尸进程,就是程序已经结束但是资源未释放的进程。wait除了返回僵尸子进程的id,获取子进程的退出状态,还会释放僵尸子进程。wait系统调用将调用内核中的kwait函数
三、subreaper
进程可以用系统调用定义自己为subreaper进程:
prctl(pr_set_child_subreaper);
如果子进程的父进程先死亡,那么该子进程就会成为一个孤儿进程。在linux中,标记为subreaper的祖先进程会成为该孤儿的父进程,否则将成为p1进程子进程。(p1进程是操作系统初始化的进程,除p0和p1进程,其他所有进程都是p1进程的子孙进程)。不过要注意的是,当p1清理重定父级进程时,会丢失关于子进程的所有信息。p1因为进程等级高,当p1作为孤儿进程的父进程时服务管理器不能再从服务守护进程中接收sigchld信号,也不能等待任何僵尸子进程。定义subreaper就可以很好的解决上述问题,并且可以有效地减少p1进程的工作量。
显示当前用户的subreaper 进程的pid 和信息:
ps fxau | grep username | grep "/sbin/upstart"
四、解读上述代码和输出结果
就运行结果而言,
1)当fork创建出来子进程后,父进程获取到cpu使用权先执行,并打印出了
然后进入while循环等待子进程执行结束。
2)接下来子进程执行并打印出了,
之后子进程 fork 创建出了一个子进程的子进程即孙子进程。
3)子进程先执行完毕,并打印出:
此时,子进程执行完毕但是未释放进程资源,于是成为了僵尸进程。
4)此时父进程获取到cpu使用权,通过wait返回子进程的pid,继续执行打印出了
wait释放了子进程的资源,使孙子进程成为了孤儿进程,但是由于之前父进程(pid=3434)将自己设置成了pr_set_child_subreaper , 使 孙子进程(pid=3436)的父亲不再是已经死亡的(pid=3435),而是父进程(pid=3434)。
5)所以当孙子执行完自己的代码后,打印出
成为了僵尸进程后,被父进程 wait() 释放出来,打印出
后结束。
与50位技术专家面对面20年技术见证,附赠技术全景图总结
以上是凯发k8官方网为你收集整理的linux c :系统调用-fork,wait,subreaper的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: