日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python实现守护进程_守护进程原理及Python实现

發(fā)布時(shí)間:2025/3/15 python 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现守护进程_守护进程原理及Python实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

守護(hù)進(jìn)程原理及Python實(shí)現(xiàn)

守護(hù)進(jìn)程,不依賴(lài)于終端,在后臺(tái)運(yùn)行的程序,通常稱(chēng)為daemon(?di?m?n或?de?m?n)。

一些常見(jiàn)的Linux軟件通常都是已守護(hù)進(jìn)程的方式運(yùn)行,比如:

nginx

redis

memcached

守護(hù)進(jìn)程的原理:

通過(guò)fork() 復(fù)刻出子進(jìn)程,并通過(guò)setsid()創(chuàng)建新會(huì)話(huà),成為會(huì)話(huà)首領(lǐng);同時(shí)結(jié)束原來(lái)的父進(jìn)程,使得復(fù)刻出來(lái)的子進(jìn)程脫離終端而運(yùn)行。

守護(hù)進(jìn)程Python代碼實(shí)現(xiàn):

def daemon_start(self):

try:

# 第1次fork,并結(jié)束父進(jìn)程

pid = os.fork()

if pid > 0:

sys.exit(0)

except Exception as e:

sys.exit(1)

# 創(chuàng)建新會(huì)話(huà),并成為會(huì)話(huà)首領(lǐng)

os.setsid()

os.chdir(self.workdir)

os.umask(self.umask)

try:

# 第2次fork,結(jié)束當(dāng)前這個(gè)子進(jìn)程,fork出來(lái)的孫子進(jìn)程由于不是進(jìn)程首領(lǐng),無(wú)法再次獲取終端(這里的子進(jìn)程,孫子進(jìn)程都是相對(duì)于最開(kāi)始的那個(gè)初始進(jìn)程而言)

pid = os.fork()

if pid > 0:

sys.exit(0)

except Exception as e:

sys.exit(1)

def handle_exit(signum, _):

sys.exit(0)

# 孫子進(jìn)程注冊(cè)信號(hào)處理方式

signal.signal(signal.SIGINT, handle_exit)

signal.signal(signal.SIGTERM, handle_exit)

signal.signal(signal.SIGHUP, signal.SIG_IGN)

# 孫子進(jìn)程是守護(hù)進(jìn)程,不存在標(biāo)準(zhǔn)輸入輸出,所以關(guān)閉。

sys.stdin.close()

核心函數(shù)說(shuō)明:

os.fork(): 對(duì)進(jìn)程進(jìn)行復(fù)刻;值得特別注意的是fork之后,原來(lái)的進(jìn)程并沒(méi)有終止,而是繼續(xù)存在,被成為父進(jìn)程;也就是說(shuō),在fork成功后,一共會(huì)存在2個(gè)進(jìn)程,1個(gè)是原來(lái)的進(jìn)程,稱(chēng)為父進(jìn)程,1個(gè)是新創(chuàng)建的進(jìn)程,稱(chēng)為子進(jìn)程。父進(jìn)程和子進(jìn)程都會(huì)從fork的位置開(kāi)始繼續(xù)向下執(zhí)行,不同的是父進(jìn)程中,得到的fork返回值為子進(jìn)程的進(jìn)程號(hào),而子進(jìn)程中得到的是0。通過(guò)這個(gè)返回值,就能判斷哪個(gè)是父進(jìn)程,哪個(gè)是子進(jìn)程。以上這點(diǎn)值得特別注意,這與我們以往理解的程序執(zhí)行邏輯完全不同。

os.setsid():創(chuàng)建新的會(huì)話(huà),并成為會(huì)話(huà)首領(lǐng)。

os.chdir():修改當(dāng)前工作目錄路徑,防止目錄被移除導(dǎo)致守護(hù)進(jìn)程異常。

os.umask():設(shè)置文件創(chuàng)建模式屏蔽字,使得創(chuàng)建文件不受系統(tǒng)默認(rèn)權(quán)限的影響。

常見(jiàn)問(wèn)題:

1.第1次fork子進(jìn)程已經(jīng)脫離終端,為什么還要第2次fork,第2次fork是否必須?

第2次fork并不是必須的,實(shí)際上,很多流行的開(kāi)源軟件的守護(hù)進(jìn)程并沒(méi)有進(jìn)行第2次fork。第2次fork的目的在于防止第1次fork出來(lái)的進(jìn)程再次獲得終端,第2次fork后,產(chǎn)生的孫子進(jìn)程不再是會(huì)話(huà)首領(lǐng),也就沒(méi)有再次獲得終端的能力。

void daemonize(void) {

int fd;

if (fork() != 0) exit(0); /* parent exits */

setsid(); /* create a new session */

/* Every output goes to /dev/null. If Redis is daemonized but

* the 'logfile' is set to 'stdout' in the configuration file

* it will not log at all. */

if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {

dup2(fd, STDIN_FILENO);

dup2(fd, STDOUT_FILENO);

dup2(fd, STDERR_FILENO);

if (fd > STDERR_FILENO) close(fd);

}

}

2.進(jìn)程已經(jīng)脫離終端,如何讓它停止或者重啟?

每一個(gè)進(jìn)程都有一個(gè)進(jìn)程id,即pid,通常程序啟動(dòng)后,會(huì)把pid寫(xiě)入到/var/run/目錄下的某個(gè)文件里,通過(guò)發(fā)送信號(hào)量給pid,即可操作相關(guān)進(jìn)程。示例代碼中的“進(jìn)程注冊(cè)信號(hào)處理方式”就是用來(lái)響應(yīng)信號(hào)量的,守護(hù)進(jìn)程可以針對(duì)不同的信號(hào),做出不同的反應(yīng)。

總結(jié)

以上是生活随笔為你收集整理的python实现守护进程_守护进程原理及Python实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。