您的位置:首页 > 编程语言 > C语言/C++

C语言之进程控制(僵尸进程和守护进程)

2017-08-09 20:41 344 查看
进程控制编程

 

1、子进程先父进程先结束:如果子进程结束的时候,父进程不做任何处理,那么这个子进程的一些信息会被保留,比如子进程的文件描述符,此时的子进程会被称为僵尸进程。这种僵尸进程会给程序带来不可想象的伤害,所以我们要尽量避免僵尸进程的产生。
僵尸进程产生的过程:

(1)父进程调用fork创建子进程后,子进程运行直至其终止,它立即从内存中移除,但进程描述符仍然保留在内存中(进程描述符占有极少的内存空间)。

(2)子进程的状态变成EXIT_ZOMBIE,并且向父进程发送SIGCHLD 信号,父进程此时应该调用 wait() 系统调用来获取子进程的退出状态以及其它的信息。在 wait 调用之后,僵尸进程就完全从内存中移除。

(3)因此一个僵尸存在于其终止到父进程调用 wait 等函数这个时间的间隙,一般很快就消失,但如果编程不合理,父进程从不调用 wait 等系统调用来收集僵尸进程,那么这些进程会一直存在内存中。

(4)僵尸进程的处理一般是用wait()函数来处理。

代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>

int main()
{
pid_t pid = fork(); //fork产生子进程,返回值pid如果是-1代表错误,0则代表子进程,非0代表的是父进程。
//fork很特殊,它会复制父进程,然后在父进程中返回的是子进程的ID号,而在子进程中是返回的0;

switch(pid)
{
case -1:
perror("fork");
exit(0);
case 0:
printf("我是子进程\n");
break; //子进程先父进程结束,产生僵尸进程
default:
printf("我是父进程\n");
while(1); //死循环防止父进程结束。
break;
}

return 0;
}

2、父进程先子进程先结束:则该父进程的所有子进程的父进程都改变为init进程。我们称这些进程由init进程领养。其执行顺序大致如下:在一个进程终止时,内核逐个检查所有活动进程,以判断它是否是正要终止的进程的子进程,如果是,则该进程的父进程ID就更改为1(init进程的ID);

有init领养的进程不会称为僵死进程,因为只要init的子进程终止,init就会调用一个wait函数取得其终止状态。这样也就防止了在系统中有很多僵死进程。

如果父进程结束,那么子进程会被init进程领养,那么这个时候我们就不能直接对这个子进程进行操作了,这个时候这个子进程会在后台继续运行,这个时候我们称这个子进程为守护进程(或者精灵进程)。在计算机中,有很多的后台程序在运行,所以这个守护进程对我们来说是很重要的。

守护进程的代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int Daemonize()
{
pid_t pid = fork();   //创建子进程
if(pid == -1)
{
perror("fork");
return -1;
}
else if(pid > 0)
{
exit(0);     //关闭父进程
}

umask(0);      //设置文件的掩码。
/*注释:文件权限掩码是指屏蔽掉文件权限中的对应位。比如,有个文件权限掩码是050,它就屏蔽了文件组拥有者的可读与可执行权限。由于使用fork函数新建的子进程继承了父进程的文件权限掩码,这就给该子进程使用文件带来了诸多的麻烦。因此,把文件权限掩码设置为0,可以大大增强该守护进程的灵活性。*/

if(setsid < 0)    //设置新的会话,目的是让这个子进程从父进程脱离出来,不受任何父进程控制。
{
perror("setsid");
return -1;
}

if(chdir("/") == -1)     //设置当前的工作目录。
{
perror("chdir");
return -1;
}

close(0);    //关闭标志输入,标志输出,标准错误,不让它在终端显示打印信息。
close(1);
close(2);

open("dev/null",O_RDONLY);  //文件的重定向,让这个守护进程的信息打印在一个文件里
open("dev/null",O_RDWR);
open("dev/null",O_RDWR);

return 0;
}

int main()
{
Daemonize();  //守护进程函数
while(1);   //死循环

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