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

Posted

技术标签:

【中文标题】在 C 中使用管道运行并发进程【英文标题】:Running concurrent processes using pipe in C 【发布时间】:2015-10-27 05:55:23 【问题描述】:

我正在使用 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 编程非常陌生,但我已经为此努力了一段时间。任何关于为什么这些可能不会同时运行的提示将不胜感激。

【问题讨论】:

open(pipearray[1]) 到底应该做什么? 这不是 C 编程。它是 POSIX(或 Unix)编程。 C99 或 C11 标准 dpnt 知道 forkpipe。您应该仔细阅读 RTFM fork(2)、pipe(2)、open(2) 并阅读 ALP Protip:总是用-Wall -Wextra -Werror编译。 【参考方案1】:

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

#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的概念,这样你就可以读到你认为需要读多少字节,和往常一样最好尝试读一堆尽可能字节。

【讨论】:

这非常有帮助。谢谢。

以上是关于在 C 中使用管道运行并发进程的主要内容,如果未能解决你的问题,请参考以下文章

C实现进程间通信(管道; 共享内存,信号量)

Python并发编程—进程间通信

Python之进程同步控制(锁信号量事件 )进程间通信——队列和管道

C命名管道不适用于多进程

生产者消费者模型,管道,进程之间共享内存,进程池

PHP多进程处理并行处理任务实例(转,备用)