我正在尝试使用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);
只打印我给的第一个数字。 有人能更好地向我解释我要做什么吗? 如何打印所有的缓冲区 ? 我在缓冲区只写了一个数字,就是这样吗? 我如何find最大值和最小值 ? 我很困扰! 🙁
这是一种方法来做我认为你只是做了很少的修改。 请注意, 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); } }
这可能是因为*buff
是一个整数,但是你写了不止一个。
如果要打印所有发送的整数,则需要知道有多少个被传送,然后循环打印。
你也有问题,因为你只发送整数的一个字节(通常是四个字节)。 你应该使用例如
write(pfd[1], &n, sizeof(n));
我相信你不明白<stdio.h>
函数(如scanf
和fprintf
)与read(2)和write(2)
(实际上printf
和fprintf
可以调用write(2)
)是不同的原始I / O系统调用。你可能会强迫他们用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)
),你必须自己管理缓冲(所以,考虑系统调用的write
结果,这可能是一个部分读取或写入的字节数)。
不要忘了使用gcc -Wall -g
(所有的警告和调试信息)进行编译,并学习使用gdb
进行调试。
这个
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的所有四个字节,尽管我认为在实际中使用管道,这不会发生。
#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); } }