摘要:守護(hù)進(jìn)程是在一類脫離終端在后臺(tái)執(zhí)行的程序通常以結(jié)尾隨系統(tǒng)啟動(dòng)其父進(jìn)程通常是進(jìn)程一般要讓當(dāng)前程序以守護(hù)進(jìn)程形式運(yùn)行在命令后加并重定向輸出即可或者使用也可以這是直接運(yùn)行程序的方式如果是用具體語言代碼的形式來實(shí)現(xiàn)呢首先看一下守護(hù)進(jìn)程的實(shí)現(xiàn)方式創(chuàng)建
守護(hù)進(jìn)程是在一類脫離終端在后臺(tái)執(zhí)行的程序, 通常以d結(jié)尾, 隨系統(tǒng)啟動(dòng), 其父進(jìn)程(ppid)通常是init進(jìn)程
一般要讓當(dāng)前程序以守護(hù)進(jìn)程形式運(yùn)行, 在命令后加&并重定向輸出即可
$ python someprogram.py > /dev/null 2>&1 &
或者使用nohup也可以
這是直接運(yùn)行程序的方式, 如果是用具體語言代碼的形式來實(shí)現(xiàn)呢, 首先看一下守護(hù)進(jìn)程的實(shí)現(xiàn)方式
創(chuàng)建子進(jìn)程, 父進(jìn)程退出
父進(jìn)程先于子進(jìn)程退出會(huì)造成子進(jìn)程成為孤兒進(jìn)程,而每當(dāng)系統(tǒng)發(fā)現(xiàn)一個(gè)孤兒進(jìn)程時(shí),就會(huì)自動(dòng)由1號(hào)進(jìn)程(init)收養(yǎng)它,這樣,原先的子進(jìn)程就會(huì)變成init進(jìn)程的子進(jìn)程
在子進(jìn)程中創(chuàng)建新會(huì)話
更改工作目錄到/, 以便umount一個(gè)文件系統(tǒng)
重設(shè)文件權(quán)限掩碼, 以便擁有完全的寫的權(quán)限, 即重設(shè)繼承來的默認(rèn)文件權(quán)限值
調(diào)用setuid, 讓當(dāng)前進(jìn)程成為新的會(huì)話組長(zhǎng)和進(jìn)程組長(zhǎng)
執(zhí)行第二次fork
關(guān)閉文件描述符, 一般是輸入/輸出和錯(cuò)誤輸出, 重定向到/dev/null
py代碼
https://gist.github.com/jamiesun/3097215
上面守護(hù)進(jìn)程的生成步驟中涉及到了孤兒進(jìn)程
任何孤兒進(jìn)程產(chǎn)生時(shí)都會(huì)立即為系統(tǒng)進(jìn)程init自動(dòng)接收為子進(jìn)程,這一過程也被稱為“收養(yǎng)”. 但由于創(chuàng)建該進(jìn)程的進(jìn)程已不存在,所以仍應(yīng)稱之為“孤兒進(jìn)程”
與之相關(guān)的一個(gè)概念就是 僵尸進(jìn)程了. 當(dāng)子進(jìn)程退出時(shí), 父進(jìn)程需要wait/waitpid系統(tǒng)調(diào)用來讀取子進(jìn)程的exit status, 然后子進(jìn)程被系統(tǒng)回收. 如果父進(jìn)程沒有wait的話, 子進(jìn)程將變成一個(gè)"僵尸進(jìn)程", 內(nèi)核會(huì)釋放這個(gè)子進(jìn)程所有的資源,包括打開的文件占用的內(nèi)存等, 但在進(jìn)程表中仍然有一個(gè)PCB, 記錄進(jìn)程號(hào)和退出狀態(tài)等信息, 并導(dǎo)致進(jìn)程號(hào)一直被占用, 而系統(tǒng)能使用的進(jìn)程號(hào)數(shù)量是有限的(可以用ulimit查看相關(guān)限制), 如果產(chǎn)生大量僵尸進(jìn)程的話, 將因?yàn)闆]有可用的進(jìn)程號(hào)而導(dǎo)致系統(tǒng)不能產(chǎn)生新的進(jìn)程
因此很多自帶重啟功能的服務(wù)實(shí)現(xiàn)就是用wait/waitpid實(shí)現(xiàn)的.
waitpid()會(huì)暫時(shí)停止目前進(jìn)程的執(zhí)行,直到有信號(hào)來到或子進(jìn)程結(jié)束
比如tornado中fork多進(jìn)程就是這樣, 監(jiān)控子進(jìn)程的運(yùn)行狀態(tài), 當(dāng)其意外退出時(shí)自動(dòng)重啟子進(jìn)程
def fork_processes(num_processes, max_restarts=100): """Starts multiple worker processes. If ``num_processes`` is None or <= 0, we detect the number of cores available on this machine and fork that number of child processes. If ``num_processes`` is given and > 0, we fork that specific number of sub-processes. Since we use processes and not threads, there is no shared memory between any server code. Note that multiple processes are not compatible with the autoreload module (or the ``autoreload=True`` option to `tornado.web.Application` which defaults to True when ``debug=True``). When using multiple processes, no IOLoops can be created or referenced until after the call to ``fork_processes``. In each child process, ``fork_processes`` returns its *task id*, a number between 0 and ``num_processes``. Processes that exit abnormally (due to a signal or non-zero exit status) are restarted with the same id (up to ``max_restarts`` times). In the parent process, ``fork_processes`` returns None if all child processes have exited normally, but will otherwise only exit by throwing an exception. """ global _task_id assert _task_id is None if num_processes is None or num_processes <= 0: num_processes = cpu_count() if ioloop.IOLoop.initialized(): raise RuntimeError("Cannot run in multiple processes: IOLoop instance " "has already been initialized. You cannot call " "IOLoop.instance() before calling start_processes()") gen_log.info("Starting %d processes", num_processes) children = {} def start_child(i): pid = os.fork() if pid == 0: # child process _reseed_random() global _task_id _task_id = i return i else: children[pid] = i return None for i in range(num_processes): id = start_child(i) if id is not None: return id num_restarts = 0 while children: try: pid, status = os.wait() except OSError as e: if errno_from_exception(e) == errno.EINTR: continue raise if pid not in children: continue id = children.pop(pid) if os.WIFSIGNALED(status): gen_log.warning("child %d (pid %d) killed by signal %d, restarting", id, pid, os.WTERMSIG(status)) elif os.WEXITSTATUS(status) != 0: gen_log.warning("child %d (pid %d) exited with status %d, restarting", id, pid, os.WEXITSTATUS(status)) else: gen_log.info("child %d (pid %d) exited normally", id, pid) continue num_restarts += 1 if num_restarts > max_restarts: raise RuntimeError("Too many child restarts, giving up") new_id = start_child(id) if new_id is not None: return new_id # All child processes exited cleanly, so exit the master process # instead of just returning to right after the call to # fork_processes (which will probably just start up another IOLoop # unless the caller checks the return value). sys.exit(0)
參考: http://bbs.chinaunix.net/thread-4071026-1-1.html
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/37945.html
摘要:多進(jìn)程中與多進(jìn)程相關(guān)的兩個(gè)重要拓展是和。函數(shù)執(zhí)行期間,主進(jìn)程除了等待無法處理其他任務(wù),所以一般不認(rèn)為這是多進(jìn)程編程。回收子進(jìn)程有兩種方式,一種是主進(jìn)程調(diào)用函數(shù)等待子進(jìn)程結(jié)束另外一種是處理信號(hào)。 轉(zhuǎn)載請(qǐng)注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請(qǐng)求 cookie web響應(yīng) session 數(shù)據(jù)庫操作 加解...
摘要:運(yùn)行模式實(shí)現(xiàn)進(jìn)程前,需了解常見的的運(yùn)行模式通用網(wǎng)關(guān)接口模式模式命令行模式模塊模式作為服務(wù)器模塊而進(jìn)程則是使用命令行模式運(yùn)行的基本實(shí)現(xiàn)中提供了一個(gè)擴(kuò)展,可以利用操作系統(tǒng)的調(diào)用來實(shí)現(xiàn)多進(jìn)程。 應(yīng)用場(chǎng)景 一些耗時(shí)任務(wù): 大數(shù)據(jù)表分表后的統(tǒng)計(jì)信息功能 分批發(fā)送短信或郵件功能 其他可分目標(biāo)的任務(wù)功能(很多種) 所以我們就需要一個(gè)常駐內(nèi)存的任務(wù)管理工具,為了保證實(shí)時(shí)性,一方面我們讓它一直執(zhí)行任...
摘要:運(yùn)行模式實(shí)現(xiàn)進(jìn)程前,需了解常見的的運(yùn)行模式通用網(wǎng)關(guān)接口模式模式命令行模式模塊模式作為服務(wù)器模塊而進(jìn)程則是使用命令行模式運(yùn)行的基本實(shí)現(xiàn)中提供了一個(gè)擴(kuò)展,可以利用操作系統(tǒng)的調(diào)用來實(shí)現(xiàn)多進(jìn)程。 應(yīng)用場(chǎng)景 一些耗時(shí)任務(wù): 大數(shù)據(jù)表分表后的統(tǒng)計(jì)信息功能 分批發(fā)送短信或郵件功能 其他可分目標(biāo)的任務(wù)功能(很多種) 所以我們就需要一個(gè)常駐內(nèi)存的任務(wù)管理工具,為了保證實(shí)時(shí)性,一方面我們讓它一直執(zhí)行任...
閱讀 2577·2021-11-25 09:43
閱讀 1849·2021-09-22 15:26
閱讀 3697·2019-08-30 15:56
閱讀 1703·2019-08-30 15:55
閱讀 1889·2019-08-30 15:54
閱讀 806·2019-08-30 15:52
閱讀 3135·2019-08-29 16:23
閱讀 886·2019-08-29 12:43