5个步骤创建Linux守护进程

Daemon是Linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

在Linux中,每一个系统与用户进行交流的界面称为终端。每一个从终端开始运行的进程都会依附于该终端,当终端关闭时,相应的进程都会自动结束。但是守护进程却能够突破这种限制,不受终端关闭的影响。反之,如果希望某个进程不因为用户、终端或者其他的变化而受到影响,那么就必须把这个进程变成一个守护进程。

第一步:创建子进程,父进程退出

由于守护进程是脱离控制终端的,因此,完成第一步后子进程变成后台进程,给用户感觉程序已经运行完毕。之后的所有工作都在子进程中完成,而用户通过shell可以执行其他的命令,从而在形式上做到了与控制终端的脱离。此时,子进程变成了孤儿进程,由init进程收养它。

第二步:在子进程中创建会话

setsid()函数用于创建一个新的会话,并担任该会话组的组长。调用setsid()有下面3个作用。

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

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

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

为什么要调用setsid()呢?

由于调用fork()时,子进程全盘复制了父进程的会话期、进程组和控制终端等。虽然父进程退出了,但原先的会话期、进程组和控制终端并没有改变,因此,还不是真正意义上的独立,而setsid()能够使进程完全独立出来,从而脱离所有其他进程的控制。

第三步:改变当前目录

使用fork()创建的子进程继承了父进程的当前工作目录。由于在进程运行过程中,当前目录所在的文件系统是不能卸载的,这对以后的使用会造成诸多麻烦(比如系统由于某种原因要进入单用户模式)。因此,通常的做法是让根目录作为守护进程的当前工作目录,这样就可以避免上述问题。当然,如有特殊需要,也可以把当前工作目录换成其他的路径,如"/tmp"。改变工作目录的函数是chdir()。

第四步:重设文件权限掩码

文件权限掩码的作用是屏敝文件权限中的对应位。

由于使用fork()函数新建的子进程继承了父进程的文件权限掩码,这就该该子进程使用文件带来了一定的影响。因此,把文件权限掩码设置为0,可以增强该守护进程的灵活性。设置文件权限掩码的函数是umask()。在这里,通常的使用方法为umask(0)。

第五步:关闭文件描述符

同文件权限掩码一样,用fork()新建的子进程会从父进程那里继承一些已经打开了的文件。这些被打开的文件可能永远不会被守护进程访问,但它们一样占用系统资源,而且还可能导致所在的文件系统无法被卸载。

特别是守护进程和终端无关,所以指向终端设备的标准输入、标准输出和标准错误流已经失去了存在的价值,应当被关闭。通常按如下方式关闭文件描述符。

for (i = 0; i < getdtablesize(); i++)
          close(i);

或者

maxfd = sysconf(_SC_OPEN_MAX);
    for(i=0;i         close(i);

这样一个简单的守护进程就建立起来了。

$tail -f /tmp/daemon.log

$ps -ef | grep daemon

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	pid_t pid;
	int i, fd;
	char * buf = "This is a Daemon\n";

	pid = fork();
	if (pid < 0) {
		printf("Eorror fork\n");
		exit(1);
	} else if (pid > 0) 
		exit(0);

	setsid();
	chdir("/tmp");
	umask(0);
	for (i = 0; i < getdtablesize(); i++)
		close(i);

	while (1) {
		if ((fd = open("daemon.log", O_CREAT|O_WRONLY|O_TRUNC,0600) < 0)) {
			printf("Open file error\n");
			exit(1);
		}
		write(fd, buf, strlen(buf));
		//close(fd);
		sleep(2);
	}
	close(fd);
	exit(0);
}

 

 

你可能感兴趣的:(Linux)