fork(),pipe()和exec()进程创建和通信

问题描述:

我必须编写使用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

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

如果您应该使用exec,那么您应该将程序分成两个二进制文件。

基本上,现在得到由孩子执行的代码应该是在第二二进制,应exec被调用。

在调用exec系列函数之一之前,还需要使用dup2将管道描述符重定向到新进程的标准输入/输出。这样,得到exec'd的第二个二进制代码不会知道管道,只会读/写标准输入/输出。

这也是值得注意的是,一些你现在正在使用的子进程中的数据是从父通过fork继承。当使用exec时,孩子不会共享父母的数据或代码,所以也可以考虑通过管道传输所需的数据。

+0

我现在就要这样做。 – cool 2011-02-23 23:52:46