并发进程

时间:2010-09-26 15:51:06

标签: c concurrency parent-child

我希望在C程序中运行多个并发进程。程序将从用户获取参数,然后将每个参数作为子进程执行。我认为这意味着我需要做的就是确保每次都由原始父进程执行fork(),然后每个结果子进程将同时运行,而不是按顺序运行。

我认为这是正确的吗?任何人都可以告诉我如何去做吗?

4 个答案:

答案 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,我假设您想获得参数总数。 argvpointer-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=1argv[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()