gpt4 book ai didi

c - 读取文件并使用管道将其发送到父进程的程序

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:41:08 28 4
gpt4 key购买 nike

我需要编写一个程序来创建从命令行到子进程的管道发送文件名。在 child 中读取该文件并使用管道将其发回。父进程应该打印文件。如果子进程发生错误,必须将错误发送给父进程。

这是我的代码,它会在文件文件中打印一些垃圾信息(并且当我运行它时它会禁用终端模拟器中的滚动)。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

void main(int argc, char *argv[]) {
int pipefd[2];
char buff[100];
int childpid;
int size;
FILE *file;

if (argc != 2) {
printf("usage:\n%s <filename>\n", argv[0]);
exit(1);
}
if (pipe(pipefd) < 0) {
perror("can't open pipe\n");
}
if ((childpid = fork()) == 0) {
sleep(1);
size = read(pipefd[0], buff, sizeof(buff));
file = fopen(buff, "r");
if (file == NULL) {
write(pipefd[1], "Can't open file", 15);
exit(1);
}
while (!feof(file)) {
if (fgets(buff, sizeof(buff), file) == NULL) {
write(pipefd[1], "Error reading file", 18);
} else {
write(pipefd[1], buff, sizeof(buff));
}
}
} else if (childpid > 0) {
size = strlen(argv[1]);
if (write(pipefd[1], argv[1], size) != size) {
perror("Error writing to pipe\n");
}
wait(NULL);
while ((size = read(pipefd[0], buff, sizeof(buff))) > 0) {
write(1, buff, size);
}
}
exit(0);
}

最佳答案

您的程序经过多次更改后按预期运行。让我们列出所有需要更改的内容以及原因-

I) 在子进程和父进程中,完成后立即关闭各自的管道。来自 man page 阅读(3)

If some process has the pipe open for writing and O_NONBLOCK is clear, read() shall block the calling thread until some data is written or the pipe is closed by all processes that had the pipe open for writing.

所以在你的代码中工作管道结束的任何地方都做这样的事情,

  size = read(pipefd[0], buff, sizeof(buff));
close(pipefd[0]);

write(pipefd[1], buff, strlen(buff));
close(pipefd[1]);

if (write(pipefd[1], argv[1], size) != size) {
perror("Error writing to pipe\n");
}
close(pipefd[1]);

while ((size = read(pipefd[0], buff, sizeof(buff))) > 0)
{
write(1, buff, size);
}
close(pipefd[0]);

您没有关闭子管道的写入端,而您的父进程在read

中阻塞

II) 您正在循环中使用类似while(fgets(...)) 的方法从文件中读取数据。 当文件中有换行符并且 fgets 返回多次时,这会发生爆炸,在此过程中每次都会覆盖 buffer

我总是使用简单的 fgetcfeof 组合来读取文件。因此,将您的文件读取机制更改为类似

unsigned count=0;
while (!feof(file) && count < sizeof(buff))
buff[count++]=fgetc(file);
if (feof(file))
buff[--count]=0;
else
buff[sizeof(buff)-1]=0;

III) 当从子进程写入文件数据时,您应该使用 strlen(因为我们已经确保缓冲区以 null 终止,见上文)而不是sizeof,因为缓冲区可能根本没有满,你最终会写出垃圾。所以,改变

  write(pipefd[1], buff, sizeof(buff));

  write(pipefd[1], buff, strlen(buff));

IV) 完成工作后,跟随 child 和 parent 的安全导出。有点像

close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child

close(pipefd[0]);
exit(EXIT_SUCCESS); // in parent

PS:我已经更改了文件读取逻辑,所以您的编译错误现在已经消失,请按照n.m 给出的建议进行操作。

关于c - 读取文件并使用管道将其发送到父进程的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10139470/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com