Linux之守護(hù)進(jìn)程詳解
一、守護(hù)進(jìn)程的概念
我們?cè)谇懊娴牟┪摹哆M(jìn)程信號(hào)的產(chǎn)生》中提到過(guò)前臺(tái)進(jìn)程和后臺(tái)進(jìn)程的概念,它們之間的區(qū)別就是是否獲得鍵盤(pán)文件,擁有鍵盤(pán)輸入的就是前臺(tái)進(jìn)程,后臺(tái)進(jìn)程獲取不到鍵盤(pán)文件
守護(hù)進(jìn)程是 Linux 系統(tǒng)中運(yùn)行在后臺(tái)的特殊進(jìn)程,具有無(wú)終端依賴、長(zhǎng)期運(yùn)行、權(quán)限分離等特點(diǎn),通常用于實(shí)現(xiàn)系統(tǒng)服務(wù)、網(wǎng)絡(luò)服務(wù)等功能,進(jìn)行守護(hù)進(jìn)程化的進(jìn)程就是將終端關(guān)閉也不會(huì)殺死,只要服務(wù)器一直運(yùn)行,它就可以一直運(yùn)行,但可以通過(guò)kill命令殺死
二、調(diào)用接口
1、創(chuàng)建新會(huì)話
#include <unistd.h> pid_t setsid(void);
返回值:成功返回新會(huì)話id,失敗返回-1
2、守護(hù)進(jìn)程
#include <unistd.h> int daemon(int nochdir, int noclose);
返回值:成功返回0,失敗返回-1
nochdir:如果該參數(shù)的值為 0,daemon函數(shù)會(huì)將當(dāng)前工作目錄更改為根目錄(/),如果為非 0 值,則不更改當(dāng)前工作目錄noclose:如果該參數(shù)的值為 0,daemon 函數(shù)會(huì)將標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到/dev/null,如果為非 0 值,則不進(jìn)行重定向
三、進(jìn)程屬性信息

