Pipe()运行不正常 - linux

时间:2013-05-10 13:00:37

标签: c linux pipe

我正在尝试使用管道通信制作程序。这就是我要做的:用户发送正整数。如果用户发送否定号码,则通信结束。父进程打印最大数量和最小数量。这就是我试过的:

#include <unistd.h>
#include <stdio.h>

main(){
int pfd[2];
int buff[200];
pipe(pfd);
if(fork()==0){
   close(pfd[0]);
   int n;
   printf("Give a number: ");
   scanf("%d",&n);
   while(n >=0 ){
      write(pfd[1],&n,1);
      printf("Give a number: ");
      scanf("%d",&n);
   }
  exit(0);
  }
else{
  close(pfd[1]);
  read(pfd[0],buff,sizeof(buff));
  printf("The parent read %d:",*buff);
  wait(0);
}
}

printf("The parent read %d:",*buff);仅打印我给出的第一个数字。有人能更好地向我解释我必须做什么吗?如何打印所有缓冲区?我在缓冲区中只写了一个数字,就是这样吗?如何找到最大最低数字?我很迷茫! :(

5 个答案:

答案 0 :(得分:1)

可能是因为*buff是一个整数,但你写的不止一个。

如果要打印所有已发送的整数,则需要知道传输的数量,然后将其打印出来。


您也遇到问题,因为您只发送整数的一个字节(通常为四个字节)。你应该使用例如。

write(pfd[1], &n, sizeof(n));

答案 1 :(得分:1)

我认为您不理解<stdio.h>函数(如scanffprintf)与read(2)和{{1}等原始I / O系统调用不同(实际上write(2)printf可以调用fprintf,您可以强制他们使用write(2)执行此操作

我不明白你想要什么样的管道协议。您似乎想要发送原​​始字节(然后您被限制为0-255)。或者你想用ASCII发送每个数字,每行一个?

也许你可以在父进程中做(假设协议是文本的,ASCII中的数字,每行一个)

fflush

并在子进程中

 FILE* wp = fdopen(pfd[1],"w");
 if (!wp) { perror("fdopen wp"); exit(EXIT_FAILURE); };
 int num = -1;
 do {
    num = 0;
    printf("Enter a number:\n");
    fflush(NULL);
    if (scanf(" %d", &num)<=0) break;
    fprintf (wp, "%d\n", num);
 } while (num>=0 && !feof(stdin));
 fclose(wp);

如果您只想使用低级I / O系统调用(即 FILE* rp = fdopen(pfd[0], "r"); if (!rp) { perror("fdopen rp"); exit(EXIT_FAILURE); }; while (!feof(rp)) { int rnum = -1; fflush(NULL); if (fscanf(" %d", &rnum)<=0) break; printf ("parent has read %d\n", rnum); }; read(2)),您必须自己管理缓冲(因此,请考虑{{1}的结果}和write(2)系统调用,可能是读取或写入的部分字节数。)

不要忘记使用read进行编译(所有警告和调试信息),并学会使用write进行调试。

答案 2 :(得分:0)

#include <unistd.h>
#include <stdio.h>

main(){
    int pfd[2];
    int buff[200];
    pipe(pfd);
    if(fork()==0){
        close(pfd[0]);
        int n;
        printf("Give a number: ");
        scanf("%d",&n);
        while(n >=0 ){
            printf("Give a number: ");
            scanf("%d",&n);
            write(pfd[1],&n,sizeof(int));
        }
        exit(0);
    }
    else{
        close(pfd[1]);
        /*      loop ??*/
        read(pfd[0],buff,199);
        printf("The parent read %d:",buff);
        /*      loop ??*/
        wait(NULL);
    }
}

答案 3 :(得分:0)

write(pfd[1],&n,1);

只写一个字节。你需要这个:

write(pfd[1],&n, sizeof n);

这将读取管道缓冲区中可用的任何内容

read(pfd[0],buff,sizeof(buff));

它阻塞,直到有东西要读,然后返回它实际读取的许多字节。可能的顺序是:

child writes your first number (probably 4 bytes)
parent reads the first number
parent executes the wait() sys call
you type in the second number (assume its negative)
child writes the second number
child exits
parent exits

您的父母需要继续阅读,直到它具有预期的所有数字或达到文件结尾(通过读取返回0表示)。像这样:

int bytesRead;
while ((bytesRead = read(pfd[0], buff, sizeof buff)) > 0)
{
    // Do whatever it is you want to do with the bytes
}
if (bytesRead == -1)
{
    // report the error
}

请注意,从理论上讲,你甚至可能不会一次性读取int的所有四个字节,但是,我认为,在管道实践中,这不会发生。

答案 4 :(得分:0)

这是一种方法,可以通过一些修改来完成我认为您尝试做的事情。 请注意,buff不再是数组,我们在打印数字时将管道本身用作临时存储。

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

int main(void)
{
    int pfd[2];
    int buff;
    int max,min;

    pipe(pfd);
    if(fork()==0){
        close(pfd[0]);
        int n;
        printf("Give a number: ");
        scanf("%d",&n);
        while(n >=0 ){
            write(pfd[1],&n,sizeof(n));
            printf("Give a number: ");
            scanf("%d",&n);
        }
        exit(0);
    }
    else {
        close(pfd[1]);
        printf("The parent read ");

        if (read(pfd[0],&buff,sizeof(int))) {
            max = buff;
            min = buff;
            printf("%d",buff);
        }


        while (read(pfd[0],&buff,sizeof(int))) {
            if (buff > max)
            max = buff;
            else if (buff < min)
            min = buff;
            printf("%d:",buff);
        }

        printf("\n");

        printf("The maximum value is: %d.\n The minimum value is: %d.\n",max,min);
        wait(NULL);
    }
}