2010-09-26 57 views
2

我期待在C程序中運行多個併發進程。程序將接受用戶的參數,然後將每個參數作爲子進程執行。我認爲這意味着我需要做的就是確保每次都由原始父進程執行fork(),然後每個生成的子進程將同時運行,而不是按順序運行。並行進程

我正確的想這個嗎?任何人都可以讓我知道我該怎麼做呢?

+0

您在示例程序中沒有對'fork()'的任何調用。這是故意的嗎? – sth 2010-09-26 15:54:29

+0

負,只是忘了把它列入。 – mispecialist 2010-09-26 16:00:53

+1

如果wait()在循環內,它將按順序執行參數。我認爲你想要做的就是等待循環開始所有進程的工作。 – 2010-09-27 14:46:25

回答

2

請原諒我從我之前的回答(通過建議使用線程)轉移手頭的事情。由於我在這裏採取了一個全新的方向,所以我不得不把這個作爲一個單獨的答案。

短版:

請在你的程序中的以下變化:

1. length = argc;    // in place of length = sizeof(argv); 
2. execl(argv[i],argv[i],0); // in place of execvp(argv[i],0); 
3. #include <unistd.h>   // if you haven't already 

龍版本:

(1)通過可變length,我假設你想獲得參數的總數。 argv是一個pointer-to-char-pointer,因此這只是一個內存地址。如果您在程序中打印出長度,您會注意到它始終爲4(或者系統中內存地址的大小)。

所以這個:

length = sizeof(argv); 

真正應該是這樣的:

length = argc; 

argc持有的執行過程中,當傳遞的參數總數。例如,

./a.out /bin/ps /bin/ls 

給出:ARGC = (而不是,一個很常見的陷阱)

(2)與您的程序的另一個問題,是execvp電話。

的execvp的prototpye如下:

int execvp(const char *file, char *const argv[]); 

地方,ARGV是傳遞給新的命令,非常類似於在自己的程序中的argv參數列表。

你在程序中使用的是:

execvp(argv[i],0); 

假設i=1argv[1] = "/bin/ls"。 什麼這個命令的作用是查找/bin/ls可執行&一個NULL指針(0)傳遞給它。這可能會導致以下運行時錯誤:

A NULL argv[0] was passed through an exec system call. 

談到EXEC手冊頁,

The first argument, by convention, should point to the filename associated with the file being executed.

雖然不是強制性的再次傳遞文件名,你肯定不應該傳遞一個NULL指針。既然你不想傳遞任何參數,我建議您使用以下execl調用,而不是:

execl(argv[i],argv[i],0); 

請記住,所有這些呼叫最終轉化爲execve()終於&然後執行,使他們最終等同。

我鼓勵您使用man瞭解更多關於exec函數族的信息。

+0

非常感謝各位,這些都是我自己應該拿起的小事情:\我現在已經完成了這個程序,並將編輯上面的代碼以匹配最終版本。如果你可以看到任何其他錯誤,請隨時告訴我:P – mispecialist 2010-09-28 09:49:28

0

你的推理看起來是正確的。父進程將分叉相同數量的孩子,因爲有參數。

雖然用線程來做併發處理不是更高效嗎?

+0

這可能是,但我用線程的經驗比我用叉子做的還要少:) – mispecialist 2010-09-26 16:02:12

+0

夠公平的..有些東西需要看看,然後;) – 2010-09-26 16:20:29

0

我相信會做你想做的。但是...

fork()實際上並沒有在單個程序中運行多個進程。它在不同進程中運行相同程序的多個副本。如果程序之間沒有明顯的重疊,你可以直接爲每個程序分別編寫main()

2

由於您在循環中調用wait(),因此您將分支子進程 ,然後分派進程將等待它在 之前完成下一個分支。如果你想讓它們並行執行,你需要在等待之前將所有的子進程分叉 進程

編輯:你無效計算長度。 sizeof argv返回指向char的指針的大小 。此代碼

#include <stdio.h> 
#include <unistd.h> 

int main(int argc, char *argv[]) 
{ 
    int pid, i, length; 

    length = argc; 

    for(i = 1; i < length; i++) 
    { 
     printf("Argv[%d]: %s\n", i, argv[i]); //error checking 
     pid = fork(); 

     if(pid < 0) 
     { 
      printf("Fork failed.\n"); 
     }//end if 
     else if(pid == 0) 
     { 
      execvp(argv[i], 0); 
     }//end else if 
     else 
     { 
      printf("Parent process (%d)\n", getpid()); 
     }//end if-else 

    }//end for 
    wait(); 
}//end main 

似乎爲我工作的罰款:

datan:~/src/c> ./a.out /bin/ps /bin/ps /bin/ps 
Argv[1]: /bin/ps 
Parent process (12748) 
Argv[2]: /bin/ps 
Parent process (12748) 
Argv[3]: /bin/ps 
Parent process (12748) 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
12627 pts/5 00:00:01 emacs 
12748 pts/5 00:00:00 a.out 
12749 pts/5 00:00:00 ps 
12750 pts/5 00:00:00 ps 
12751 pts/5 00:00:00 ps 
datan:~/src/c> 12627 pts/5 00:00:01 emacs 
12749 pts/5 00:00:00 ps 
12750 pts/5 00:00:00 ps 
    PID TTY   TIME CMD 
6615 pts/5 00:00:00 bash 
12627 pts/5 00:00:01 emacs 
12749 pts/5 00:00:00 ps 

(雖然你可能應該等到所有的孩子,不是任何作爲這個代碼)。

+0

我曾經等待循環開始,但移動它退出不會改變任何東西,除非它需要用戶輸入才能恢復提示。 – mispecialist 2010-09-27 15:04:33

+0

我確信並行執行的ls&ps命令不會有什麼好處,它會在控制檯上產生混亂的輸出。 – 2010-09-27 15:52:15

+0

另外,sizeof argv返回指向字符指針的大小,而不是指向字符的指針。 – 2010-09-27 15:57:50