您的位置:首页 > 运维架构 > Linux

一个Linux守候进程例子,避免产生僵死进程

2012-03-15 13:29 411 查看
在前一部分提到了僵死进程的概念,如果我们写一个进程,这个进程fork 了一个新的子进程。而,我们不想等待这个进程完全结束,不想在主程序结束时,这个子进程变成僵死进程。利用量词调用 fork 可以达到这一目标。

下面为一个例子,及解释:

[cpp] view
plaincopy

#include<stdio.h>

#include<sys/wait.h>

int main(int argc, char **argv[])

{

pid_t pid;

printf("Main pid is %d./n",getpid());

pid = fork();/*第一个子进程,用来产生第二个子进程,提前与第二个子进程退出*/

if(pid < 0)

{

printf("fork error/n");

exit(1);

}

else if(pid == 0 )/*第一个子进程中执行*/

{

printf("child pid is %d,and my ppid is %d./n",getpid(),getppid());

pid = fork();/*产生第二个子进程,作为最终的目标进程*/

if(pid < 0)

{

printf("fork error/n");

exit(1);

}

else if(pid > 0)/*在第一个子进程退出*/

{

printf("child pid is %d,and my ppid is %d,i will die./n",getpid(),getppid());

exit(0);

}

sleep(2);/*第二个子进程休眠2秒,等待其父进程结束后,第二个子进程成为init进程的子进程,避免第二个成为僵死进程*/

printf("second child,my pid is %d, parent pid = %d/n", getpid(),getppid());

exit(0);

}

/*在主进程中执行,等待第一个子进程结束,避免第一个进程成为僵死进程*/

if (waitpid(pid, NULL, 0) != pid)

{

printf("waitpid error/n");

exit(1);

}



printf("My pid is %d,i have waitted %d died./n",getpid(),pid);



return 0;

}

在 Ubuntu10.4上的结果:

Main pid is 2736.

child pid is 2737,and my ppid is 2736.

child pid is 2737,and my ppid is 2736,i will die.

My pid is 2736,i have waitted 2737 died.

second child,my pid is 2738, parent pid = 1

总结:

在程序中,主程序中等待了第一个子进程结束,使第一个子进程不会产生僵死。在第一个子进程中,产生第二个子进程。第二个子进程休眠 2秒,等待其父进程(第一个子进程)结束。这是第二个子进程由于在退出前,其父进程提前结束,其父进程变为init。避免产生僵死。为最终需要的目标进程。

在设计中,如果需要一个进程运行时间很长,并且避免产生僵死,则可以在第二个子进程中执行需要的指令。

[cpp] view
plaincopy

#include<stdio.h>

#include<unistd.h>

#include<sys/resource.h>

#include<fcntl.h>

#include<signal.h>

#include<syslog.h>

void daemon_init(const char * cmd);

int main(int argc, char * argv[])

{

daemon_init("liyachao_d");

time_t ticks;

while(1)

{

sleep(60);

ticks = time(NULL);

syslog(LOG_INFO,"%s",asctime(localtime(&ticks)));

}

return 0;

}

void daemon_init(const char * cmd)

{

int i;

int fd0;

int fd1;

int fd2;

pid_t pid;

struct rlimit rl;

struct sigaction sa;

/*清空文件默认生成权限*/

umask(0);

/*取得最大的文件描述符*/

if(getrlimit(RLIMIT_NOFILE,&rl) < 0 )

{

printf("can't get file limit.");

}

pid = fork();

if(pid < 0 )

{

printf("fork error.");

exit(1);

}

else if(pid > 0)

{

exit(0);

}

setsid();

/*

Ensure future opens won't allocate controlling TTYs.



*/

sa.sa_handler =SIG_IGN;

sigemptyset(&sa.sa_mask);

sa.sa_flags = 0;

if(sigaction(SIGHUP,&sa,NULL) < 0 )

{

printf("catn't ignore SIGHUP");

exit(1);

}



pid = fork();

if(pid < 0 )

{

printf("child fork error.");

exit(1);

}

else if(pid > 0)

{

exit(0);

}

/*改变工作目录到root*/

if(chdir("/") < 0 )

{

printf("can't change directory to /");

exit(1);

}

/*关闭所有的文件描述符*/

if (rl.rlim_max == RLIM_INFINITY)

{

rl.rlim_max = 1024;

}

for (i = 0; i < rl.rlim_max; i++)

{

close(i);

}

/*重定向文件描述符0,1,2,到/dev/null*/

fd0 = open("/dev/null",O_RDWR);

fd1 = open("/dev/null",O_RDONLY);

fd2 = open("/dev/null",O_RDWR);

openlog(cmd, LOG_CONS, LOG_DAEMON);

/*初始化日志文件*/

if (fd0 != 0 || fd1 != 1 || fd2 != 2)

{

syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2);

exit(1);



}

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