Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 读取文件并使用管道将其发送到父进程的程序_C_Linux_Pipe - Fatal编程技术网

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

C 读取文件并使用管道将其发送到父进程的程序,c,linux,pipe,C,Linux,Pipe,我需要写一个程序,创建管道发送文件名从命令行到子进程。在child中,读取该文件并使用管道将其发送回。父进程应该打印文件。若子进程发生错误,则必须将错误发送到父进程 这是我的代码,它在文件中打印一些垃圾文件(并且在运行终端模拟器时禁用滚动) #包括 #包括 #包括 #包括 #包括 void main(int argc,char*argv[]){ int-pipefd[2]; 字符buff[100]; int-childpid; 整数大小; 文件*文件; 如果(argc!=2){ printf(“

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

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

#包括
#包括
#包括
#包括
#包括
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