对于daemon守护进程,可能大多数朋友了解不多.对于守护进程,也就是说它由init直接来管理.举个例子:当我们打开一个terminal,输入gedit,然后编辑一些字,不要关闭gedit,这时候回到终端terminal,按ctrl+c,这时候你看到了什么,gedit关闭了对不对.因为gedit可以看成是一个进程哇,而且这时候终端并没有显示$或者#,结束的肯定是gedit的进程哇.如果我们想让这些进程在我们的后台运行,不受到terminal的限制,就需要来写一个daemon守护进程了.
这里说一下具体的方法:
1.fork()一个子进程
2.把父进程exit(0)退出,这时候子进程成为了一个孤立的进程,由init接管
3.setsid(),脱离控制终端,登录会话和进程组
介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号 (PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。 控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使 进程成为会话组长.当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。
4.close(i) ,关闭文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。
5.umask(0);重置文件权限掩码
6.更改当前的工作目录chdir(),这个可选
ok,这样子一个daemon就差不多了.
下面写了一个编程的实例,用wget 后台执行一个下载,然后把下载信息记录到info.txt文件中以便察看下载结果.
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- int main(){
- pid_t daemon;
- int i,fd;
- daemon = fork();
- if(daemon < 0){
- printf("Fork Error!");
- exit(1);
- }
- else if (daemon > 0 ) {
- printf("Father process exited!");
- exit(0);
- }
- setsid();
- umask(0);
- for (i = 0;i < getdtablesize();i++){
- close(i);
- }
- system("wget -c http://cdimage.ubuntu.com/daily-live/current/quantal-desktop-amd64.iso >info.txt 2>&1");
- exit(0);
- }