我正在尝试使用管道通信制作程序。这就是我要做的:用户发送正整数。如果用户发送否定号码,则通信结束。父进程打印最大数量和最小数量。这就是我试过的:
#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);
仅打印我给出的第一个数字。有人能更好地向我解释我必须做什么吗?如何打印所有缓冲区?我在缓冲区中只写了一个数字,就是这样吗?如何找到最大和最低数字?我很迷茫! :(
答案 0 :(得分:1)
可能是因为*buff
是一个整数,但你写的不止一个。
如果要打印所有已发送的整数,则需要知道传输的数量,然后将其打印出来。
您也遇到问题,因为您只发送整数的一个字节(通常为四个字节)。你应该使用例如。
write(pfd[1], &n, sizeof(n));
答案 1 :(得分:1)
我认为您不理解<stdio.h>
函数(如scanf
和fprintf
)与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);
}
}