Setsid()函数的相关内容:
(1) setsid()函数的作用:创建一个新的会话,并且担任该会话组的组长。具体作用包括:让一个进程摆脱原会话的控制,让进程摆脱原进程的控制,让进程摆脱原控制终端的控制。
(2) 创建守护进程要调用setsid()函数的原因:由于创建守护进程的第一步是调用fork()函数来创建子进程,再将父进程退出。由于在调用了fork()函数的时候,子进程拷贝了父进程的会话期、进程组、控制终端等资源、虽然父进程退出了,但是会话期、进程组、控制终端等并没有改变,因此,需要用setsid()韩式来时该子进程完全独立出来,从而摆脱其他进程的控制。
(3) 改变当前目录为根目录:
使用fork()创建的子进程是继承了父进程的当前工作目录,由于在进程运行中,当前目录所在的文件系统是不能卸载的,这对以后使用会造成很多的麻烦。因此通常的做法是让“/”作为守护进程的当前目录,当然也可以指定其他的别的目录来作为守护进程的工作目录。
(4) 重设文件权限掩码:
文件权限掩码是屏蔽掉文件权限中的对应位。由于使用fork()函数新创建的子进程继承了父进程的文件权限掩码,这就给该子进程使用文件带了很多的麻烦(比如父进程中的文件没有执行文件的权限,然而在子进程中希望执行相应的文件这个时候就会出问题)。因此在子进程中要把文件的权限掩码设置成为0,即在此时有最大的权限,这样可以大大增强该守护进程的灵活性。设置的方法是:umask(0)。
(5) 关闭文件描述符:
同文件权限码一样,用fork()函数新建的子进程会从父进程那里继承一些已经打开了的文件。这些文件被打开的文件可能永远不会被守护进程读写,如果不进行关闭的话将会浪费系统的资源,造成进程所在的文件系统无法卸下以及引起预料的错误。按照如下方法关闭它们:
for(i=0;i 关闭打开的文件描述符close(i);
(6) 守护进程的退出:
上面建立了守护进程,当用户需要外部停止守护进程运行时,往往需要使用kill命令来停止该守护进程,所以守护进程中需要编码来实现kill发出的signal信号处理,达到进程的正常退出。实现该过程的函数是signal函数:
signal(SIGTERM, sigterm_handler);
void sigterm_handler(int arg)
{
//进行相应处理的函数
}。功能是:将一个给定的函数和一个特定的信号联系起来,即在收到特定的信号的时候执行相应的函数。
3、守护进程实现的一个简单的例子:
#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()
{
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(); //使子进程独立1.摆脱原会话控制 2.摆脱原进程组的控制 3.摆脱控制中端的控制
chdir("/"); //改变当前工作目录,这也是为了摆脱父进程的影响
umask(0); //重设文件权限掩码
for(i=0;i<MAXFILE;i++) //关闭文件描述符(常说的输入,输出,报错3个文件),
//因为守护进程要失去了对所属的控制终端的联系,这三个文件要关闭
close(i);
while(1)
{
if((fd=open("/tmp/dameon.txt",O_CREAT|O_WRONLY|O_APPEND,0600))<0)
{
printf("open file err \n");
exit(0);
}
write(fd,buf,len+1);
close(fd);
sleep(10);
}
}