1. PPID(Parent Process ID)
- 全稱:父進(jìn)程ID
- 含義:當(dāng)前進(jìn)程的父進(jìn)程的唯一標(biāo)識(shí)符
- 作用:用于跟蹤進(jìn)程間的父子關(guān)系(例如,通過(guò)
fork()創(chuàng)建的子進(jìn)程會(huì)繼承父進(jìn)程的PPID)
2. PID(Process ID)
- 全稱:進(jìn)程ID
- 含義:操作系統(tǒng)分配給每個(gè)進(jìn)程的唯一數(shù)字標(biāo)識(shí)符(范圍通常為1~32768)
- 作用:用于區(qū)分和管理系統(tǒng)中的不同進(jìn)程(例如,通過(guò)
kill命令終止進(jìn)程)
3. PGID(Process Group ID)
- 全稱:進(jìn)程組ID
- 含義:進(jìn)程所屬的進(jìn)程組的ID,進(jìn)程組是一個(gè)或多個(gè)相關(guān)進(jìn)程的集合,一個(gè)任務(wù)對(duì)應(yīng)一個(gè)進(jìn)程組
- 作用:便于批量管理相關(guān)進(jìn)程(如停止或恢復(fù)整個(gè)進(jìn)程組)
4. SID(Session ID)
- 全稱:會(huì)話ID
- 含義:進(jìn)程所屬的會(huì)話的ID,會(huì)話由一個(gè)或多個(gè)進(jìn)程組組成,通常由登錄
shell創(chuàng)建,實(shí)際上是bash的id - 作用:管理終端會(huì)話中的所有進(jìn)程(例如,當(dāng)用戶注銷時(shí),整個(gè)會(huì)話的進(jìn)程會(huì)被終止)
5. TTY(Teletypewriter)
- 全稱:終端設(shè)備
- 含義:進(jìn)程關(guān)聯(lián)的終端設(shè)備(如
pts/0表示偽終端),若顯示為?,表示進(jìn)程無(wú)控制終端 - 作用:區(qū)分進(jìn)程是否在終端中運(yùn)行(如后臺(tái)服務(wù)通常無(wú)終端)
6. TPGID(Foreground Process Group ID)
- 全稱:前臺(tái)進(jìn)程組ID
- 含義:當(dāng)前在終端前臺(tái)運(yùn)行的進(jìn)程組的ID
- 作用:終端輸入/輸出會(huì)被分配給前臺(tái)進(jìn)程組(例如,按
Ctrl+C會(huì)中斷前臺(tái)進(jìn)程)
7. STAT(Process Status)
全稱:進(jìn)程狀態(tài)
含義:進(jìn)程的當(dāng)前狀態(tài),常見(jiàn)狀態(tài)碼包括:
R(運(yùn)行中)S(睡眠中)D(不可中斷睡眠)T(停止)Z(僵尸進(jìn)程)
作用:快速判斷進(jìn)程的運(yùn)行狀態(tài)(例如,Z表示進(jìn)程已終止但未被父進(jìn)程回收)
8. UID(User ID)
- 全稱:用戶ID
- 含義:?jiǎn)?dòng)進(jìn)程的用戶的唯一標(biāo)識(shí)符(如
root的UID為0) - 作用:用于權(quán)限控制(例如,普通用戶無(wú)法修改
root進(jìn)程)
9. TIME
- 全稱:CPU時(shí)間
- 含義:進(jìn)程自啟動(dòng)以來(lái)累計(jì)使用的CPU時(shí)間(格式為
HH:MM:SS) - 作用:衡量進(jìn)程對(duì)CPU資源的占用情況
10. COMMAND
- 全稱:命令名稱
- 含義:?jiǎn)?dòng)進(jìn)程的命令或程序名稱(如
bash、nginx) - 作用:快速識(shí)別進(jìn)程的功能(例如,通過(guò)
COMMAND列判斷是否為惡意程序)
同一個(gè)session內(nèi)啟動(dòng)的sid都一樣
同一PGID的,即一個(gè)組內(nèi)的,PID與PGID相同的被稱為組長(zhǎng)
四、深入理解守護(hù)進(jìn)程
1、實(shí)現(xiàn)過(guò)程
首先創(chuàng)建子進(jìn)程然后退出父進(jìn)程,使子進(jìn)程在后臺(tái)運(yùn)行,然后創(chuàng)建新會(huì)話,脫離掉原會(huì)話和控制終端,保證進(jìn)程不受終端信號(hào)影響,然后再重定向標(biāo)準(zhǔn)輸入輸出,確保守護(hù)進(jìn)程不與終端交互,然后變更工作目錄,忽略掉子進(jìn)程退出信號(hào)和終端停止信號(hào),所以守護(hù)進(jìn)程本質(zhì)上是一個(gè)孤兒進(jìn)程
2、實(shí)例
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <syslog.h>
void daemonize() {
// 創(chuàng)建子進(jìn)程并退出父進(jìn)程,子進(jìn)程成為孤兒進(jìn)程
pid_t pid = fork();
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS);
// 創(chuàng)建新會(huì)話,調(diào)用該函數(shù)的進(jìn)程會(huì)成為新會(huì)話的會(huì)話首進(jìn)程、新進(jìn)程組的組長(zhǎng)進(jìn)程
//并且會(huì)脫離原有的控制終端
if (setsid() == -1) exit(EXIT_FAILURE);
// 重定向標(biāo)準(zhǔn)輸入輸出
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
int fd = open("/dev/null", O_RDWR);
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
// 允許所有權(quán)限
umask(0);
// 變更工作目錄
chdir("/");
// 忽略子進(jìn)程狀態(tài)改變時(shí)發(fā)送給父進(jìn)程的信號(hào)
signal(SIGCHLD, SIG_IGN);
}
int main() {
daemonize();
while (1) {
sleep(3600); // 模擬工作
}
return 0;
}上面的過(guò)程,可以被函數(shù)daemon函數(shù)替換
#include <unistd.h>
#include <syslog.h>
int main() {
// 使用 daemon 函數(shù)將當(dāng)前進(jìn)程轉(zhuǎn)換為守護(hù)進(jìn)程
// 第一個(gè)參數(shù) 0 表示將工作目錄更改為根目錄
// 第二個(gè)參數(shù) 0 表示將標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出重定向到 /dev/null
if (daemon(0, 0) == -1) {
perror("daemon");
return 1;
}
// 模擬守護(hù)進(jìn)程持續(xù)工作
while (1) {
// 睡眠 3600 秒(1 小時(shí))
sleep(3600);
}
return 0;
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
LNMP下添加Discuz x2.5的偽靜態(tài)規(guī)則
今天一個(gè)找我配置過(guò) lnmp 環(huán)境的用戶要搭建 Discuz 論壇,但是發(fā)現(xiàn)不支持偽靜態(tài),倡萌沒(méi)怎么折騰過(guò) Discuz,百度下才知道,原來(lái)軍哥的 LNMP 環(huán)境包自帶的 DZ 規(guī)則不適用于 Discuz x2.5,記錄下對(duì)應(yīng)的偽靜態(tài)規(guī)則2016-09-09
深入理解linux下查看進(jìn)程內(nèi)存的使用情況
本篇文章是對(duì)linux下查看進(jìn)程內(nèi)存的使用情況進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
CentOS7系統(tǒng)增加swap的操作方法實(shí)例
這篇文章主要給大家介紹了關(guān)于CentOS7系統(tǒng)增加swap的操作方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用CentOS7系統(tǒng)具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

