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

论坛 期权论坛 脚本     
匿名技术用户   2020-12-23 09:55   11   0

进程控制编程

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;
}



分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP