守護進程

1什麼叫作守護進程shell

守護進程通常在系統引導裝入的時候啓動,在系統關閉的時候關閉,由於他們沒有控制終端,因此說他們是後臺運行的,用來執行一些日長的任務編程

利用ps -axj能夠查看,其中a是查看其餘的用戶所擁有的進程,x顯示沒有控制終端的進程狀態,-j顯示與做業有關的信息,主要是第一行的信息網絡

這個ps命令要正確 的打印,系統必須支持會話,不然不能正確的顯示,父進程是0的一般是內核進程,內核進程的生命週期存在於系統的整個生命週期中,他們以超級用戶權限運行,沒有控制終端,不能使用命令行
tcp

如何判斷是不是守護進程,當TPGID=-1的時候就是守護進程,comman命令加了[]就是系統級的守護進程,沒有加[]就是用戶級的守護進程,要注意,init並非一個內核級的守護進程,他是用戶級的守護進程的父進程ide

咱們如何斷定是否使用內核守護進程:咱們使用一個內核組件,卻不被用戶進程的上下文所調用,而且是常駐內存,咱們就應該使用內核守護進程函數

使用守護進程的大致原則:ui

若是一個進程永遠都是之後臺方式啓動,而且不能受到Shell退出影響而退出,一個正統的作法是將其建立爲守護進程(daemon)。守護進程值得是系統長期運行的後臺進程,相似Windows服務。守護進程信息經過ps –a沒法查看到,須要用到–x參數,當使spa

用這條命令的時候,每每還附上-j參數以查看做業控制信息,其中TPGID一欄爲-1就是守護進程。操作系統

2對於守護進程的編程規則命令行

  
  
  
  
  
#include "apue.h"#include <syslog.h>#include <fcntl.h>#include <sys/resource.h>void daemonize(const char *cmd){ int i,fd0,fd1,fd2; pid_t pid; struct rlimit r1; struct sigaction sa; umask(0); if(getrlimit(RLIMIT_NOFILE,&r1) < 0)  err_quit("%s:can't get file limit",cmd); if((pid = fork())<0)  err_quit("%s:can't fork",cmd); else if(pid != 0)  exit(0); setsid(); sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if(sigaction(SIGHUP,&sa,NULL) < 0)  err_quit("%s:can't ignore SIGHUP",cmd); if((pid = fork()) < 0)  err_quit("%s:can't fork",cmd); else if(pid != 0) { exit(0); } if(chdir("/") < 0)  err_quit("%s:can't change directory to /",cmd); if(r1.rlim_max == RLIM_INFINITY) r1.rlim_max = 1024; for(i = 0; i < r1.rlim_max;i++)  close(i); fd0 = open("/dev/null",O_RDWR); fd1 = dup(0); fd2 = dup(0); openlog(cmd,LOG_CONS,LOG_DAEMON); if(fd0 != 0|| fd1 != 1||fd2 != 2) { syslog(LOG_ERR,"unexpected file descriptors %d %d %d",fd0,fd1,fd2); exit(0); }}int main(){ daemonize("my "); sleep(10); return 0;}

將一個進程變成一個守護進程的方法

(1)首先應該改變的是文件模式屏蔽字,由於在本來的進程上下文中,文件屏蔽字是不必定符合規範的,並且守護進程通常須要建立一個具備特定要求的屏蔽字,因此應該本身設置一個合理的屏蔽字,若是有更加嚴格的要求通常將文件模式設置爲007

(2)調用fork,進行建立一個新的子進程,爲何要這麼作第一,若是在shell中這樣啓動一個程序,當父進程exit的時候,會讓shell認爲此程序已經執行完畢第二,這樣保證了這個進程不是一個子進程,這是使用setsid的先決條件

(3)調用setsid來進行設置一個新的會話,在建立會話的時候爲了保證不分配一個控制終端,一般會在fork一次,這樣就必定這個進程不是控制終端進程(其實在第一次fork的時候,而且使用了setsid的時候就肯定了必定不是控制終端)這樣作實際上是爲了更加肯定(能夠這樣理解)

(4)更改當前的工做目錄成爲根目錄,由於若是不更改成根目錄,原本工做的目錄其實就要一直被掛載,這在某些系統中,顯然是這樣作到,由於有可能這個操做系統會被刪除

(5)進行全部的文件描述符的關閉

(6)某些守護進程打開/dev/null等,使其映射到0,1,2

關於程序的運行的結果顯示

3守護進程出錯記錄

首先咱們進行syslog的介紹

 syslog是一種工業標準的協議,可用來記錄設備的日誌。在UNIX系統,路由器、交換機等網絡設備中,系統日誌(System Log)記錄系統中任什麼時候間發生的大小事件。管理者能夠經過查看系統記錄,隨時掌握系統情況。UNIX的系統日誌是經過syslogd這個進程記錄系統有關事件記錄,也能夠記錄應用程序運做事件。經過適當的配置,咱們還能夠實現運行syslog協議的機器間通訊,經過分析這些網絡行爲日誌,藉以追蹤掌握與設備和網絡有關的情況。

由於守護進程是沒有控制終端的,因此通常不能要求守護進程將出錯記錄寫到控制檯上,固然也不能寫到一個文件中,若是每一個守護進程都寫到一個文件中,則無疑再用的時候是很麻煩的


