多程序程式設計

2022-05-09 18:48:42 字數 4261 閱讀 9959

linux下乙個程序在記憶體裡有三部份的資料,就是「資料段」,「堆疊段」和「**段」,其實學過組合語言的人一定知道,一般的cpu象i386,都有上述三種段暫存器,以方便作業系統的執行。「**段」,顧名思義,就是存放了程式**的資料,假如機器中有數個程序執行相同的乙個程式,那麼它們就可以使用同一

個**段。

堆疊段存放的就是子程式的返回位址、子程式的引數以及程式的區域性變數。而資料段則存放程式的全域性變數,常數以及動態資料分配的資料空間(比如用malloc之類的函式取得的空間)。這其中有許多細節問題,這裡限於篇幅就不多介紹了。系統如果同時執行數個相同的程式,它們之間就不能使用同乙個堆疊段和資料 段。

(二) 如何使用fork

在linux下產生新的程序的系統呼叫就是fork函式,這個函式名是英文中「分叉」的意思。為什麼取這個名字呢?因為乙個程序在執行中,如果使用了fork,就產生了另乙個程序,於是程序就「分叉」了,所以這個名字取得很形象。下面就看看如何具體使用fork,這段程式演示了使用fork的基本框架:

#include #include#includeusing namespace std;

int main()

else

}else

close(fd);

} else

return 0;

}

#include #include #include #include #include #include #include #include

int main()

else

printf("please input a number to unlock the file.\n");

scanf("%d", &i);

if (flock(fd, lock_un) == 0)

else

close(fd);

} else

return 0;

}

程式執行後,你就能看到螢幕上交替出現子程序與父程序各列印出的一千條資訊了。如果程式還在執行中 ,你用ps命令就能看到系統中有兩個它在執行了。

那麼呼叫這個fork函式時發生了什麼呢?乙個程式一呼叫fork函式,系統就為乙個新的程序準備了前述三個段,首先,系統讓新的程序與舊的程序使用同乙個**段,因為它們的程式還是相同的,對於資料段和堆疊段,系統則複製乙份給新的程序,這樣,父程序的所有資料都可以留給子程序,但是,子程序一旦開始執行,雖然它繼承了父程序的一切資料,但實際上資料卻已經分開,相互之間不再有影響了,也就是說,它們之間不再共享任何資料了。而如果兩個程序要共享什麼資料的話,就要使用另一套函式(shmget,shmat,shmdt等)來操作。現在,已經是兩個程序了,對於父程序,fork函式返回了子程式的程序號,而對於子程式,fork函式則返回零,這樣,對於程式,只要判斷fork函式的返回值,就知道自己是處於父程序還是子程序中。

讀者也許會問,如果乙個大程式在執行中,它的資料段和堆疊都很大,一次fork就要複製一次,那麼fork 的系統開銷不是很大嗎?其實unix自有其解決的辦法,大家知道,一般cpu都是以「頁」為單位分配空間的,象intel的cpu,其一頁在通常情況下是4k位元組大小,而無論是資料段還是堆疊段都是由許多「頁」構成的, fork函式複製這兩個段,只是「邏輯」上的,並非「物理」上的,也就是說,實際執行fork時,物理空間上兩個程序的資料段和堆疊段都還是共享著的,當有乙個程序寫了某個資料時,這時兩個程序之間的資料才有了區別,系統就將有區別的「頁」從物理上也分開。系統在空間上的開銷就可以達到最小。

乙個小幽默:下面演示乙個足以"搞死"linux的小程式,其源**非常簡單:

void main()

這個程式什麼也不做,就是死迴圈地fork,其結果是程式不斷產生程序,而這些程序又不斷產生新的程序,很快,系統的程序就滿了,系統就被這麼多不斷產生的程序"撐死了"。用不著是root,任何人執行上述程式都足以讓系統死掉。哈哈,但這不是linux不安全的理由,因為只要系統管理員足夠聰明,他(或她)就可以預先給每個使用者設定可執行的最大程序數,這樣,只要不是root,任何能執行的程序數也許不足系統總的能執行和程序數的十分之一,這樣,系統管理員就能對付上述惡意的程式了。

(三) 如何啟動另一程式的執行

下面我們來看看乙個程序如何來啟動另乙個程式的執行。在linux中要使用exec類的函式,exec類的函式不止乙個,但大致相同,在linux中,它們分別是:execl,execlp,execle,execv,execve和execvp,下面我只以execlp為例,其它函式究竟與execlp有何區別,請通過manexec命令來了解它們的具體情況。

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

那麼如果我的程式想啟動另一程式的執行但自己仍想繼續執行的話,怎麼辦呢?那就是結合fork與exec的 使用。下面一段**顯示如何啟動執行其它程式:

