使用管道在进程之间发送字符串
Posted
技术标签:
【中文标题】使用管道在进程之间发送字符串【英文标题】:Using pipes to send strings between processes 【发布时间】:2016-06-21 21:25:21 【问题描述】:我正在尝试将我的代码从 C# 重写为 C 并且遇到了一些麻烦。
所以我有一个名为 test 的文件,其中有一行文本。我想阅读该行,通过进程之间的管道将其发送并在屏幕上打印。
代码如下:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void
read_from_pipe (int file)
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
void
write_to_pipe (int file)
FILE *stream;
FILE *testfile;
stream = fdopen (file, "w");
testfile = fopen("test.txt", "r");
char *line = NULL;
size_t len = 0;
//ssize_t read;
getline(&line, &len, testfile);
fprintf (stream, "%s", line);
free(line);
fclose(testfile);
fclose (stream);
int
main (void)
pid_t pid;
int mypipe[2];
if (pipe (mypipe))
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
pid = fork ();
if (pid == (pid_t) 0)
close (mypipe[1]);
read_from_pipe (mypipe[0]);
return EXIT_SUCCESS;
else if (pid < (pid_t) 0)
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
else
close (mypipe[0]);
write_to_pipe (mypipe[1]);
return EXIT_SUCCESS;
但是,在运行此代码时,我似乎遇到了分段错误。有什么我遗漏的吗?
【问题讨论】:
哪一行出现分段错误? 您应该检查来自getline()
的错误。如果出现错误,可能是没有分配line
,所以你在打印的时候会出现分段错误。
getline()
调用看起来没问题。确保fopen()
成功。
当您调用getline()
时,testfile
的值是多少。
该文件可能不在您的当前目录中。尝试使用绝对路径。
【参考方案1】:
创建test.txt
文件后,它可能会正常工作。
至少在我的机器上修复了它。
在 C 语言中,您通常需要进行一些相当繁琐的错误检查才能稳健地编写程序。例如,您应该编写如下内容:
int read_from_pipe (int file)
FILE *stream;
int c;
if((stream = fdopen (file, "r"))==NULL) goto err;
while ((c = fgetc (stream)) != EOF)
putchar (c);
if(ferror(stream)) int er=errno; fclose (stream); errno=er; goto err;
return 0;
err:
perror("read"); return -errno;
等等
测试文件的fopen
行看起来像:
if(!(testfile = fopen("test.txt", "r"))) perror("write"); return -errno;
您可能收到了很好的"write: No such file or directory"
消息。
【讨论】:
if(ferror(stream)) fclose( stream ); goto err;
有问题。 fclose
可能会失败,修改errno。在这种情况下,错误处理中打印的错误消息将具有误导性。所以……需要更多的乏味。
@WilliamPursell 谢谢【参考方案2】:
您的程序崩溃的可能性有多种,但很可能是因为您缺少一些重要的检查,并且您的程序的工作目录中缺少文件“test.txt”。
缺少的第一个检查是 testfile 是否为 NULL:
testfile = fopen("test.txt", "r");
testfile 文件指针未经检查地传递给 getline(),如果传递一个无效的文件指针,可能会使程序崩溃。 正如 Barmar 之前所说,即使 testfile 有效, getline() 本身也可能会失败,但是在我当前的 Debian 上,手册页没有说明在错误条件下行指针会发生什么,所以我只检查返回值
最后一点,如果你正在学习这类东西,你应该学习如何使用 gdb。 像这样使用:
$ gcc -ggdb3 -o pipetest pipetest.c
$ gdb pipetest
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
[...]
(gdb) run
Starting program: /home/thilo/code/test/pipetest
Program received signal SIGSEGV, Segmentation fault.
_IO_getdelim (lineptr=0x7fffffffe068, n=0x7fffffffe060, delimiter=10, fp=0x0) at iogetdelim.c:56
56 iogetdelim.c: No such file or directory.
(gdb) bt
#0 _IO_getdelim (lineptr=0x7fffffffe068, n=0x7fffffffe060, delimiter=10, fp=0x0) at iogetdelim.c:56
#1 0x00000000004008fb in write_to_pipe (file=4) at pipetest.c:28
#2 0x00000000004009d9 in main () at pipetest.c:62
(gdb) frame 1
#1 0x00000000004008fb in write_to_pipe (file=4) at pipetest.c:28
28 getline(&line, &len, testfile);
(gdb) print line
$1 = 0x0
【讨论】:
【参考方案3】:此代码在我的机器(Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.68-1+deb7u2 x86_64 GNU/Linux)上正常运行,无需修改。 我删除了“test.txt”文件,结果出现了分段错误。
因此,我认为您遇到的问题是“test.txt”文件不存在,或者您没有运行程序的用户的读取权限。
【讨论】:
以上是关于使用管道在进程之间发送字符串的主要内容,如果未能解决你的问题,请参考以下文章