這是日誌系統的主要設施,這個設施被稱爲syslog設施,與用戶進程調用syslog不是一個東西,三種能夠產生日誌的方法

(1)用戶守護進程調用syslog函數產生日誌消息,這些消息被送往UNIX域數據報套接字(這是一個設備,目前先了解爲就是一個設施)而後接下來syslog是不產生UDP數據報的,要注意

(2)經過tcp/ip網絡在或者不在此係統上的進程發送消息到UDP端口54

(3)內核經過log發送到klog

其中syslogd這個守護進程讀取這三種格式的日誌消息,而且根據/etc/syslog.conf發送,該文件決定了不一樣種類的消息應該送向何處,列如緊急消息可送往系統管理員,而警告信息能夠送往一個文件

該syslog整個設備的接口(這裏的接口指的是操做整個syslog的接口,能夠往/dev/log或者UDP或者klog裏面寫,總之就是整個syslog的寫入接口,可是能夠根據選項選擇怎樣寫,寫什麼樣的小設備

主要有四個接口

#include<syslog.h>

void openlog(const char* ident,int option,int facility);

ident:通常是程序的名字,自動追加到每則日誌消息中

option:



打開日誌系統,其中這個是可選的,若是沒有調用openlog,則在第一次調用syslog的時候,自動調用openlog。    

facility:

facility可讓配置文件說明,來自不一樣設施的消息將以不一樣的方式進行處理

注意:若是不調用openlog,或者以facility爲0來調用,那麼在調用syslog,可將facility做爲priority參數的一個不分進行說明

void syslog(int priority,const char *format,....);

priority:是facility和level的組合,其中level能夠是

format:以及其餘的全部參數傳至vsprintf函數進行格式話,在format中,每一個出現的%m字符都被替換成和errno對應的字符串

void closelog(void );

用來關閉被用於與syslogd函數通訊的描述符

int setlogmask(int makdpri);

設置屏蔽字,若是被設置,則不進行屏蔽,優先級屏蔽字

列如,咱們提供一個範列

4單實例守護進程

什麼叫作單實例守護進程

由於出於須要,系統在某個時間只須要一個守護進程運行,列若有的守護進程須要排他性的訪問一個設備;好比說,cron進程在具體 的時間內運行某一個進程,此進程是守護進程,若是運行多個這樣子的守護進程,則會在相同的時間內運行多個同樣的程序,形成混輪,因此這個cron進程須要字任意一個時間內運行一個守護進程!!

守護進程採用文件-和記錄鎖實現了單實例守護進程,此方法假設,守護進程都須要建立一個文件,而且在第一個守護進程建立文件以後就對整個文件進行加鎖,使其餘的相同的守護進程不能自進行此文件的加鎖,這樣就實現了守護進程的單實例運行

  
  
  
  
  
#include "unistd.h"#include "stdlib.h"#include "fcntl.h"#include "syslog.h"#include "string.h"#include "errno.h"#include "stdio.h"#include <sys/stat.h>#define LOCKFILE "var/run/daemon.pid"#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)extern int lockfile(int);int already_running(void){ int fd; char buf[16]; fd = open(LOCKFILE,O_RDWR|O_CREAT,LOCKMODE); if(fd < 0) { syslog(LOG_ERR,"can't open :%s %s",LOCKFILE,strerror(errno)); exit(1); } if(lockfile(fd) < 0) { if(errno == EACCES || errno ==EAGAIN) { close(fd); return(1); } syslog(LOG_ERR,"can't lock %s:%s",LOCKFILE,strerror(errno)); exit(1); } ftruncate(fd,0); sprintf(buf,"%ld",(long)getpid()); write(fd,buf,strlen(buf)+1); return 0;}int main(){ already_running(); return 0;}

如以上的程序,先建立一個文件夾,而且在運用此函數時候鎖住該文件,若是再有守護進程調用的時候,則進行鎖住,而且將其寫入文件,strerror是將錯誤標誌轉換成字符串

5守護進程的慣例

在unix系統中,一般的守護進程設計一般是如此設計

(1)若是守護進程使用鎖文件,則該鎖文件一般位於/var/run目錄中。然而須要主義的是,在該目錄建立文件一般須要超級用戶的權限,鎖文件的名字一般是name.pid,例如cron守護進程鎖文件的名字是/var/run/crond.pid

(2)若是守護進程支持配置選項,那麼該配置文件通常是放在/etc上的,文件名字通常是name.cond,name是該守護進程或服務的名字,

(3)守護進程可使用命令啓動,可是該啓動命令一班是在系統初始化 的腳本中進行的,若是守護進程終止,應當自動進行重啓,而且若是一個守護進程更新了配置文件,則應該從新啓動

(4)爲了不當更改配置文件,須要中止在啓動進程的時候,某些進程將捕捉SIGHUP信號,當接受到此信號的時候,從新讀取配置文件。由於守護進程不與終端結合,他們或者是沒有控制終端的會話首進程,或者是孤兒進程組的成員,因此守護進程沒有裏有指望接受SIGHUP,所以,守護進程能夠重複使用SIGHUP






相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息