守护进程

来源:互联网 发布:淘宝商城女装 编辑:程序博客网 时间:2024/05/01 08:51

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Daemonize myself.
守护进程,也就是通常说的Daemon进程,
是Linux中的后台服务进程。
它是一个生存期较长的进程,
通常独立于控制终端并且周期性地执行
某种任务或等待处理某些发生的事件。
守护进程常常在系统引导装入时启动,
在系统关闭时终止。Linux系统有很多守护进程,
大多数服务都是通过守护进程实现的,同时,
守护进程还能完成许多系统任务,例如,
作业规划进程crond、打印进程lqd等
(这里的结尾字母d就是Daemon的意思)。 */
void sigterm_handler(int arg)
{
_running=0;
}
int
daemon (int nochdir, int noclose)
{
  pid_t pid;

  pid = fork ();

  /* In case of fork is error. */
  if (pid < 0)
    {
      perror ("fork");
      return -1;
    }

  /* In case of this is parent process. */
  if (pid != 0) //先让父进程退出
    exit (0);
//  会话周期:会话期是一个或多个进程组的集合。通常,
//一个会话开始于用户登录,终止于用户退出,在此期间该用户运行的所有进程都属于这个会话期。
//setsid函数用于创建一个新的会话,并担任该会话组的组长
  /* Become session leader and get pid. */
  pid = setsid();

  if (pid < -1)
    {
      perror ("setsid");
      return -1;
    }

  /* Change directory to root. 使用fork创建的子进程继承了父进程的当前工作目录,要改变*/
  if (! nochdir)
    chdir ("/");

  /* File descriptor close. */
  if (! noclose)
    {
      int fd;

      fd = open ("/dev/null", O_RDWR, 0);
      if (fd != -1)
 {
// 如果想让某个进程不因为用户或终端或其他地变化而受到影响,
//那么就必须把这个进程变成一个守护进程。守护进程是脱离控制终端,
//在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,
//就会自动由1号进程(init)收养它,这样,原先的子进程就会变成init进程的子进程。
// setsid函数用于创建一个新的会话,
//并担任该会话组的组长。调用setsid有下面的3个作用:   
//让进程摆脱原会话的控制   让进程摆脱原进程组的控制   
//让进程摆脱原控制终端的控制   
//那么,在创建守护进程时为什么要调用setsid函数呢?
//由于创建守护进程的第一步调用了fork函数来创建子进程,
//再将父进程退出。由于在调用了fork函数时,子进程全盘拷贝了父进程的会话期
//、进程组、控制终端等,虽然父进程退出了,但会话期、进程组、
//控制终端等并没有改变,因此,这还不是真正意义上的独立开来,
//而setsid函数能够使进程完全独立出来,从而摆脱其他进程的控制。

   dup2 (fd, STDIN_FILENO);
   dup2 (fd, STDOUT_FILENO);
   dup2 (fd, STDERR_FILENO);
   if (fd > 2)
     close (fd);
 }
    }
  文件权限掩码是指屏蔽掉文件权限中的对应位。比如,有个文件权限掩码是050,它就屏蔽了文件组拥有者的可读与可执行权限。
   //由于使用fork函数新建的子进程继承了父进程的文件权限掩码,
   //这就给该子进程使用文件带来了诸多的麻烦。因此,
   //把文件权限掩码设置为0,可以大大增强该守护进程的灵活性。
   //设置文件权限掩码的函数是umask。在这里,通常的使用方法为umask(0)。
   //当用户需要外部停止守护进程运行时,
   //往往会使用 kill命令停止该守护进程。所以,
   //守护进程中需要   编码来实现kill发出的signal信号处理,
   //达到进程的正常退出。
  signal(SIGTERM, sigterm_handler);

  umask (0027);
  关闭文件描述符
    同文件权限码一样,用fork函数新建的子进程会从父进程那里继承一些已经打开了的文件。
  //这些被打开的文件可能永远不会被守护进程读写,
  //但它们一样消耗系统资源,而且可能导致所在的文件系统无法卸下。
  for(int i=0;i<MAXFILE;i++)
   close(i);
while(_running)
{
  if((fd=open("/tmp/dameon.log",O_CREAT|O_WRONLY|O_APPEND,0600))<0)
   {   
   perror("open");
   exit(1);
   }
}
  return 0;
}

int main(void)
{
 daemon(0,0);
 sleep(1000);
 
 return 0;

原创粉丝点击