Linux 读取文件并使用管道将其发送到父进程的程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10139470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Program that read file and send it to parent process with pipe
提问by jcubic
I need to write a program that create pipe send filename from command line to child process. In child read that file and send it back using pipe. Parent process should print the file. if error occur in child process error must be send to parent process.
我需要编写一个程序来创建从命令行到子进程的管道发送文件名。在孩子中读取该文件并使用管道将其发送回。父进程应该打印文件。如果在子进程中发生错误,则必须将错误发送给父进程。
here is my code, it print some junk along file file (and also it disable scrolling in terminal emulator when I run it).
这是我的代码,它沿文件文件打印一些垃圾(并且在我运行它时还禁用终端模拟器中的滚动)。
#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);
}
采纳答案by Pavan Manjunath
Your program works as intended after quite a few changes. Lets list out what all changes are required and why-
您的程序在经过多次更改后按预期工作。让我们列出所有需要更改的内容以及原因-
I)Both in the child and parent, close the respective pipes as soon as you are done with them. From man pageof read(3)
,
I)在孩子和父母中,完成后立即关闭各自的管道。从手册页中read(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.
如果某个进程打开管道进行写入并且 O_NONBLOCK 已清除,则 read() 将阻塞调用线程,直到写入一些数据或管道被所有打开管道进行写入的进程关闭。
So do something like this in your code everywhere where the job pipes is over,
所以在你的代码中在作业管道结束的地方做这样的事情,
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]);
You hadn't closed the write end of of the pipe in the child and your parent was blocking in the read
您没有关闭孩子管道的写端,而您的父母正在阻止 read
II)You are using something like while(fgets(...))
in a loop to read data from file. This will bomb when there are newlines in the file and fgets
returns multiple times, overwriting the buffer
everytime during the process
II)您正在使用类似while(fgets(...))
循环的东西从文件中读取数据。当文件中有换行符并fgets
多次返回时,这将爆炸,buffer
在此过程中覆盖每次
I always use simple fgetc
and feof
combination to read from file. So, change your file reading mechanism to something like
我总是使用简单fgetc
和feof
组合来读取文件。因此,将您的文件读取机制更改为类似
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)While writing the file data from the child, you should use strlen
(as we have already made sure buffer is null terminated, see above ) and not sizeof
as the buffer may not be full at alland you will end up writing junk. So, change
III)在从子进程写入文件数据时,您应该使用strlen
(因为我们已经确保缓冲区为空终止,请参见上文),而不是sizeof
因为缓冲区可能根本没有满,您最终会写入垃圾。所以,改变
write(pipefd[1], buff, sizeof(buff));
to
到
write(pipefd[1], buff, strlen(buff));
IV)Follow a safe exit
from the child and parent after their job is done. Something like
IV)exit
在孩子和家长完成工作后,跟着他们的保险箱。就像是
close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child
and
和
close(pipefd[0]);
exit(EXIT_SUCCESS); // in parent
PS: I've changed the file reading logic, so your compiler error is gone now and do follow the advice given by n.m.
PS:我已经更改了文件读取逻辑,因此您的编译器错误现在已经消失,请遵循nm给出的建议。
回答by Jonathan Leffler
This code does not compile:
此代码无法编译:
while (fgets(buff, sizeof(buff), file) != NULL) {
write(pipefd[1], "Error reading file", 18);
} else {
write(pipefd[1], buff, sizeof(buff));
}
You can't have an else
clause there.
你不能在else
那里有一个条款。
回答by n. 'pronouns' m.
You cannot write sizeof(buf)
meaningful bytes if fgets
returned less than that. The rest will be filled with junk.
sizeof(buf)
如果fgets
返回的字节数少于该值,则无法写入有意义的字节。其余的将充满垃圾。
Moreover, mixing string-oriented fgets
with binary read/write
is a bad style. Use read
or fread
to read the file. They return number of bytes read, use this number as an argument to write
.
此外,将面向字符串fgets
与二进制混合read/write
是一种糟糕的风格。使用read
或fread
读取文件。它们返回读取的字节数,将此数字用作write
.