char command[256];

void main()

else

}}

此程式從終端讀入命令並執行之,執行完成後,父程序繼續等待從終端讀入命令。熟悉dos和windows系統呼叫的朋友一定知道dos/windows也有exec類函式,其使用方法是類似的,但dos/windows還有spawn類函式,因為dos是單任務的系統,它只能將「父程序」駐留在機器內再執行「子程序」,這就是spawn類的函式。 win32已經是多工的系統了,但還保留了spawn類函式,win32中實現spawn函式的方法同前述unix中的方法差不多,開設子程序後父程序等待子程序結束後才繼續執行。unix在其一開始就是多工的系統,所以從核 心角度上講不需要spawn類函式。

另外,有乙個更簡單的執行其它程式的函式system,它是乙個較高層的函式,實際上相當於在shell環境 下執行一條命令,而exec類函式則是低層的系統呼叫。

(四) linux的程序與win32的程序/執行緒有何區別

熟悉win32程式設計的人一定知道,win32的程序管理方式與unix上有著很大區別,在unix裡,只有程序的概念 ,但在win32裡卻還有乙個「執行緒」的概念,那麼unix和win32在這裡究竟有著什麼區別呢?

unix裡的fork是七十年代unix早期的開發者經過長期在理論和實踐上的艱苦探索後取得的成果,一方面, 它使作業系統在程序管理上付出了最小的代價,另一方面,又為程式設計師提供了乙個簡潔明瞭的多程序方法。

win32裡的程序/執行緒是繼承自os/2的。在win32裡,「程序」是指乙個程式,而「執行緒」是乙個「程序」 裡的乙個執行「線索」。從核心上講,win32的多程序與unix並無多大的區別,在win32裡的執行緒才相當於unix 的程序,是乙個實際正在執行的**。但是,win32裡同乙個程序裡各個執行緒之間是共享資料段的。這才是與 unix的程序最大的不同。

int g;

dword winapi childprocess( lpvoid lpparameter )

exitthread( 0 );

};void main()

}

在win32下,使用createthread函式建立執行緒,與unix不同,執行緒不是從建立處開始執行的,而是由 createthread指定乙個函式,執行緒就從那個函式處開始執行。此程式同前面的unix程式一樣,由兩個執行緒各列印1000條資訊。threadid是子執行緒的執行緒號,另外,全域性變數g是子執行緒與父執行緒共享的,這就是與unix最大的不同之處。大家可以看出,win32的程序/執行緒要比unix複雜,在unix裡要實現類似win32的執行緒並不難,只要fork以後,讓子程序呼叫threadproc函式,並且為全域性變數開設共享資料區就行了,但在win32下就無法實現類似fork的功能了。所以現在win32下的c語言編譯器所提供的庫函式雖然已經能相容大多數unix的庫函式, 但卻仍無法實現fork。

對於多工系統,共享資料區是必要的,但也是乙個容易引起混亂的問題,在win32下,乙個程式設計師很容易忘記執行緒之間的資料是共享的這一情況,乙個執行緒修改過乙個變數後,另乙個執行緒卻又修改了它,結果引起程式出問題。但在unix下,由於變數本來並不共享,而由程式設計師來顯式地指定要共享的資料,使程式變得 更清晰與安全。

linux還有自己的乙個函式叫clone,這個函式是其它unix所沒有的,而且通常的linux也並不提供此函式(要使用此函式需自己重新編譯核心,並設定clone_actually_works_ok選項),clone函式提供了更多的建立新程序的功能,包括象完全共享資料段這樣的功能。

至於win32的「程序」概念,其含義則是「應用程式」,也就是相當於unix下的exec了。

多程序程式設計

一。多程序程式設計 1.函式學習 1 建立程序 1.函式名 fork 函式原型 pid t fork void 函式功能 建立乙個子程序 所屬標頭檔案 返回值 成功時 在父程序中返回子程序的pid 在子程序中返回是0 失敗時 子程序返回的 1 引數說明 無引數 2.函式名 vfork 函式原型 pi...

多程序程式設計

1.程序是正在執行的程式的例項 每個程序都至少包含乙個執行緒 2.電腦程式是由指令組成的 程序是這些指令的實際執行體 3.程序的狀態 被建立 就緒 執行 阻塞 掛起 終止等狀態 用subprocess模組來管理程序 import subprocess 1.呼叫subprocess.call 建立程序...

python多程序 Python多程序程式設計詳解

本文 在 python 3.6 環境下測試通過。多程序 multiprocessing 模組是在 python 2.6 版本中加入的,和多執行緒 threading 模組類似,都是用來做並行運算的。不過python既然有了threading,為什麼還要搞乙個multiprocessing呢?這是因為...