c语言main函数守护进程,C语言编写守护进程

概念

守护进程(daemon)是一种运行在后台的一种特殊的进程,它独立于控制终端而且周期性的执行某种任务或等待处理某些发生的事件。因为在Linux中,每一个系统与用户进行交流的界面成为终端,每个今后终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭。可是守护进程却能突破这种限制,它脱离于终端而且在后台运行,而且它脱离终端的目的是为了不进程在运行的过程当中的信息在任何终端中显示而且进程也不会被任何终端所产生的终端信息所打断。它从被执行的时候开始运转,知道整个系统关闭才退出(固然能够认为的杀死相应的守护进程)。若是想让某个进程不由于用户或中断或其余变化而影响,那么就必须把这个进程变成一个守护进程。shell

实现步骤

建立子进程,父进程退出(使子进程成为孤儿进程):这是编写守护进程的第一步,因为守护进程是脱离终端的,所以完成第一步后就会在shell终端里形成一个程序已经运行完毕的假象。以后的全部工做在子进程中完成,而用户在shell终端里则能够执行其余命令,从而在形式上作到了与控制终端脱离。实现的语句以下:

// 是父进程就结束,而后子进程继续执行

if(pid = fork()) {

exit(0);

}

在子进程中建立新的会话(脱离控制终端):这步是建立守护进程中最重要的一步,虽然实现起来很简单,可是它的意义很是重要,在这里使用的是系统函数setsid()来建立一个新的会话,而且担任该会话组的组长。

进程组(process group):一个或多个进程的集合,每个进程组有惟一一个进程组ID,即进程组长进程的ID。网络

会话期(session):一个或多个进程组的集合,有惟一一个会话期首进程(session leader)。会话期ID为首进程的ID。会话期能够有一个单独的控制终端(controlling terminal)。与控制终端链接的会话期首进程叫作控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其他进程组称为后台进程组。session

挂断信号(SIGHUP):默认的动做是终止程序。当终端接口检测到网络链接断开,将挂断信号发送给控制进程(会话期首进程)。若是会话期首进程终止,则该信号发送到该会话期前台进程组。一个进程退出致使一个孤儿进程组中产生时,若是任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中全部进程。所以当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会致使该会话期内其余进程退出。函数

c语言main函数守护进程,C语言编写守护进程_第1张图片

改变当前目录为根目录:使用fork()建立的子进程是继承了父进程的当前工做目录,因为在进程运行中,当前目录所在的文件系统是不能卸载的,这对之后使用会形成不少的麻烦。所以一般的作法是让“/”做为守护进程的当前目录,固然也能够指定其余的别的目录来做为守护进程的工做目录。this

重设文件权限掩码:文件权限掩码是屏蔽掉文件权限中的对应位。因为使用fork()函数新建立的子进程继承了父进程的文件权限掩码,这就给该子进程使用文件带了不少的麻烦(好比父进程中的文件没有执行文件的权限,然而在子进程中但愿执行相应的文件这个时候就会出问题)。所以在子进程中要把文件的权限掩码设置成为0,即在此时有最大的权限,这样能够大大加强该守护进程的灵活性。设置的方法是:umask(0)。编码

关闭文件描述符:同文件权限码同样,用fork()函数新建的子进程会从父进程那里继承一些已经打开了的文件。这些文件被打开的文件可能永远不会被守护进程读写,若是不进行关闭的话将会浪费系统的资源,形成进程所在的文件系统没法卸下以及引发预料的错误。code

守护进程的退出:

上面创建了守护进程,当用户须要外部中止守护进程运行时,每每须要使用kill命令来中止该守护进程,因此守护进程中须要编码来实现kill发出的signal信号处理,达到进程的正常退出。实现该过程的函数是signal函数:blog

// 将一个给定的函数和一个特定的信号联系起来,即在收到特定的信号的时候执行相应的

signal(SIGTERM, sigterm_handler);

void sigterm_handler(int arg) {

// 进行相应处理的函数

}。

例子

#include

#include

#include

#include

#include

#include

#include

#define MAXFILE 65535

int main()

{

pid_t pc;

int i,fd,len;

char *buf="this is a dameon \n";

len = strlen(buf);

// 建立一个进程用来作守护进程

// 有看到不少开源服务有fork两次,但第2次fork不是必须的。

// fork第二次主要目的是。防止进程再次打开一个控制终端。

// 由于打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,子进程ID != sid(sid是进程父进程的sid)。因此也没法打开新的控制终端。

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

}

}

你可能感兴趣的:(c语言main函数守护进程)