做網(wǎng)站需要寬帶網(wǎng)推是什么
文章目錄
- 一、前臺(tái)進(jìn)程和后臺(tái)進(jìn)程
- 二、Linux 的進(jìn)程間關(guān)系
- 三、setsid——將當(dāng)前進(jìn)程設(shè)置為守護(hù)進(jìn)程
- 四、daemon——設(shè)置為守護(hù)進(jìn)程
- 五、結(jié)語
一、前臺(tái)進(jìn)程和后臺(tái)進(jìn)程
Linux
中每一次用戶登錄都是一個(gè) session
,一個(gè) session
中只能有一個(gè)前臺(tái)進(jìn)程在運(yùn)行,鍵盤信號(hào)只能發(fā)送給前臺(tái)進(jìn)程,其中誰擁有鍵盤文件誰就是前臺(tái)進(jìn)程。./process &
表示啟動(dòng)一個(gè)后臺(tái)進(jìn)程,后臺(tái)進(jìn)程和前臺(tái)進(jìn)程可以同時(shí)向顯示器進(jìn)行打印。
jobs
查看后臺(tái)進(jìn)程。
fg 后臺(tái)任務(wù)號(hào)
將一個(gè)后臺(tái)進(jìn)程提到前臺(tái)。如果 ctrl+z
將一個(gè)前臺(tái)進(jìn)程給暫停了,那么操作系統(tǒng)會(huì)把 bash
提到前臺(tái)來,并且把暫停的進(jìn)程放到后臺(tái)。在命令行中前臺(tái)進(jìn)程一定要存在。bg 后臺(tái)任務(wù)號(hào)
將一個(gè)因?yàn)闀和6环诺胶笈_(tái)的任務(wù)重新啟動(dòng),啟動(dòng)后是在后臺(tái)運(yùn)行。
二、Linux 的進(jìn)程間關(guān)系
其中 PGID
是進(jìn)程組 ID,一個(gè)任務(wù)會(huì)對(duì)應(yīng)一個(gè)進(jìn)程組,一個(gè)任務(wù)可能需要幾個(gè)進(jìn)程共同來完成。多個(gè)任務(wù)(進(jìn)程組),在同一個(gè) session
內(nèi)啟動(dòng)的,sid
是一樣的,該 sid
其實(shí)就是操作系統(tǒng)為該會(huì)話所創(chuàng)建的 bash
的 pid
我們?cè)?Xshell 上關(guān)閉連接(退出登錄)后,操作系統(tǒng)并沒有把之前登錄創(chuàng)建的 session
全部清理掉,沒有把該 session
下的后臺(tái)進(jìn)程全部終止掉,但是在其他一些操作系統(tǒng)上,例如 Windows
,它的注銷功能,就是把當(dāng)前 session
中的全部進(jìn)程全部終止。為了避免出現(xiàn)用戶退出后,進(jìn)程被終止,這里引出守護(hù)進(jìn)程的概念,所謂守護(hù)進(jìn)程,就是該進(jìn)程自成進(jìn)程組,自成會(huì)話。
三、setsid——將當(dāng)前進(jìn)程設(shè)置為守護(hù)進(jìn)程
#include <unistd.h>pid_t setsid(void);
- 返回值:成功,返回一個(gè)新的
sid
,一般都是當(dāng)前進(jìn)程的pid
。失敗,-1被返回,錯(cuò)誤碼被設(shè)置。 - 注意:調(diào)用該函數(shù)的進(jìn)程不能是某個(gè)進(jìn)程組的組長(zhǎng)。而我們一般直接在命令行
./
執(zhí)行的某個(gè)可執(zhí)行文件,都是自成進(jìn)程組的,自己就是進(jìn)程組的組長(zhǎng),所以要向?qū)崿F(xiàn)守護(hù)進(jìn)程,非常重要的一步就是fork
創(chuàng)建子進(jìn)程,然后讓父進(jìn)程退出,此時(shí)子進(jìn)程的組 ID 就是父進(jìn)程的 PID,而不是自己的 PID,此時(shí)就可以在子進(jìn)程中調(diào)用setsid
函數(shù)。守護(hù)進(jìn)程的本質(zhì)也是孤兒進(jìn)程,它會(huì)被操作系統(tǒng)領(lǐng)養(yǎng),但是它為自己創(chuàng)建了一個(gè)新的會(huì)話(session
),此時(shí)就不受任何用戶登錄和注銷的影響。
守護(hù)進(jìn)程的過程分為以下四步:
-
忽略其他異常信號(hào)
-
創(chuàng)建子進(jìn)程,終止父進(jìn)程,讓子進(jìn)程成為一個(gè)獨(dú)立的會(huì)話
-
更改當(dāng)前的工作目錄
-
將標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤重定向到
/dev/null
(相當(dāng)于一個(gè)垃圾箱,輸入進(jìn)程的東西都被丟棄了,并且從里面獲取不到任何輸入)
// Daemon.hpp
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>const std::string nullfile = "/dev/null";void Daemon(const std::string &cwd = "")
{// 1. 忽略其他異常信號(hào)signal(SIGCHLD, SIG_IGN); // 17號(hào)信號(hào)——子進(jìn)程退出給父進(jìn)程發(fā)送這個(gè)信號(hào)signal(SIGPIPE, SIG_IGN); // 讀端關(guān)閉寫端正常,操作系統(tǒng)會(huì)給寫端發(fā)送13號(hào)信號(hào),終止掉寫端signal(SIGSTOP, SIG_IGN); // 暫停信號(hào)// 2. 創(chuàng)建子進(jìn)程,將父進(jìn)程終止,讓子進(jìn)程變成獨(dú)立的會(huì)話if (fork() > 0)exit(0);setsid();// 3. 更改當(dāng)前的工作目錄if (!cwd.empty())chdir(cwd.c_str());// 4. 將標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯(cuò)誤重定向至 /dev/null(這就相當(dāng)于一個(gè)垃圾箱,輸入進(jìn)去的內(nèi)容都會(huì)被丟棄)int fd = open(nullfile.c_str(), O_RDWR);if(fd > 0){dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
}
小Tips:一般守護(hù)進(jìn)程的名字都以 d
結(jié)尾。
四、daemon——設(shè)置為守護(hù)進(jìn)程
daemon
函數(shù)是系統(tǒng)為我們提供的將一個(gè)進(jìn)程設(shè)置成守護(hù)進(jìn)程的函數(shù)。
#include <unistd.h>int daemon(int nochdir, int noclose);
nochdir
為 0 表示將進(jìn)程的工作目錄設(shè)置到 /
目錄。noclose
表示將標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤重定向到 /dev/null
中。
五、結(jié)語
今天的分享到這里就結(jié)束啦!如果覺得文章還不錯(cuò)的話,可以三連支持一下,春人的主頁還有很多有趣的文章,歡迎小伙伴們前去點(diǎn)評(píng),您的支持就是春人前進(jìn)的動(dòng)力!