多程序併發如何防止殭屍程序——伺服器開發
在併發伺服器設計中,很常用的一種辦法是用fork為每個連線建立子程序來單獨處理客戶端請求。
流程圖如下:
可見,在父程序中直接執行accept等待下一個連線而並沒有用wait或者waitpid來等待子程序返回。這會造成怎樣的後果呢?當子程序exit退出的時候,它並沒有真正銷燬,而是還著保留一個數據結構用來記錄它的退出狀態等資訊(因為父程序有可能會獲取該資訊)。若父程序不用wait或者waitpid等待,則此資訊會一直保留直到父程序退出。不幸的是,併發伺服器恰恰在正常情況會一直執行下去,並且不斷為每個連線創造子程序,久而久之造成嚴重的資源洩漏。所以併發伺服器必須採用某些手段來防止殭屍程序。
在子程序退出時會給父程序傳送一個SIGCHLD訊號,我們可以在父程序迴圈accept之前用signal來為SIGCHLD註冊一個回撥函式來等待子程序返回。
signal函式的宣告:
void (*signal(int signo,void (*func)(int)))(int);
這是一個含函式指標的函式宣告,它的第二個引數和返回值都是函式指標,也可以用以下宣告方式。typedef void(*sig_t) ( int );
sig_t signal(int signo,sig_t func);
注:以上兩個函式宣告是同等的。
簡單來解釋:signal第一引數填的是要處理的訊號(這裡是SIGCHLD),第二個引數是收到這個訊號要呼叫的回撥函式的指標。
具體做法如下:
void sid_child(int signo) //處理SIGCHLD訊號的回撥函式 { pid_t pid; int stat; while((pid=waitpid(-1,&stat,WNOHANG))>0); return; }
//此處省略之前socket、bind
listen(servfd,10);
signal(SIGCHLD,sid_child); //為SIGCHLD的註冊回撥函式sid_child
while(1)
{
if((cliefd=accept(servfd,(sockaddr*)0,0))<0)
{
if(errno==EINTR) continue;
else err_sys("accept call error");
}
//這裡省略fork建立子程序處理請求
}
解釋:
1、
呼叫後,當父程序收到有子程序傳來的SIGCHLD訊號,就會中斷呼叫回撥函式sid_child。signal(SIGCHLD,sid_child);
2、
while((pid=waitpid(-1,&stat,WNOHANG))>0);
在sid_child函式裡,迴圈呼叫waitpid等待子程序。
為什麼要迴圈呼叫waitpid? waitpid的用法是如何?
waitpid的宣告:
pid_t waitpid(pid_t pid,int * status,int options);
這裡挑重點的講:waitpid功能是等待某個子程序返回,waitpid第一個引數是要等待返回的子程序ID號,若填-1則代表等待任意子程序返回。第二個引數用以接受子程序終止狀態。第三個是附加選項,,WNOHANG選項的意思使函式不阻塞,無論有沒子程序退出都返回。
WNOHANG選項下waitpid的呼叫特性:
2.1、當有子程序退出且正常返回時,返回子程序ID號;
2.2、當沒有子程序退出,返回0;
2.3、當調用出錯返回-1;
又因為無論有多少子程序只要有沒處理的子程序退出,就會父程序收到且只有一個SIGCHLD,所以while((pid=waitpid(-1,&stat,WNOHANG))>0); 的意思是:只有收到SIGCHLD訊號,就迴圈等待退出的子程序,直到waitpid返回非大於零的數(代表沒有子程序退出了)。之後又返回正常的迴圈中,accept等待連線。當下次有子程序退出,父程序會再一次收到SIGCHLD。
3、
if((cliefd=accept(servfd,(sockaddr*)0,0))<0)
{
if(errno==EINTR) continue;
else err_sys("accept call error");
}
accept、write、read等都是慢系統呼叫。當伺服器阻塞在accept中時,我們知道父程序收到SIGCHLD就會發生中斷並呼叫我們註冊的回撥函式sid_child。當回撥函式返回時,慢系統呼叫的函式可能會返回一個EINTR錯誤,表明該函式在阻塞等待期間被中斷了。當然這個錯誤是我們設計預料之內的,所以我們得呼叫continue來繼續迴圈工作。
這樣就防止殭屍程序的出現。
相關推薦
多程序併發如何防止殭屍程序——伺服器開發
在併發伺服器設計中,很常用的一種辦法是用fork為每個連線建立子程序來單獨處理客戶端請求。 流程圖如下: 可見,在父程序中直接執行accept等待下一個連線而並沒有用wait或者waitpid來等待子程序返回。這會造成怎樣的後果呢?當子程序exit退出的時候,它並沒有真正
Python多程序併發操作中程序池Pool的應用
在利用Python進行系統管理的時候,特別是同時操作多個檔案目錄,或者遠端控制多臺主機,並行操作可以節約 大量的時間。當被操作物件數目不大時,可以直接利用multiprocessing中的Process動態成生多個程序,10幾個 還好,但如果是上百個,上千個目標,
如何防止殭屍程序?
1.殭屍程序:殭屍程序是當子程序比父程序先結束,而父程序又沒有回收子程序,釋放子程序佔用的資源,此時子程序將成為一個殭屍程序。如果父程序先退出 ,子程序被init接管,子程序退出後init會回收其佔用的相關資源。 2.產生原因: a. 子程序結束後向父程序發出SIGCHLD訊號,父程序預
編寫一unix程式,防止殭屍程序的出現.
殭屍程序的避免 ⒈父程序通過wait和waitpid等函式等待子程序結束,這會導致父程序掛起。 ⒉ 如果父程序很忙,那麼可以用signal函式為SIGCHLD安裝handler,因為子程序結束後
2.4 程序控制之殭屍程序和孤兒程序
學習目標:理解殭屍程序和孤兒程序形成的原因 一、孤兒程序 1. 孤兒程序: 父程序先於子程序結束,則子程序成為孤兒程序。子程序成為孤兒程序之後,init程序則會成為其新的父程序,稱為init程序領養孤兒程序。 2. 例程: 1 #include <stdio.h> 2 #incl
Linux多程序併發伺服器(TCP)
Linux多程序併發伺服器(TCP) 前言:在Linux環境下多程序的應用很多,其中最主要的就是網路/客戶伺服器。多程序伺服器是當客戶有請求時 ,伺服器用一個子程序來處理客戶請求。父程序繼續等待其它客戶的請求。這種方法的優點是當客戶有請求時 ,伺服器能及時處理客戶 ,特別是在客戶伺服
Linux學習之網路程式設計(多程序併發伺服器)
言之者無罪,聞之者足以戒。 - “詩序” 上面我們所說過的通訊都是一個伺服器一個客戶端之間的通訊,下面我們來交流一下多程序併發伺服器的相關知識 邏輯上就是這個樣子的,就是一個伺服器多個客戶端進行資料的傳輸。 1、傳送資料的函式: ssize_t send(int sockfd,
linux網路程式設計之多程序併發伺服器
1)使用多程序併發伺服器考慮的因素: (1)父程序描述最大檔案描述符的個數(父程序需要關閉accept返回的新檔案描述符) (2)系統內可建立程序的個數(與記憶體大小相關) (3)程序建立過多是否降低整體服務效能 2)多程序建立併發
嵌入式linux-sqlite3資料庫,多程序併發伺服器,線上詞典
文章目錄 1,簡介: 2,框架圖 2.1,客戶端框架 2.1,伺服器端框架 3,程式碼 3.1,客戶端程式碼 3.2,伺服器端程式碼 1,簡介: 1,線上詞典
嵌入式Linux網路程式設計,TCP多併發伺服器,TCP多執行緒併發伺服器,TCP多程序併發伺服器
文章目錄 1,TCP多執行緒併發伺服器 1.1,標頭檔案net.h 1.2,客戶端client.c 1.3,伺服器端server.c 2,TCP多程序併發伺服器 2.1,標頭檔案net.h 2.2,客
零基礎學python:併發伺服器、面向連線、多程序、多執行緒、單程序
面向連線的併發伺服器 只能同時為一個人服務 為了幫助小夥伴們更好的學習Python,小編整理了Python的相關學習視訊及學習路線圖; ,新增小編學習群943752371即可獲取 多程序併發伺服器 多程序伺服器代表:Apache伺服器 主程序中必需
linux(一)------多程序併發伺服器實現(fork)
本文實現一個多程序併發伺服器 實現思路: 利用fork()函式實現每有一個client連線時就會建立一個子程序程序與client通訊,父程序負責回收子程序的PCB 直接上程式碼! #include <stdio.h> #i
linux socket多程序併發伺服器
/***sever***/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>
linux fork多程序併發伺服器模型之C/C++程式碼實戰
在很早的文章中, 我們一起聊過伺服器如何與多個客戶端進行通訊, 那時, 我們要麼用select, 要麼用多執行緒, 卻沒有用多程序。 其實, 多程序也可以實現與多個客戶端進行通訊。 如果是在while中迴圈accept, 然後迴圈處理事情
Linux 網路程式設計 全解(四)--------多程序併發伺服器和多執行緒併發伺服器
寫在前面:這個系列也是停滯了20多天了,從今天開始再次步入正軌,以後每個週末都會陸陸續續的更新,這個系列預計完結的時間還會在大約一個月左右,今天靜下心來多整理幾篇。QQ:993650814 正文: 一、多程序併發伺服器 設計思路:當有新的客戶端連線到
TCP客戶端/伺服器網路程式設計------多程序併發模型(附帶實現)
多程序併發模型相比同步阻塞迭代模型,多程序併發模型可以避免是程式阻塞在read系統呼叫上。如果沒有客戶端來建立連線,則會阻塞在accept處。一旦某個客戶端連線建立起來,則立即開啟一個新的程序來處理與這個客戶的資料互動。避免程式阻塞在read呼叫,而影響其他客戶端的連線。缺陷
Python學習多程序併發寫入同一檔案
最近學習了Python的多程序,想到我的高德API爬蟲那個爬取讀寫速度我就心累,實在是慢,看到多程序可以充分利用CPU核數我就開始完善我的程式碼,不過過程是艱辛的,在此之中出現了很多問題,其中最大的問題是爬取的資料是正確的,但是讀寫到Excel中卻開啟是空,想了半天也沒解決,腦子笨沒辦法,不過我
Python多程序併發操作程序池Pool
目錄: multiprocessing模組 Pool類 apply apply_async map close terminate join 程序例項 multiprocessing模組 如果你打算編寫多程序的服務程式,Unix/
Linux 多工程式設計——特殊程序:殭屍程序、孤兒程序、守護程序
殭屍程序(Zombie Process) 程序已執行結束,但程序的佔用的資源未被回收,這樣的程序稱為殭屍程序。 在每個程序退出的時候,核心釋放該程序所有的資源、包括開啟的檔案、佔用的記憶體等。 但是仍然為其保留一定的資訊,這些資訊主要主要指程序控制塊的資訊(包括程序號、退出狀態、執行時
Python中建立程序的方法,以及併發並行,殭屍程序,孤兒程序的相關概念
一、併發與並行 並行:多個計算機核心在同時處理多個任務,這時多個任務間是並行關係 併發:同時處理多個任務,但是核心在多個任務間不斷地切換,達到好像都在處理執行的效果,但實際一個時間點核心只能處理其中一個任務。 二、程序 程序與執行緒是實現多工程式設計的實施方案 程序與執