system,popen函式與fork的區別

2021-08-17 17:56:51 字數 3224 閱讀 2712

說明:

①system函式在執行的過程中經過fork—>exec—>wait,但system在執行的過程中會一直等待,直到shell執行完才退出,所以system為序列執行

②system在執行的過程中對sigchld、sigint、sigquit都做了處理

③sigchld是子程序在退出的時候給父程序發的乙個訊號,system中遮蔽了sigchld訊號,原因是為了system呼叫能夠及時的退出並且能夠正確獲取子程序的退出狀態,成功**子程序

說明:

①popen函式在執行時不需要等待shell執行完才退出,所以popen是並行執行

②popen在執行時對sigchld、sigint、sigquit不做處理

③popen建立的子程序如果不執行pclose,popen建立的子程序就會變成殭屍程序

④popen用建立管道的方式啟動乙個程序,並呼叫shell。因為管道是單向的,所以type引數只能定義成唯讀或只寫,結果流也相應的是唯讀或只寫;command引數是乙個字串指標,指向的是乙個以null結束符結尾的字串,這個字串包含了乙個shell命令,這個命令被送到/bin/sh以-c引數執行,即由shell執行;type引數也是乙個指向以null結束符結尾的字串指標,這個字串以』r』或』w』指明。

⑤popen沒有遮蔽sigchld,原因是popen是並行的,如果呼叫程序在pclose之前執行乙個wait操作的話就會獲取到popen建立的子程序狀態,這樣在呼叫pclose的時候就會**子程序失敗,返回-1,同時設定error為echld,標誌pclose無法獲取子程序狀態。

⑥ popen函式的返回值是乙個普通的標準i/o流, 它只能用 pclose函式來關閉, 而不是 fclose 函式. 向這個流的寫入被轉化為對 command 命令的標準輸入; 而 command 命令的標準輸出則是和呼叫 popen, 函式的程序相同,除非這個被command命令自己改變. 相反的, 讀取乙個 「被popen了的」 流, 就相當於讀取 command 命令的標準輸出, 而 command 的標準輸入則是和呼叫 popen, 函式的程序相同.

fork用來建立乙個子程序,父子程序共享**,對於資料段和堆疊段,系統將父程序複製乙份給子程序。子程序一旦開始執行,雖然繼承了父程序的所有資料,但實際上資料已經分開了,互不影響,即不再共享資料。如果要讓兩個程序共享一些資料,就要使用一些函式(shmget,shmat,shmdt等)實現。

事實上,目前大多數的unix系統在實現上並沒有作真正的copy。一般地,cpu都是以「頁」為單位分配空間的,像intel的cpu,其一頁在通常情況下是4k位元組大小,而無論是資料段還是堆疊段都是由許多「頁」構成的,fork函式複製這兩個段,只是「邏輯」上的,並非「物理」上的,也就是說,實際執行fork時,物理空間上兩個程序的資料段和堆疊段都還是共享著的,當有乙個程序寫了某個資料時,這時兩個程序之間的資料才有了區別,系統就將有區別的「頁」從物理上也分開。系統在空間上的開銷就可以達到最小。

vfork和fork一樣,也是建立乙個子程序,但是它並不將父程序的位址空間完全複製到子程序中,不會複製頁表。因為子程序會立即呼叫exec,於是也就不會存放該位址空間。不過在子程序中呼叫exec或exit之前,他在父程序的空間中執行。

為什麼會有vfork,因為以前的fork當它建立乙個子程序時,將會建立乙個新的位址空間,並且拷貝父程序的資源,而往往在子程序中會執行exec呼叫,這樣,前面的拷貝工作就是白費力氣了,這種情況下,聰明的人就想出了vfork,它產生的子程序剛開始暫時與父程序共享位址空間(其實就是執行緒的概念了),因為這時候子程序在父程序的位址空間中執行,所以子程序不能進行寫操作,並且在兒子「霸佔」著老子的房子時候,要委屈老子一下了,讓他在外面歇著(阻塞),一旦兒子執行了exec或者exit後,相當於兒子買了自己的房子了,這時候就相當於分家了。

vfork和fork之間的另乙個區別是:

vfork保證子程序先執行,在她呼叫exec或exit之後父程序才可能被排程執行。如果在呼叫這兩個函式之前子程序依賴於父程序的進一步動作,則會導致死鎖。

由此可見,這個系統呼叫是用來啟動乙個新的應用程式。其次,子程序在vfork()返回後直接執行在父程序的棧空間,並使用父程序的記憶體和資料。這意味著子程序可能破壞父程序的資料結構或棧,造成失敗。

為了避免這些問題,需要確保一旦呼叫vfork(),子程序就不從當前的棧框架中返回,並且如果子程序改變了父程序的資料結構就不能呼叫exit函式。子程序還必須避免改變全域性資料結構或全域性變數中的任何資訊,因為這些改變都有可能使父程序不能繼續。

通常,如果應用程式不是在fork()之後立即呼叫exec(),就有必要在fork()被替換成vfork()之前做仔細的檢查。

用fork函式建立子程序後,子程序往往要呼叫一種exec函式以執行另乙個程式,當程序呼叫一種exec函式時,該程序完全由新程式代換,而新程式則從其main函式開始執行,因為呼叫exec並不建立新程序,所以前後的程序id 並未改變,exec只是用另乙個新程式替換了當前程序的正文,資料,堆和棧段。

乙個程序一旦呼叫exec類函式,它本身就「死亡」了,系統把**段替換成新的程式的**,廢棄原有的資料段和堆疊段,並為新程式分配新的資料段與堆疊段,唯一留下的,就是程序號,也就是說,對系統而言,還是同乙個程序,不過已經是另乙個程式了。不過exec類函式中有的還允許繼承環境變數之類的資訊,這個通過exec系列函式中的一部分函式的引數可以得到。

system ,popen 函式呼叫

包含標頭檔案 include函式原型 int system const char command 作用 執行命令 返回值 1.失敗返回 1 2.當命令不能執行返回127 3.命令執行成功返回程序狀態值 包含標頭檔案 include函式原型 file popen const char command,...

F函式(水題)

問題描述 最近cyz 一直在研究乙個函式,函式是這樣的 if x 100 f x f f x 11 if x 101 f x x 10 現在cyz 需要知道一些值對應的函式值。輸入格式 輸入檔案包括若干行 最多2500000行 每行乙個正整數x x 1000000 最後一行以0結束.注意0不是要求的...

F 的建構函式

f 的建構函式 f 是.net中的函式程式語言,雖然,為了跟其它.net語言有更好的協作關係,f 本身也有相當的物件導向的功能,但是並不完整,有一些功能限制。譬如,不支援 protected 訪問控制。再如,或算是一種特色,多建構函式中,必須其中乙個為主建構函式,而其他建構函式只能呼叫主建構函式,這...