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

Linux进程控制编程之守护进程

2011-05-21 13:43 441 查看
本次将记录有关Linux守护进程的概念及其用法。

守护进程是我们通常说的Daemon进程,是后台服务进程,通常独立于控制终端并周期性地执行任务或等待事件。守护进程常在系统引导装入时启动,在系统关闭时终止。在Linux中,每一个从终端运行的进程都会依附于这个终端,当终端被关闭时,进程会自动关闭。但是守护进程就能突破这种限制,如果想让某个进程不因为用户或终端的变化而受到影响,则应该把这个进程变成守护进程。

编写守护进程的步骤:

1.创建子进程,退出父进程

退出父进程后,子进程变成孤儿进程,由1号进程(init进程)收养。

关键代码如下:

pid = fork();

if (pid > 0)

{

exit(0);

}

2.在子进程中创建新会话

先介绍两个概念:进程组和会话组

进程组是一个或多个进程的集合,由进程组ID唯一标识。每个进程组都有组长进程,组长的进程号就是进程组ID,且该进程组ID不会因组长进场的退出而受到影响。

会话组是一个或多个进程组的集合,通常来说,会话始于用户登录,终止于用户退出。

接下来重点介绍setsid函数,它是创建守护进程的最重要一环。setsid函数用于创建一个新的会话,并担任会话组的组长。setsid函数的作用有3点

(1)让进程摆脱原会话组的控制

(2)让进程摆脱原进程组的控制

(3)让进程摆脱原控制终端的控制

为什么要执行setsid函数呢?原因是,之前我们利用fork函数创建子进程的时候,把父进程的会话组、进程组、控制终端等信息都复制过来了,虽然父进程退出了,但是子进程还是会保留这些信息的。所以我们需要执行setsid函数来改变这些信息,进行“越狱”。

prototype : pid_t setsid(void)

return : 该进程组ID —— success

-1 —— failure

3.改变当前目录为根目录

一般子进程继承父进程的当前目录环境下的文件系统是不能卸载的,对以后使用可能会有麻烦(如系统需要进入单用户模式)。通常的做法是把根目录“/”作为守护进程的当前工作目录。

4.重设文件权限掩码

子进程继承父进程的权限掩码,带来不便,一般把掩码重设为0,较为灵活。

5.关闭文件描述符

子进程会从父进程那里继承一些已经打开了的文件,它们在消耗着系统资源。由于子进程已经脱离了终端的控制,文件描述符为0、1、2的文件(输入、输出、报错)也失去了存在价值,应被关闭。

摘自《嵌入式Linux应用程序开发详解》的例程如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

#define MAXFILE 65535

int main(void)
{
pid_t pc;
int i, fd, len;
char *buf = "This is a Dameon/n";
len = strlen(buf);

pc = fork();    //第一步
if (pc < 0)
{
printf("error fork/n");
exit(1);
}
else if (pc > 0)
{
exit(0);
}

setsid();       //子进程在运行,第二步
chdir("/");      //第三步
umask(0);        //第四步
for (i = 0; i < MAXFILE; i++)   //创建守护进程完成
{
close(i);
}

for (;;)
{         //以下正式进行守护进程工作,每隔10s往dameon.log写入一条语句
if((fd = open("/tmp/dameon.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0)
{
perror("open");
exit(1);
}

write(fd, buf, len+1);
close(fd);
sleep(10);
}
}


编译运行后,执行tail -f /tmp/dameon.log 即可查询到该文件周期性更新的效果。

执行 ps -ef | grep daemon 即能查询到守护进程的状态。

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