Linux系統編程(六)守護進程
- 一、進程組
- 概念
- 二、會話
- 創建會話的條件
- 守護進程
- 概念
- 守護進程模型
- 創建守護進程
一、進程組
概念
進程組,也稱之為作業。代表一個或多個進程的集合。每個進程都屬于一個進程組。
當父進程,創建子進程的時候,默認子進程與父進程屬于同一進程組。進程組ID == 第一個進程ID(組長進程)。所以,組長進程標識:其進程組ID == 其進程ID
組長進程可以創建一個進程組,創建該進程組中的進程,然后終止。只要進程組中有一個進程存在,進程組就存在,與組長進程是否終止無關。
進程組生存期:進程組創建到最后一個進程離開(終止或轉移到另一個進程組)。
一個進程可以為自己或子進程設置進程組ID
二、會話
創建會話的條件
- 調用進程不能是進程組組長,該進程變成新會話首進程(session header)
- 該進程成為一個新進程組的組長進程。
- 需有root權限(ubuntu不需要)
- 新會話丟棄原有的控制終端,該會話沒有控制終端
- 該調用進程是組長進程,則出錯返回
- 建立新會話時,先調用fork, 父進程終止,子進程調用setsid
守護進程
概念
Daemon(精靈)進程,是Linux中的后臺服務進程,通常獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。一般采用以d結尾的名字。
Linux后臺的一些系統服務進程,沒有控制終端,不能直接和用戶交互。不受用戶登錄、注銷的影響,一直在運行著,他們都是守護進程。如:預讀入緩輸出機制的實現;ftp服務器;nfs服務器等。
創建守護進程,最關鍵的一步是調用setsid函數創建一個新的Session,并成為Session Leader。
守護進程模型
- 創建子進程,父進程退出
所有工作在子進程中進行形式上脫離了控制終端 - 在子進程中創建新會話
setsid()函數
使子進程完全獨立出來,脫離控制 - 改變當前目錄為根目錄
chdir()函數
防止占用可卸載的文件系統
也可以換成其它路徑 - 重設文件權限掩碼
umask()函數
防止繼承的文件創建屏蔽字拒絕某些權限
增加守護進程靈活性 - 關閉文件描述符
繼承的打開文件不會用到,浪費系統資源,無法卸載 - 開始執行守護進程核心工作
- 守護進程退出處理程序模型
創建守護進程
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include<time.h>
#include <errno.h>
#include <sys/time.h>
#include <memory.h>void handler(int signo)
{time_t now; //實例化time_t結構struct tm* timenow; //實例化tm結構指針time(&now);//time函數讀取現在的時間(國際標準時間非北京時間),然后傳值給nowtimenow = localtime(&now);//localtime函數把從time取得的時間now換算成你電腦中的時間(就是你設置的地區)char buf[50] = {0};sprintf(buf,"%s\n" ,asctime(timenow));int fd;fd = open("./time.txt", O_CREAT | O_RDWR,0644);if (fd == -1){perror("file error:");exit(1);}lseek(fd, 0, SEEK_END);int ret=write(fd,buf,sizeof(buf));if (ret < 0 && errno == EINTR){perror("write error:");}memset(buf,0,sizeof(buf));printf("write success \n");}void mydaemond(void)
{pid_t pid, sid;int ret;pid = fork();if (pid < 0){perror("pid error:");exit(1);}else if (pid == 0){sid = setsid();if (sid == -1){perror("sid error:");exit(1);}//ret = chdir("/home/");//if (ret < 0)//{// perror("chdir error:");// exit(1);//}umask(0002);//關閉文件描述符close(STDIN_FILENO);open("/dev/null", O_RDWR);dup2(0, STDOUT_FILENO);dup2(0, STDERR_FILENO);//安裝信號struct sigaction act;act.sa_flags = 0;sigemptyset(&act.sa_mask);act.sa_handler = handler;sigaction(SIGALRM, &act, NULL);itimerval it;it.it_interval.tv_sec = 2;it.it_interval.tv_usec = 0;it.it_value.tv_sec = 2;it.it_value.tv_usec = 0;//啟用時間setitimer(ITIMER_REAL, &it, NULL);}else{exit(1);}
}int main()
{mydaemond();while (1);return 0;
}
使用守護進程實現每兩秒打印當前時間到文件中