我期待在C程序中運行多個併發進程。程序將接受用戶的參數,然後將每個參數作爲子進程執行。我認爲這意味着我需要做的就是確保每次都由原始父進程執行fork(),然後每個生成的子進程將同時運行,而不是按順序運行。並行進程
我正確的想這個嗎?任何人都可以讓我知道我該怎麼做呢?
我期待在C程序中運行多個併發進程。程序將接受用戶的參數,然後將每個參數作爲子進程執行。我認爲這意味着我需要做的就是確保每次都由原始父進程執行fork(),然後每個生成的子進程將同時運行,而不是按順序運行。並行進程
我正確的想這個嗎?任何人都可以讓我知道我該怎麼做呢?
請原諒我從我之前的回答(通過建議使用線程)轉移手頭的事情。由於我在這裏採取了一個全新的方向,所以我不得不把這個作爲一個單獨的答案。
短版:
請在你的程序中的以下變化:
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=1
和argv[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函數族的信息。
非常感謝各位,這些都是我自己應該拿起的小事情:\我現在已經完成了這個程序,並將編輯上面的代碼以匹配最終版本。如果你可以看到任何其他錯誤,請隨時告訴我:P – mispecialist 2010-09-28 09:49:28
你的推理看起來是正確的。父進程將分叉相同數量的孩子,因爲有參數。
雖然用線程來做併發處理不是更高效嗎?
這可能是,但我用線程的經驗比我用叉子做的還要少:) – mispecialist 2010-09-26 16:02:12
夠公平的..有些東西需要看看,然後;) – 2010-09-26 16:20:29
我相信會做你想做的。但是...
fork()
實際上並沒有在單個程序中運行多個進程。它在不同進程中運行相同程序的多個副本。如果程序之間沒有明顯的重疊,你可以直接爲每個程序分別編寫main()
。
由於您在循環中調用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
(雖然你可能應該等到所有的孩子,不是任何作爲這個代碼)。
我曾經等待循環開始,但移動它退出不會改變任何東西,除非它需要用戶輸入才能恢復提示。 – mispecialist 2010-09-27 15:04:33
我確信並行執行的ls&ps命令不會有什麼好處,它會在控制檯上產生混亂的輸出。 – 2010-09-27 15:52:15
另外,sizeof argv返回指向字符指針的大小,而不是指向字符的指針。 – 2010-09-27 15:57:50
您在示例程序中沒有對'fork()'的任何調用。這是故意的嗎? – sth 2010-09-26 15:54:29
負,只是忘了把它列入。 – mispecialist 2010-09-26 16:00:53
如果wait()在循環內,它將按順序執行參數。我認爲你想要做的就是等待循環開始所有進程的工作。 – 2010-09-27 14:46:25