LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 904|回复: 2

Creat daemon!

[复制链接]
发表于 2005-11-3 14:37:03 | 显示全部楼层 |阅读模式
author:anuode
   
  先介绍一个系统调用函数:setsid()   
setsid()创建一个会话并设置GID。加入调用进程不是一个进程组的领导者进程的话,该进程将创建一个新的会话,在这种情况下,将使调用进程成为该 新会话的领导者进程,也成为该新进程组的领导者进程,并且没有控制终端,最后,在这个会话中将只有这一个进程组,这个进程组中也只有这一个进程。   
编写daemon程序的规则:   
1.在后台运行    为避免挂起控制终端,要将daemon仿如后台执行。其方法是,在进程中调用fork使父进程终止,让daemon子进程继续在后台运行。       if(pid=fork())       exit(0);  
  2.脱离控制终端,登陆会话和进程组    登陆控制终端包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登陆终端。控制终端,登陆会话和进程组通常是从父进程继承下来 的。我们的目的就是摆脱它们,使之不受它们的影响。     方法就是调用setsid();   
3.禁止进程重新打开控制终端    现在通过2的setsid调用,进程已经是会话的组长,它可以重新申请打开一个控制终端。可以再次调用fork()使进程不再是会话的组长就可以避免进程 重新打开控制终端:    if(pid=fork())       exit(0);  
  4.关闭打开的文件描述符    for(i=0;i<OPEN_MAX;i++)    close(i);  
  5.改变当前工作目录    进程活动时,其工作目录所在的文件系统不能卸载。一般使用chdir(“/”)将工作目录改变到根目录。  
  6.重设文件创建掩码    进程从创建它的父进程那里继承了文件创建的掩码,它可以修改daemon进程创建的文件的权限。为防止这一点可以将文件创建掩码清除掉:       umask(0);  
  7.处理SIGCHLD信号    处理此信号并不是必需的。可以简单的将其忽略掉:        signal(SIGCHLD,SIG_IGN);
    例:
    extern int daemon_proc;   
    int daemon_init(const char *pname,int facility)   
      {     
               int i;      
               pid_t pid;

       /*-------创建一个子进程,并结束父进程------*/      
              if((pid = fork())<0)         
                         return(-1);      
              else  
                    {
                          if(pid)        
                               _exit(0);   
                       }
        
      /*-------儿子进程继续执行-------*/     
               if(setsid()<0)        
                         return(-1);                /*使儿子进程1变为新会话的领导者进程*/            
     
  /*------忽略掉SIGHUP信号-----*/      
              signal(SIGHUP,SIG_IGN);
       /*------创建孙子进程,并结束儿子进程-------*/   
              if((pid=fork())<0)         
                          return(-1);      
              else
                 {
                       if (pid)         
                            _exit(0);
                    }
       /*-------孙子进程继续执行--------*/      
                    daemon_proc =1 ;      /*告诉出错处理函数,当出现错误是,是去写日志而不是将错误输出到stderr*/
                  chdir("/");      
                  umask(0);     

  /*-------关闭前64个描述符------*/      
             for(i=0;i<64;i++)           
                         close(i);
      /*--------重定向标准输入、标准输出和标准出错到/dev/dull--------*/      
         open("/dev/null",O_RDONLY);      
         open("/dev/null",O_RDWR);     
         open("/dev/null".O_RDWR);
         openlog(pname,LOG_PID,facility);
          return(0);
         }
    说明:第二次fork()的原因是要确保daemon在将来不会自动请求控制终端当打开一个终端设备时。由于经过第一次fork()后,儿子进程就变成了 新会话的领导者进程且没有控制终端,当它打开一个终端设备的时候,这个终端就变成了会话领导者进程的控制终端。通过第二次fork(),可以保证孙子进程 不会是一个会话的领导者进程,这样它就不能够请求一个控制终端。
发表于 2005-11-3 20:28:08 | 显示全部楼层
very good!!!!
回复 支持 反对

使用道具 举报

发表于 2005-11-3 22:12:38 | 显示全部楼层
这个和daemon函数有什么区别吗?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表