2011-02-23 109 views
5

我必須編寫使用pipe()來創建進程的程序。fork(),pipe()和exec()進程創建和通信

我的第一個任務是編寫一個父進程,它使用fork()函數生成四個子進程。

一旦fork()成功,將子進程替換爲另一個進程rover1, rover2, rover3, and rover4,儘管它們都具有相同的代碼。

過程的功能如下。

  1. 每個子進程最初都有自己的編號。它從父母收到一個新號碼。使用以下公式它創建其自己的新的數目如下,並將其轉發到父:

    mynumber = (3 * mynumber + 4 * numberreceived)/7

  2. 該過程繼續直到母體發送,該系統是穩定的消息。父母也有其初始號碼。它接收所有的孩子的數量和計算它的新號碼如下:

    mynumber = (3 * mynumber + numbers sent by all the children)/7

  3. 父將這個號碼發送到它的所有兒童。這個過程將繼續,直到父母發現其號碼不再改變。那時它會告訴孩子系統已經變得穩定。

這就是我所做的,但我的教授說我必須使用exec()來執行子進程,並用另一個子進程替換子進程。我不知道如何使用exec()。你能幫我解決這個問題嗎?

我只附加第一代子代。

// I included stdio.h, unistd.h stdlib.h and errno.h 
int main(void) 
{ 
    // Values returned from the four fork() calls 
    pid_t rover1, rover2, rover3, rover4; 

    int parentnumber, mynumber1, mynumber2, mynumber3, mynumber4; 

    int childownnumber1 = 0, status = 1, childownnumber2 = 0, 
     childownnumber3 = 0, childownnumber4 = 0, numberreceived = 0; 

    printf("Enter parent number: "); 
    printf("%d", parentnumber); 
    printf("Enter each children number"); 
    printf("%d %d %d %d", mynumber1, mynumber2, mynumber3, mynumber4); 

    // Create pipes for communication between child and parent 
    int p1[2], p2[2]; 
    // Attempt to open pipe 
    if (pipe(p1) == -1) { 
    perror("pipe call error"); 
    exit(1); 
    } 
    // Attempt to open pipe 
    if (pipe(p2) == -1) { 
    perror("pipe call error"); 
    exit(1); 
    } 

    // Parent process generates 4 child processes 
    rover1 = fork(); 

    // if fork() returns 0, we're in the child process; 
    // call exec() for each child to replace itself with another process 
    if (rover1 == 0) { 
    for(; numberreceived != 1;) { 
     close(p1[1]); // Close write end of pipe 
     close(p2[0]); // Close read end of second pipe 

     // Read parent's number from pipe 
     read(p1[0], &numberreceived, sizeof(int)); 

     if (numberreceived == 1) { 
     // System stable, end child process 
     close(p1[0]); 
     close(p2[1]); 
     _exit(0); // End child process 
     } 

     mynumber1 = (int)((3*mynumber1 + 4*numberreceived)/7.0); 

     printf("\nrover1 number: "); 
     printf("%i", mynumber1); 

     // Write to pipe 
     write(p2[1], &mynumber1, sizeof(int));  
    }  
    } 
    /* Error: 
    * If fork() returns a negative number, an error happened; 
    * output error message 
    */ 
    if (rover1 < 0) { 
    fprintf(stderr, 
      "can't fork, child process 1 not created, error %d\n", 
      errno); 
    exit(EXIT_FAILURE); 
    } 
} 
+0

是一個什麼樣的子進程都應該包含在'roverX'可執行文件中做的功能? – user470379 2011-02-23 16:55:03

+0

@ user470379-是的,我想。 – cool 2011-02-23 17:00:01

回答

2

exec系列函數是用來用新的替換過程當前進程。注意使用這個詞取代。一旦調用exec,當前進程就會消失,新進程開始。如果要創建單獨的進程,則必須先在子進程中新建二進制文件,然後再使用exec

使用exec函數與從命令行執行程序類似。要執行的程序以及傳遞給程序的參數在調用exec函數時提供。

例如,以下exec命令*是等同於隨後的外殼命令:

execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);

/bin/ls -r -t -l

*注意, 「爲arg0」 爲命令/文件名執行


由於這是作業,所以重要的是要對這個過程有一個很好的理解。你可以通過pipefork,並且exec有幾個教程組合的閱讀文檔,開始更好地瞭解每一個步驟。

以下鏈接應該幫助你開始:

+0

@ jschmier-感謝所有這些鏈接。我將如上使用exec函數。 – cool 2011-02-23 23:54:47

1

如果您應該使用exec,那麼您應該將程序分成兩個二進制文件。

基本上,現在得到由孩子執行的代碼應該是在第二二進制,應exec被調用。

在調用exec系列函數之一之前,還需要使用dup2將管道描述符重定向到新進程的標準輸入/輸出。這樣,得到exec'd的第二個二進制代碼不會知道管道,只會讀/寫標準輸入/輸出。

這也是值得注意的是,一些你現在正在使用的子進程中的數據是從父通過fork繼承。當使用exec時,孩子不會共享父母的數據或代碼,所以也可以考慮通過管道傳輸所需的數據。

+0

我現在就要這樣做。 – cool 2011-02-23 23:52:46