欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux守护进程(精灵进程)

程序员文章站 2024-03-19 23:06:40
...

守护进程

守护进程也称精灵进程,是运行在后台的一种特殊进程,它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。

Linux系统启动时会启动很多系统服务进程,这些系统服务进程没有控制终端,不能直接和用户交互。其它进程都是在用户登录或运行程序时创建,在运行结束或用户注销时终止,但系统服务进程(守护进程)不受用户登录注销的影响,它们一直在运行着。这种进程有一个名称叫守护进程(Daemon)。

使用命令查看守护进程
ps axj | more

Linux守护进程(精灵进程)

  • 凡是TPGID一栏写着-1的都是没有控制终端的进程,也就是守护进程。
  • 在COMMAND一列用[]括起来的名字表示内核线程,这些线程在内核里创建,没有用户空间代码,因此没有程序文件名和命令行, 通常采用以k开头的名字,表示Kernel。
  • 可以看出,守护进程通常采用以d结尾的名字,表示Daemon。

创建守护进程

创建守护进程最关键的一步是调用setsid函数创建一个新的Session,并成为Session Leader。

#include <unistd.h>
pid_t setsid(void);
该函数调用成功时返回新创建的Session的id(其实也就是当前进程的id),出错返回-1。

注意,调用这个函数之前,当前进程不允许是进程组的Leader,否则该函数返回-1。要保证当前进程不是进 程组的Leader也很容易,只要先fork再调用setsid就行了。fork创建的子进程和父进程在同一个进程组中,进程组的Leader必然是该组的第一个进程,所以子进程不可能是该组的第一个进程,在子进程中调用setsid就不会有问题了。

成功调用该函数的结果是:

  • 创建一个新的Session,当前进程成为Session Leader,当前进程的id就是Session的id。
  • 创建一个新的进程组,当前进程成为进程组的Leader,当前进程的id就是进程组的id。
  • 如果当前进程原本有一个控制终端,则它失去这个控制终端,成为一个没有控制终端的进程。所谓失去控制终端是指,原来的控制终端仍然是打开的。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

void mydaemon()
{
    int fd0;
    pid_t pid;
    struct sigaction sa;
    umask(0);  //设置文件的默认权限
    if((pid = fork()) < 0)  
    {
        perror("fork");
        exit(1);
    }
    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)   //注册SIGCHLD信号,确保不会干扰父进程。
    {
        perror("sigaction");
        exit(2);
    }
     //再次fork 终止父进程,保持子进程不是话首进程,从保证后
     //续不会在和其他终端关联!
     //这部分不是必须的
  // if((pid = fork()) < 0)    
  //{
  //    perror("fork2");
  //   exit(3);
  //  }
  //  else if(pid > 0)    
  // {
  //    exit(0);  
  //  }
    if(chdir("/") < 0)   //更改工作目录
    {
        perror("chdir");
        exit(3);
    }
    close(0);    //关闭不必要的文件描述符
    fd0 = open("/dev/null", O_RDWR);  
    dup2(fd0, 1); //重定向
    dup2(fd0, 2);
      while(1)
    {}

}

int main()
{
    mydaemon();

    return 0;
}

Linux守护进程(精灵进程)

daemon函数

Linux守护进程(精灵进程)

#include <unistd.h>


int main()
{
    daemon(0, 0); 
    while(1)
    {}  
    return 0;
}