就拿linux0.11原始碼分析,從程序2的建立與銷毀舉例子。在這裡貼出的**看不懂的不要緊,我會盡量把流程說清楚,看的懂的那是最好,程式設計師的語言不就是**嗎~ ?
linux核心被載入到記憶體後,就會執行main.c
中的main
函式,建立程序0,程序0建立程序1,程序1建立程序2
void main(void)
...}
fokk
後就會建立程序1,在子程序中(程序1)fork
返回0,為什麼返回0,在這裡說的比較清楚了,
init()
由程序1開始執行。
void init(void)
...程序1執行塊···
if (pid>0)
while (pid != wait(&i))
...}
程序1裡面又要執行fork
,建立程序2,pid等於0代表的是子程序,大於0代表父程序,所以父程序(程序1)呼叫wait
wait
的定義在lib/wait.c
檔案中,
#define __library__
#include #include _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
pid_t wait(int * wait_stat)
_syscall3
宣告在unistd.h
標頭檔案中。呼叫wait
最終呼叫的是sys_waitpid
#define _syscall3(type,name,atype,a,btype,b,ctype,c) \
type name(atype a,btype b,ctype c) \
sys_waitpid
找到程序後,就會把程序的狀態設定為中斷等待態,並且重新排程schedule()
程序排程發現程序的狀態時中斷等待狀態,就不會執行該程序,需要等待下一次排程。
int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
// 若沒有找到符合要求的子程序,則返回出錯碼(子程序不存在)。
return -echild;
}
呼叫wait
後,程序1就不再cpu上執行了,此時程序2的狀態時可執行狀態,程序排程後,程序2開始執行,程序2做完自己的事後,就會執行_exit
方法,該方法對應就是sys_exit
int sys_exit(int error_code)
do_exit
主要事釋放程序占用的頁,然後把自己的狀態改為task_zombie
僵死狀態,
tell_father(current->father);
通知父程序,給父程序傳送訊號task[i]->signal |= (1<<(sigchld-1));
,不是說給父程序發訊號,父程序就會醒來,需要等待下一次程序排程schedule();
int do_exit(long code)
static void tell_father(int pid)
/* if we don't find any fathers, we just release ourselves */
/* this is not really ok. must change it to make father 1 */
printk("bad bad - no father found\n\r");
release(current); // 如果沒有找到父程序,則自己釋放
}
到這裡子程序釋放了自己的占用的記憶體頁資料,但是在程序表裡還占用程序結構,為什麼不釋放完呢,因為父程序還需要知道子程序的返回值,該返回值就存在程序結構體裡,子程序已經是僵死狀態了,這再也不會執行了,等下一次程序排程後,父程序發現收到sigchld訊號,並且是可中斷等待狀態,父程序開始甦醒,接著上次wait**處執行,也就是上面提到的sys_waitpid
,該方法找到子程序是task_zombie
的程序,釋放子程序占用的程序項。
如果父程序不呼叫wait,子程序結束後,父程序不知道子程序有沒有死,就沒有辦法釋放子程序,雖然子程序釋放了自己占用記憶體頁,但是沒有辦法釋放占用的程序結構體,子程序就會變成殭屍程序。
case task_zombie:
current->cutime += (*p)->utime;
current->cstime += (*p)->stime;
flag = (*p)->pid; // 臨時儲存子程序pid
code = (*p)->exit_code; // 取子程序的退出碼
release(*p); // 釋放該子程序
put_fs_long(code,stat_addr); // 置狀態資訊為退出碼值
return flag; // 返回子程序的pid
避免linux系統呼叫fork後產生僵死程序
殭屍程序 就是 已經結束,但是還沒有清理出去的.用kill 9 pid 也無法殺死.所以程式中應該避免出現殭屍程序.用fork之後,父程序如果沒有wait waitpid 等待子程序的話,子程序完畢後,就成了殭屍程序.但是父程序如果等待wait waitpid的話,就沒法幹別的事情了.尤其在多個子程...
為什麼baseServlet可以呼叫很多方法
servlet會先呼叫service 然後再根據service方法中的定義呼叫doget,dopost等方法 servlet中,service方法是一直存在的,因為最高層的介面servlet 像httpservlet等具體的servlet都是直接或者間接實現了這個介面 裡面就有這個方法,所以不管是怎...
呼叫close 後發生了什麼
我們考慮簡單的客戶端 伺服器通訊的場景,其典型模式為 在tcp層面表現為 我們考慮一些異常情況,客戶端上 選用 unix網路程式設計 第一卷 中的伺服器 客戶端樣例程式。伺服器部分 int main int argc,char ar 伺服器監聽9999埠,新鏈結建立後,發出當前時間,隨後呼叫clos...