C 读取文件并使用管道将其发送到父进程的程序
我需要写一个程序,创建管道发送文件名从命令行到子进程。在child中,读取该文件并使用管道将其发送回。父进程应该打印文件。若子进程发生错误,则必须将错误发送到父进程 这是我的代码,它在文件中打印一些垃圾文件(并且在运行终端模拟器时禁用滚动)C 读取文件并使用管道将其发送到父进程的程序,c,linux,pipe,C,Linux,Pipe,我需要写一个程序,创建管道发送文件名从命令行到子进程。在child中,读取该文件并使用管道将其发送回。父进程应该打印文件。若子进程发生错误,则必须将错误发送到父进程 这是我的代码,它在文件中打印一些垃圾文件(并且在运行终端模拟器时禁用滚动) #包括 #包括 #包括 #包括 #包括 void main(int argc,char*argv[]){ int-pipefd[2]; 字符buff[100]; int-childpid; 整数大小; 文件*文件; 如果(argc!=2){ printf(“
#包括
#包括
#包括
#包括
#包括
void main(int argc,char*argv[]){
int-pipefd[2];
字符buff[100];
int-childpid;
整数大小;
文件*文件;
如果(argc!=2){
printf(“用法:\n%s\n”,argv[0]);
出口(1);
}
如果(管道(管道FD)<0){
perror(“无法打开管道”);
}
if((childpid=fork())==0){
睡眠(1);
大小=读取(pipefd[0],buff,sizeof(buff));
file=fopen(浅黄色,“r”);
if(file==NULL){
写入(pipefd[1],“无法打开文件”,15);
出口(1);
}
而(!feof(文件)){
if(fgets(buff,sizeof(buff),file)==NULL){
写入(pipefd[1],“错误读取文件”,18);
}否则{
写入(pipefd[1],buff,sizeof(buff));
}
}
}否则如果(childpid>0){
大小=strlen(argv[1]);
if(写入(pipefd[1],argv[1],大小)!=size){
perror(“写入管道时出错”);
}
等待(空);
而((size=read(pipefd[0],buff,sizeof(buff)))>0){
写入(1,浅黄色,大小);
}
}
出口(0);
}
此代码不编译:
while (fgets(buff, sizeof(buff), file) != NULL) {
write(pipefd[1], "Error reading file", 18);
} else {
write(pipefd[1], buff, sizeof(buff));
}
那里不能有
else
子句。此代码不编译:
while (fgets(buff, sizeof(buff), file) != NULL) {
write(pipefd[1], "Error reading file", 18);
} else {
write(pipefd[1], buff, sizeof(buff));
}
那里不能有
else
子句。如果fgets
返回的值小于该值,则不能写入sizeof(buf)
有意义的字节。剩下的将装满垃圾
此外,将面向字符串的
fgets
与二进制read/write
混合使用是一种糟糕的风格。使用read
或fread
读取文件。它们返回读取的字节数,使用此数字作为参数写入如果fgets
返回的字节数小于此值,则无法写入sizeof(buf)
有意义的字节。剩下的将装满垃圾
此外,将面向字符串的fgets
与二进制read/write
混合使用是一种糟糕的风格。使用read
或fread
读取文件。它们返回读取的字节数,将此数用作参数,以写入经过多次更改后,程序可以正常工作。让我们列出所有需要更改的内容以及原因-
I)在子级和父级中,处理完相应的管道后,立即关闭它们。从的第(3)部分读取
如果某个进程将管道打开以进行写入,并且O_NONBLOCK清除,
read()将阻止调用线程,直到写入或删除某些数据
管道由所有打开管道的进程关闭
写作
因此,在工作管道结束的任何地方,都要在代码中执行类似的操作
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]);
您没有关闭子级中管道的写入端,而您的父级正在读取中阻塞
II)您在循环中使用类似于的while(fgets(…)
从文件中读取数据当文件中有换行符且fgets
多次返回时,此操作将爆炸,并在该过程中每次覆盖缓冲区
我总是使用简单的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;
close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child
到
IV)在孩子和家长完成工作后,遵循安全的退出。差不多
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;
close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child
及
PS:我已更改了文件读取逻辑,因此您的编译器错误现在已消失,请务必遵循n.m的建议。经过多次更改后,您的程序仍能正常运行。让我们列出所有需要更改的内容以及原因-
I)在子级和父级中,处理完相应的管道后,立即关闭它们。从的第(3)部分读取
如果某个进程将管道打开以进行写入,并且O_NONBLOCK清除,
read()将阻止调用线程,直到写入或删除某些数据
管道由所有打开管道的进程关闭
写作
因此,在工作管道结束的任何地方,都要在代码中执行类似的操作
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]);
您没有关闭子级中管道的写入端,而您的父级正在读取中阻塞
II)您在循环中使用类似于的while(fgets(…)
从文件中读取数据当文件中有换行符且fgets
多次返回时,此操作将爆炸,并在该过程中每次覆盖缓冲区
我总是使用简单的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;
close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child
到
IV)在孩子和家长完成工作后,遵循安全的退出。差不多
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;
close(pipefd[1]);
_exit(EXIT_SUCCESS); // in child
及
PS:我已经更改了文件读取逻辑,因此您的编译器错误现在消失了,请按照n.m给出的建议操作,它应该是int main(int argc,char*argv[])
。您能告诉我们您面临什么问题吗?如果文件足够大,您会遇到死锁;父级等待子级死亡,但子级可能被挂起,等待父级读取管道。假设是双向管道;这些还不是标准的(尽管我相信它们在Linux上是可用的)。当父进程完成对其的写入时,它应该关闭其管道的写入端;可以说,孩子应该关闭t