A. 關於父子進程的執行順序和執行過程
(1)fork
函數用於從已存在進程中創建一個新進程。新進程稱為子進程,而原進程稱為父進
程。這兩個分別帶回它們各自的返回值,其中父進程的返回值是子進程的進程號,而子進程
則返回
0,大於0則是父進程。因此,可以通過返回值來判定該進程是父進程還是子進程。
使用 fork
函數得到的子進程是父進程的一個復製品,它從父進程處繼承了整個進程的地
址空間,包括進程上下文、進程堆棧、內存信息、打開的文件描述符、信號控制設定、進程
優先順序、進程組號、當前工作目錄、根目錄、資源限制、控制終端等,而子進程所獨有的只
有它的進程號、資源使用和計時器等。因此可以看出,使用
fork
函數的代價是很大的,它復
制了父進程中的代碼段、數據段和堆棧段里的大部分內容,使得
fork
函數的執行速度並不
很快。
(2)所以他們是同時進行的,要想停止父進程或子進程 就用exit()函數退出創建子進程,父進程退出
pid=fork();
if(pid>0){
exit(0);
}
(3)如果不想退出就用wait
函數,它是用於使父進程(也就是調用
wait
的進程)阻塞,直到一個子進程結束或者該進程接到了一個指定的信號為止。如果該父進程沒有子進程或者他的子進程已經結束,
wait則就會立即返回。waitpid
的作用和 wait
一樣,但它並不一定要等待第一個終止的子進程,它還有若干選項,如可提供一個非阻塞版本的
wait
功能,也能支持作業控制。實際上
wait
函數只waitpid
函數的一個特例,在
linux 內部實現
wait
函數時直接調用的就是 waitpid
函數。它們的頭文件都是#include
<sys/types.h> #include <sys/wait.h>
B. linux 父進程創建子進程的例子
父進程為什麼要創建子進程呢?前面我們已經說過了Linux是一個多用戶操作系統,在同一時間會有許多的用戶在爭奪系統的資源.有時進程為了早一點完成任務就創建子進程來爭奪資源. 一旦子進程被創建,父子進程一起從fork處繼續執行,相互競爭系統的資源.有時候我們希望子進程繼續執行,而父進程阻塞直到子進程完成任務.這個時候我們可以調用wait或者waitpid系統調用.
#i nclude
#i nclude
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid,int *stat_loc,int options);
wait系統調用會使父進程阻塞直到一個子進程結束或者是父進程接受到了一個信號.如果沒有父進程沒有子進程或者他的子進程已經結束了wait回立即返回.成功時(因一個子進程結束)wait將返回子進程的ID,否則返回-1,並設置全局變數errno.stat_loc是子進程的退出狀態.子進程調用exit,_exit 或者是return來設置這個值. 為了得到這個值Linux定義了幾個宏來測試這個返回值.
WIFEXITED:判斷子進程退出值是非0
WEXITSTATUS:判斷子進程的退出值(當子進程退出時非0).
WIFSIGNALED:子進程由於有沒有獲得的信號而退出.
WTERMSIG:子進程沒有獲得的信號號(在WIFSIGNALED為真時才有意義).
waitpid等待指定的子進程直到子進程返回.如果pid為正值則等待指定的進程(pid).如果為0則等待任何一個組ID和調用者的組ID相同的進程.為-1時等同於wait調用.小於-1時等待任何一個組ID等於pid絕對值的進程. stat_loc和wait的意義一樣. options可以決定父進程的狀態.可以取兩個值 WNOHANG:父進程立即返回當沒有子進程存在時. WUNTACHED:當子進程結束時waitpid返回,但是子進程的退出狀態不可得到.
父進程創建子進程後,子進程一般要執行不同的程序.為了調用系統程序,我們可以使用系統調用exec族調用.exec族調用有著5個函數.
#i nclude
int execl(const char *path,const char *arg,…);
int execlp(const char *file,const char *arg,…);
int execle(const char *path,const char *arg,…);
int execv(const char *path,char *const argv[]);
int execvp(const char *file,char *const argv[]):
exec族調用可以執行給定程序.關於exec族調用的詳細解說可以參考系統手冊(man execl). 下面我們來學習一個實例.注意編譯的時候要加 -lm以便連接數學函數庫.
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
void main(void)
{
pid_t child;
int status;
printf(」This will demostrate how to get child status\n」);
if((child=fork())==-1)
{
printf(」Fork Error :%s\n」,strerror(errno));
exit(1);
}
else if(child==0)
{
int i;
printf(」I am the child:%ld\n」,getpid());
for(i=0;i<1000000;i++) sin(i);
i=5;
printf(」I exit with %d\n」,i);
exit(i);
}
while(((child=wait(&status))==-1)&(errno==EINTR));
if(child==-1)
printf(」Wait Error:%s\n」,strerror(errno));
else if(!status)
printf(」Child %ld terminated normally return status is zero\n」,
child);
else if(WIFEXITED(status))
printf(」Child %ld terminated normally return status is %d\n」,
child,WEXITSTATUS(status));
else if(WIFSIGNALED(status))
printf(」Child %ld terminated e to signal %d znot caught\n」,
child,WTERMSIG(status));
}
strerror函數會返回一個指定的錯誤號的錯誤信息的字元串.
C. 管道通信中如何實現對管道的互斥使用父子進程的同步又是如何實現的
廠長,腸長,懸賞分給我吧,找了好久的呢~
.
~。父子進程的同步主要表現在兩個方面:1,父進程讀出之前確定管道中有數據,否則阻塞自己,這一點通過系統調用wait()函數既可以實現,當子進程結束時父進程才執行,那麼此時管道中肯定有子進程寫入的數據了;2,子進程在寫入之前要確定管道中的數據已被父進程讀出,否則不能寫入或者阻塞自己。這可以通過進程見的互斥來間接辦到,因為子進程間的互斥,所以每個子進程在執行開始都對管道pipe加鎖,並且子進程在向管道中寫入數據後還有調用sleep()系統用調用睡眠若干時間,那麼就可保證父進程能夠從管道中讀出數據,然後下一子進程才能寫入。
D. C語言中 怎麼實現雙線程 或者 父子線程啊
運行一個程序,這個運行實體就是一個「進程」。
例如,用滑鼠雙擊IE瀏覽器的圖標,你運行了一個IE「進程」。第一個窗未關,你又用滑鼠雙擊IE瀏覽器的圖標,又出來一個瀏覽器的窗。這時,你運行了同一個程序的兩個進程。
對於自己寫的程序也如此。運行它,這個運行實體就是一個「進程」。同時運行兩個,就是兩個進程。計算機分別對兩個進程分配資源,直到進程結束,收回資源。
線程是進程里真真跑的線路,真真執行的運算,每個進程有一個主線程。進程里可以開第二第三條新的執行線路,gcc 用 pthread_create(),VC++ 用 CreateThread(), 這就叫雙線程和多線程。進程是線程的容器,同一進程的線程共享它們進程的資源。線程里建的線程就是父子線程。
兩個或多個進程協同工作時,需要互相交換信息,有些情況下進程間交換的少量信息,有些情況下進程間交換大批信息。這就要通訊。通訊方式不止一種。管道就是一種。VC++ 用 CreatePipe() 函數建立。
管道的實質是一個共享文件,可藉助於文件系統的機制實現,創建、打開、關閉和讀寫.
一個進程正在使用某個管道寫入或讀出數據時,另一個進程就必須等待. 發送者和接收者雙方必須知道對方是否存在,如果對方已經不存在,就沒有必要再發送信息.,發送信息和接收信息之間要協調,當寫進程把一定數量的數據寫入管道,就去睡眠等待,直到讀進程取走數據後,把它喚醒。
VC++ 線程例子:
#include <windows.h>
#include <iostream.h>
DWORD WINAPI fun1(LPVOID lp);
DWORD WINAPI fun2(LPVOID lp);
int piao=500;
int main()
{
HANDLE pthread1,pthread2;
pthread1=CreateThread(0,0,fun1,0,0,0);
pthread2=CreateThread(0,0,fun2,0,0,0);
CloseHandle(pthread1);
CloseHandle(pthread2);
Sleep(3000);
return 0;
}
DWORD WINAPI fun1(LPVOID lp)
{
while(1)
{
if(piao>0)
cout<< "thread-1-"<< piao--<<endl;
else
break;
}
return 0;
}
DWORD WINAPI fun2(LPVOID lp)
{
while(1)
{
if(piao>0)
cout<<"thread-2-"<<piao--<<endl;
else
break;
}
return 0;
}
===================================
建管道函數原形:
BOOL CreatePipe(
PHANDLE hReadPipe, // read handle
PHANDLE hWritePipe, // write handle
LPSECURITY_ATTRIBUTES lpPipeAttributes, // security attributes
DWORD nSize // pipe size
);
E. linux終端下使用pipe實現父子進程交互
看這個問題好久都沒人回答。。。
挺簡單的,fork一子一父進程,父進程循環讀入文件內容,並寫進道管道裡面,子進程循環從管道接收然後列印出來。
擼碼辛苦,望採納。
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>
intmain()
{
pid_tresult;
intn,num;
intpipe_fd[2];
intfd;
charbuf1[100],buf2[100];
memset(buf1,0,sizeof(buf1));
memset(buf2,0,sizeof(buf2));
fd=open("/home/w.c",O_RDONLY);
if(pipe(pipe_fd)<0)
{
printf("error! ");
return-1;
}
result=fork();
if(result<0)
{
printf("error! ");
exit(0);
}
elseif(result==0)
{
close(pipe_fd[1]);
while((n=read(pipe_fd[0],buf1,99))>0)
{
buf1[n]='