linux 進程通訊之 守護進程

守護進程(Daemon)

Daemon(精靈)進程,是linux中的後臺服務進程,一般獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的時間。通常採用以d結尾的名字。從下面的進程信息能夠看出,守護進程都是【?】。linux

colord    1160  0.0  0.2 399424 14520 ?        Ssl  6月06   0:00 /usr/lib/colord/colord

Linux後臺的一些系統服務進程,沒有控制終端,不能直接和用戶交互。不受用戶登陸,註銷的影響,一直在運做着,他們都是守護進程。如ftp服務器;nfs服務器等。shell

建立守護進程,最關鍵的一步是調用setsid函數建立一個新的會話(session),併成爲session leader。服務器

會話和進程組

會話比進程組更高一級,多個進程組對應一個會話。session

多個進程在同一個進出組,第一個進程是進程組的組長。函數

組長(父進程)不能夠建立會話,必須是組員(子進程)建立。code

能夠用【ps ajx】查看session id進程

建立會話(session)

1,建立會話的進程不能是組長進程(父進程)資源

2,建立會話成功的進程,變成組長進程(父進程)terminal

3,新會話的進程丟棄原來的終端控制get

4,創建新會話時,先調用fork,終止父進程,子進程調用建立會話的函數setsid

#include <sys/types.h>
#include <unistd.h>
pid_t setsid(void);
DESCRIPTION
       setsid()  creates a new session if the calling process is not a process
       group leader.  The calling process is the leader  of  the  new  session
       (i.e., its session ID is made the same as its process ID).  The calling
       process also becomes the process group leader of a new process group in
       the session (i.e., its process group ID is made the same as its process
       ID).

       The calling process will be the only process in the new  process  group
       and in the new session.

普通的進程爲何不是守護進程?由於,普通的進程在終端執行,當關閉終端時,終端會給這個終端裏執行的全部進程發送信號SIGHUP,這個信號的默認處理的中斷進程。因此,當終端被關閉時,因此的進程都被終止了,不能成爲守護進程。

Signal     Value     Action   Comment
──────────────────────────────────────────────────────────────────────
SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process

建立守護進程的步驟:

1,建立子進程,終止父進程

2,在子進程中調用函數setsid,來建立新會話

3,改變當前進程的目錄。chdir函數

4,從新設置文件權限的掩碼。umask函數

5,關閉0,1,2文件描述符。守護進程用不到0,1,2文件描述符。避免浪費資源。

6,開始執行守護進程的核心代碼。

7,推出守護進程,通常執行不到這裏,由於一直在循環裏。

例子:每分鐘作一個文件

#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

#define _FILE_ "%s/log/data_%ld"

void catc(int num){
  char* host = getenv("HOME");
  char buf[256] = {0};
  sprintf(buf, _FILE_, host, time(NULL));
  
  int fd = open(buf, O_WRONLY|O_CREAT, 0664);
  if(fd < 0){
    perror("open:");
    exit(1);
  }
  close(fd);
}
int main(){

  //建立子進程
  pid_t pid = fork();
  //關閉父進程
  if(pid > 0){
    exit(0);
  }

  //建立新會話
  setsid();

  //設置掩碼
  umask(0);

  //改變工做目錄
  chdir(getenv("HOME"));

  //關閉文件描述符
  close(0),close(1),close(2);

  //設置定時器
  struct itimerval it = {{60, 0}, {1, 0}};
  setitimer(ITIMER_REAL, &it, NULL);

  //捕捉信號SIGALRM
  struct sigaction act;
  act.sa_flags = 0;
  sigemptyset(&act.sa_mask);
  act.sa_handler = catc;
  sigaction(SIGALRM, &act, NULL);
  
  while(1)
    sleep(1);
}

守護進程擴展瞭解

普通的進程也能強行變成守護進程。使用命令【nohup】。

它的做用是,阻塞信號SIGHUP,也就是當終端被關閉時,信號SIGHUP被阻塞了,因此進程就沒有被終止。

nohup ./a.out >> a.log &

命令解釋:

  • ./a.out:要執行的程序
  • 把輸出重定向到a.log
  • &:後臺執行的意思
相關文章
相關標籤/搜索