簡體   English   中英

Pipe()運行不正常 - linux

[英]Pipe() doesn't work well - linux

我正在嘗試使用管道通信制作程序。 這就是我要做的:用戶發送正整數。 如果用戶發送否定號碼,則通信結束。 父進程打印最大數量和最小數量。 這是我試過的:

#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); 只打印我給的第一個數字。 有人能更好地向我解釋我必須做什么嗎? 如何打印所有緩沖區 我在緩沖區中只寫了一個數字,就是這樣嗎? 如何找到最大最小數字? 我很困擾! :(

這可能是因為*buff是一個整數,但你寫的不止一個。

如果要打印所有已發送的整數,則需要知道已傳輸的數量,然后在循環中打印它們。


您也遇到問題,因為您只發送整數的一個字節(通常是四個字節)。 你應該使用eg

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

我相信你不明白<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進行調試。

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

這個

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的所有四個字節,但我認為,在管道實踐中,這不會發生。

這是一種方法來做我認為你嘗試做的很少的修改。 請注意, 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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM