您的位置:首页 > 其它

简单实现一个守护进程(Daemon)

2016-07-20 12:24 295 查看
学习进程就不得不提到一个运行在后台的特殊进程――守护进程。(也称精灵进程)。Linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程不受用户登录注销的影响,它们一直在运行着而我们就将这种进程称为守护进程。
守护进程独立于控制终端并周期性的执行某种任务或者等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用1守护进程实现的,比如,Internet服务器inetd、Web服务器httpd等。此外,守护进程还可以完成许多系统任务,比如作业规划进程crond等。
可以使用ps axj命令查看系统中的进程。

(由于太多只截取了一部分)
还可以使用相关参数来有选择性的查看。参数a表示不仅列当前用户的进程,也列出所有其他用户的进程,参数x表示不仅列有控制终端的进程,也列出所有无控制终端的进程,参数j表示列出与作业控制相关的信息。
使用参数x来进行查看。



了解了守护进程的概念之后,自己也可以来写一个守护进程。

创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader。
在调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进程组的Leader只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进程组中,进程组Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子 进程中调用setsid就不会有问题了。
创建守护进程可以按照如下步骤进行:

1、 调用umask函数将文件模式创建屏蔽字设置为0;
2、调用fork,父进程退出(exit);
3、调用setsid创建一个新会话;
4.、将当前工作目录更改为根目录;
5、 关闭不在需要的文件描述符;
6.、其他:忽略SIGCHLD信号。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
void creat_daemon() {
int i;
int fd0;
pid_t pid;
struct sigaction sa;
umask(0);
if( (pid = fork()) < 0 )
{      }
else if (pid != 0)
{          exit(0);  //终止父进程     }
setsid(); //设置新会话
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if( sigaction(SIGCHLD, &sa, NULL ) < 0 )
{       return;     }
if( (pid = fork())<0)
{printf("fork error!\n");
return;     }
else if( pid != 0)
{          exit(0);     }
if( chdir("/") < 0 )
{printf("child dir error\n");
return;
}
close(0);
fd0 = open("/dev/null", O_RDWR);
dup2(fd0, 1);
dup2(fd0, 2);
}
int main()
{     creat_daemon();
while(1)
{
sleep(1);
}
}
可以看到有的人创建时调用了一次fork(),而有的人则调用了两次fork()。这是什么原因呢?
第一次fork的作用是让shell认为本条命令已经终止,不用挂在终端输入上。还有一个作用是为后面setsid服务。setsid的调用者不能是进程组组长(group leader),此时父进程是进程组组长。
第二次的作用是:防止进程再次打开一个控制终端。因为打开一个控制终端的前台条件是该进程必须是会话组长。再fork一次,子进程ID != sid(sid是进程父进程的sid)。所以也无法打开新的控制终端。 因此,第二次fork不是必须的。但是为了安全起见,调用两次是比较保险的。

本文出自 “七月朔风” 博客,请务必保留此出处http://luminous.blog.51cto.com/10797288/1828026
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: