2012-06-21 48 views
3

我正在使用管道来编写协处理程序。父母创建两个管道,一个管道用于写入孩子,另一个管道用于从孩子读取。但是当我运行该程序时,它会处于等待状态,因为它将默认设置为完全缓冲。而且我不想在子进程源代码中使用缓冲区。如何刷新协处理管道中的I/O缓冲区

我知道第19章高级编程在UNIX环境下引入了一种使用伪终端的方式。但我想知道是否有更多样本来做到这一点。谢谢大家。

这里是我的源代码:

#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 


int main() 
{ 
    #define MAXSIZE 1024 

    char workload[MAXSIZE]; 
    char result[MAXSIZE]; 
    char buf[10] = {0}; 
    workload[strlen(workload)] = EOF; 
    int workload_size = strlen(workload); 

    int fd1[2], fd2[2]; 
    int n; 
    pid_t pid; 
    if (pipe(fd1) < 0 || pipe(fd2) < 0) { 
     fprintf(stderr, "pipe error: %s\n", strerror(errno)); 
     exit(1); 
    } 

    if ((pid = fork()) < 0) { 
     fprintf(stderr, "fork error: %s\n", strerror(errno)); 
     exit(1); 
    } else if (pid > 0) { 
     close(fd1[0]); 
     close(fd2[1]); 
     while(fgets(workload, MAXSIZE, stdin) != NULL) 
     { 
      workload_size = strlen(workload); 
      if (write(fd1[1], workload, workload_size) != workload_size) { 
       fprintf(stderr, "write to pipe error: %s\n", strerror(errno)); 
       exit(1); 
      } 

      if ((n = read(fd2[0], result, MAXSIZE)) < 0) { 
       fprintf(stderr, "read from pipe error: %s\n", strerror(errno)); 
       exit(1); 
      } 

      if (n == 0) { 
       fprintf(stderr, "child closed the pipe\n"); 
       exit(1); 
      } 

      result[n] = 0; 

      if (puts(result) == EOF) { 
       fprintf(stderr, "fputs error\n"); 
       exit(1); 
      } 
     } 
    } else { 
     close(fd1[1]); 
     close(fd2[0]); 
     if (fd1[0] != STDIN_FILENO) { 
      if (dup2(fd1[0] ,STDIN_FILENO) != STDIN_FILENO) { 
       fprintf(stderr, "dup2 error to stdin.\n"); 
       exit(1); 
      } 
      close(fd1[0]); 
     } 
     if (fd2[1] != STDOUT_FILENO) { 
      if (dup2(fd2[1] ,STDOUT_FILENO) != STDOUT_FILENO) { 
       fprintf(stderr, "dup2 error to stdout.\n"); 
       exit(1); 
      } 
      close(fd2[1]); 
     } 

     if (execl("./a.out", "a.out", NULL) < 0) { 
      fprintf(stderr, "execl error: %s\n", strerror(errno)); 
      exit(1); 
     } 
     exit(0); 
    } 

    return 0; 
} 

从标准输入和输出,它只是读取的子进程:

#include <stdio.h> 

int main() 
{ 
    #define MAXSIZE 1024 
    char x[MAXSIZE]; 
    int n; 
    while(fgets(x, 1024, stdin) != NULL) 
    { 
     printf("%s", x); 
    } 
    return 0; 
} 

回答

2

可以使用stdbuf工具来改变你的子进程的缓冲。

或者,如果您可以更改子进程的代码,请直接从子进程调用setvbuf

+0

它确实是一个整洁的方式。谢谢! –

+0

我想知道是否可以直接在源代码中更改管道的缓冲区? –

+0

已更新,请使用'setvbuf' –