0

我使用一个简单的管道。我读了一会儿,一次 1 个字符,我想每次我读一个字符时,我都会覆盖一些东西

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    cpid = fork();
    if (cpid == -1) {
        perror("cpid");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        int i = 0;
        while (read (pipefd[0], &(buf[i++]), 1)>0);
        printf ("Server receives: %s", buf);
        close (pipefd[0]);
        exit (EXIT_SUCCESS);
    }
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2)+1);
        close(pipefd[1]);
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
  return 0;
}

代码现已修复,已过时:例如,如果我输入:“Flowers”,它会打印 F,然后是 ~6 个无法打印的字符

但是:发生了一件奇怪的事情,我只是使用了一个长度超过 30 的字符串,它根本没有产生任何错误,而且它确实设法写入了整个字符串。虽然我的两个缓冲区都比这小得多。

4

2 回答 2

2

这里看起来不对:

while (read (pipefd[0], &buf, 1)>0);

您一遍又一遍地将一个字符读入缓冲区的第一个位置。相反,您应该增加放置读取字符的位置。

例如

int i = 0;
while (read(pipefd[0], buf + i, 1) >0 ) ++i;
buf[i] = 0; // end string

检查它不会变得大于 buf 大小可能也很好:

while (read(pipefd[0], buf + i, 1) >0 && i < sizeof(buf)) ++i;
于 2012-06-08T04:41:47.597 回答
1

(按照安德斯的建议。)

使用 GCC 4.6.3,我的代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

int main () {
    int pipefd[2];
    int cpid;
    char buf[31];
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    cpid = fork();
    if (cpid == -1)
    {
        perror("cpid");
        exit(EXIT_FAILURE);
    }
    if (cpid == 0) {      // child reads from pipe
        close (pipefd[1]); // close unused write end
        int i=0;
        while (read(pipefd[0], &(buf[i++]), 1) != 0);
        printf ("Server receives: %s\n", buf);
        close (pipefd[0]);
        exit (EXIT_SUCCESS);
    }
    else {               // parent writes to pipe
        close (pipefd[0]); // closing unused read end;
        char buf2[30];
        printf("Server transmits: ");
        scanf ("%s", buf2);
        write (pipefd[1], buf2, strlen(buf2)+1);
        close(pipefd[1]);
        wait(NULL);
        exit(EXIT_SUCCESS);
    }
  return 0;
}

产生:

[user@host tmp]$ gcc pipes.c -o pipes && ./pipes 
Server transmits: Flowers
Server receives: Flowers

(我也同意他关于边界检查的观点。)


编辑:根据您的评论,如果您更改以下行(对我来说是 35)

scanf("%s", buf2);

fgets(buf2, 30, stdin);

你获得两个好处。(a) 通过限制将复制到buf2. (b) 您能够“接受”非换行符空格(空格和制表符),而使用scanf,您不能:

[user@host tmp]$ gcc pipes.c -o pipes && ./pipes 
Server transmits: Flowers smell nice
Server receives: Flowers smell nice
于 2012-06-08T05:01:34.137 回答