在C中使用管道运行并发进程

时间:2015-10-27 05:55:23

标签: c pipe fork ipc

我正在C中完成一项任务,目的是使用管道在两个进程之间传递变量。这两个进程必须从父进程分叉,并且它们必须同时运行以一次传递一个字符(如下所示)。

我遇到的问题是fork()ed进程没有并发运行。发送者似乎先行,并且在运行约26秒后接收器开始。这是我写的代码:

#include <stdio.h>

int ret;
int pipearray[2];
char buffer[26];

void mysender();
void myreceiver();

int main()
{
  int pid = 0;
  int i = 0;
  ret = pipe(pipearray);


  while (i < 2) {
    pid = fork();
    if ( pid == 0 && i == 0 ) /* child process execution (receiver) */
      {
    myreceiver();
    printf("Your receiver is done\n");
    exit(0);
      }

     else if ( pid == 0 && i == 1 ) /* now executes sender */
     {
    mysender();
    printf("Your sender is done\n");
    exit(0);
     }
    ++i;
  }

  close(pipearray[0]);
  close(pipearray[1]);
  sleep(30);
  printf("Parent function has finished.\n");      

  return 0;
}

void mysender() 
{
  char c;
  int index = 90;
  close(pipearray[0]);

  while (index > 64) /* loop for all values of A-Z in ASCII */ 
    {      
      c = (char) index;
      open(pipearray[1]);
      write(pipearray[1], c, sizeof(c)); /* Sends letter to pipe */
      --index;
      sleep(1);
    }

  close(pipearray[1]);
}

void myreceiver()
{
  int index = 0;
  close(pipearray[1]);

  while(buffer != 'A') /*loop runs until 'A' is handled */
  { 
    sleep(1);
    open(pipearray[0]);
    read(pipearray[0], buffer, 1);
    printf("%s", &buffer);
    index++;
    if ( index == 26 ) { break; }
  }

  close(pipearray[0]);
}

预期结果:

ZYXWVUTSRQPONMLKJIHGFEDCBA
Your sender is done
Your receiver is done
The parent function has finished.

我的结果:

Your sender is done
The parent function has finished.
Your receiver is done

我对C编程很陌生,但我已经暂时搁置了一段时间。任何有关这些可能无法同时运行的提示都将非常感激。

1 个答案:

答案 0 :(得分:2)

您的代码中存在许多错误。不要尝试在fork之后打开管道,它已经打开并且没有名称。写应该使用c的地址。阅读必须读到正确的地方。写入stdout后必须刷新。您的条件必须稍加修改才能保证正确。父进程必须等待其子进程。这是修改后的代码:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
int ret;
int pipearray[2];
char buffer[26];

void mysender();
void myreceiver();

int main()
{
  int pid = 0;
  int i = 0;
  ret = pipe(pipearray);


  while (i < 2) {
    pid = fork();
    if ( pid == 0 && i == 0 ) /* child process execution (receiver) */
      {
        myreceiver();
        printf("Your receiver is done\n");
        exit(0);
      }

    else if ( pid == 0 && i == 1 ) /* now executes sender */
      {
        mysender();
        printf("Your sender is done\n");
        exit(0);
      }
    ++i;
  }

  close(pipearray[0]);
  close(pipearray[1]);
  // Don't sleep, but wait until the end of the two children
  wait(NULL);
  wait(NULL);
  //  sleep(30);
  printf("Parent function has finished.\n");      

  return 0;
}

void mysender() 
{
  char c;
  int index = 90;
  close(pipearray[0]);

  while (index > 64) /* loop for all values of A-Z in ASCII */ 
    {      
      c = (char) index;
      // try to open a anonymous pipe is a non-sense
      //      open(pipearray[1]);
      // Send a buffer by its address
      write(pipearray[1], &c, sizeof(c)); /* Sends letter to pipe */
      --index;
      sleep(1);
    }

  close(pipearray[1]);
}

void myreceiver()
{
  int index = 0;
  close(pipearray[1]);

  // Ensure condition is entered first
  buffer[index] = 0;
  // This is not the best condition ever, but ok.
  while(buffer[index] != 'A') /*loop runs until 'A' is handled */
  { 
    sleep(1);
    // Don't open an anonymous pipe
    //    open(pipearray[0]);
    // Read at the right position
    read(pipearray[0], buffer+index, 1);
    // print and flush, could also be printf("%s"...); flush(stdout);
    printf("%s\n", buffer);
    index++;
    if ( index == 26 ) { break; }
  }

  close(pipearray[0]);
}

现在,考虑删除阅读器中的睡眠,因为它将与写入同步,这样如果没有写入就不能进行读取。 Alos考虑读取更多的一个字节,因为没有 message 的概念,因此您可以读取您认为需要读取的字节数,并且像往常一样最好尝试读取一堆你可以使用字节。