我希望在C程序中运行多个并发进程。程序将从用户获取参数,然后将每个参数作为子进程执行。我认为这意味着我需要做的就是确保每次都由原始父进程执行fork(),然后每个结果子进程将同时运行,而不是按顺序运行。
我认为这是正确的吗?任何人都可以告诉我如何去做吗?
答案 0 :(得分: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
(虽然你应该等待所有的孩子,而不仅仅是这个代码所做的任何孩子。)
答案 1 :(得分: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 = 3 (而不是 2 ,这是一个非常常见的陷阱)
(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
可执行文件&amp;将NULL指针(0
)传递给它。这可能会导致以下运行时错误:
A NULL argv[0] was passed through an exec system call.
参考exec手册页,
按照惯例,第一个论点, 应该指向文件名 与文件相关联 执行。
虽然不必再次传递文件名,但您当然不应该传递NULL指针。由于您不想传递任何参数,我建议您使用以下execl
调用,而不是:
execl(argv[i],argv[i],0);
请记住,所有此类调用最终都会最终转换为execve()
&amp;然后执行,最终使它们等效。
我们建议您使用man
详细了解exec系列函数。
答案 2 :(得分:0)
你的推理似乎是正确的..父进程会分叉与参数相同数量的子进程。
虽然使用线程进行并发处理会不会更有效率?
答案 3 :(得分:0)
我相信会做你想做的事。然而...
fork()
并不真正在一个程序中运行多个进程。它在不同的进程中运行同一程序的多个副本。如果程序之间没有重大的重叠,您也可以为每个程序单独写main()
。