0

I'm trying to make a program using the pipe communication. This is what I'm trying to do: the user sends positive integers. If the user sends a negative number the communication ends. The parent process prints the maximum number and the minimum number. This is what I tried:

#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);
}
}

This printf("The parent read %d:",*buff); prints only the first number I gave. Can someone explain to me better what I have to do? How to print all the buffer? Am I writing only 1 number in the buffer and that's it? How do I find the maximum and the minimum number? I am very confused! :(

4

5 回答 5

1

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

如果要打印发送的所有整数,则需要知道传输了多少,然后循环打印它们。


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

write(pfd[1], &n, sizeof(n));
于 2013-05-10T13:03:35.877 回答
1

我相信您不明白<stdio.h>函数(如scanffprintf)与原始 I/O 系统调用(如read(2)write(2)(实际上printffprintf可以调用write(2),您可能会强迫他们使用 )执行此操作不同fflush

我不明白你在管道上想要什么协议。似乎您想发送原始字节(然后您被限制为 0-255)。还是您想以 ASCII 格式发送每个数字,每行一个?

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

 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);

并在子进程中

 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);
 };

如果您只想使用低级 I/O 系统调用(即read(2)write(2)),您必须自己管理缓冲(因此,请考虑readwrite系统调用的结果,这可能是读取或写入的字节数的一部分)。

不要忘记编译gcc -Wall -g(所有警告和调试信息)并学习gdb用于调试。

于 2013-05-10T13:06:13.580 回答
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);
    }
}
于 2013-05-10T14:02:36.217 回答
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);
    }
}
于 2013-05-10T13:17:12.817 回答
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

你的父母需要继续阅读,直到它拥有它期望的所有数字或到达文件结尾(由 read 返回 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 的所有四个字节,尽管我认为,在使用管道的实践中,这不会发生。

于 2013-05-10T13:20:58.173 回答