我想使用外部程序来处理内存中的数据。像外部压缩器,编码器一样,任何可以处理我的数据并获得结果的东西。我读了很多关于管道的内容,但仍然无法正常工作。因此,我得到了一个简单的程序,该程序试图通过这样的管道写入外部程序,然后将其打印到stdout:
stdout
(w) pipeA (r) $prog +---+
+-----------+ /~~~~~~~~~~~\ |{1}|
|[1] [0]| ----> |{0} {1}| ----> | |
+~~> +-----------+ \~~~~~~~~~~~/ | |
| +---+
|
+-+
write() |
+-+
而且我仍然一无所获。我的代码是这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define PIP_RD_0 0 /* read end of pipe file descriptor */
#define PIP_WR_1 1 /* write end of pipe file descriptor */
int main(void)
{
int pipA[2];
int pid;
char buf_IN[32] = "Hello pipe!\n";
char buf_OUT[32];
ssize_t n_written, n_read;
if ((pipe(pipA) == -1)) {
perror("pipe failed");
exit(1);
}
if ((pid = fork()) < 0) {
perror("fork failed");
exit(2);
}
/*****************************/
if (pid == 0)
{ /* in child */
dup2(0, pipA[0]); // pipA[read(0)-end]->$prog[write{0}-end]
close(pipA[1]); // $prog won't write to this pipe(A)
// external ``$prog''ram
execlp("wc", "wc", (char *) 0); // out should be: ' 1 2 12'
//execlp("base64", "base64", (char *) 0); // out should be: 'SGVsbG8gcGlwZSEK'
;///if we're here something went wrong
perror("execlp() @child failed");
exit(3);
}
else
{ /* in parent */
//dup2(pipA[1], 0); // STDIN -> pipA // that supposed to connect STDIN->pipA; just in case I needed it
close(pipA[0]); // we won't read it, let $prog write to stdout
//perror("execlp() @parent failed");
//exit(4);
n_written = write(pipA[1], buf_IN, strlen(buf_IN));
close(pipA[1]); // I guess this will close the pipe and send child EOF
// base64: read error: Input/output error
// wc: 'standard input': Input/output error
// 0 0 0
}
return 0;
}
评论显示我在做什么。我必须承认我没有在管道中获得这些dup(),这就是我在这里引起问题的原因,但不知道。您可以解决这个看似简单的问题吗?任何帮助表示赞赏。
您具有从头到尾的dup2()
的参数。您需要:
sup2(pipA[0], 0);
如注释中所述,您没有在子级中关闭足够的文件描述符:
拇指法则:如果您dup2()
管道的一端到标准输入或标准输出,同时关闭两个由返回的原始文件描述符dup2()
尽快地。特别是,在使用任何pipe()
功能系列。
如果您将描述符与pipe()
要么exec*()
与exec*()
如果父进程不会通过以下方式与其任何子进程通信,管道,必须确保尽早关闭管道的两端足够(例如在等待之前),以便其子代可以接收EOF指示在读取(或获取SIGPIPE信号或在写),而不是无限期地阻止。即使父级在不使用dup()
的情况下使用管道,也应通常至少会关闭管道的一端,这种情况极少发生一个在单个管道的两端进行读写的程序。
请注意,dup()
选项fcntl()
,并且fcntl()
的F_DUPFD
和dup2()
选项也可以进入讨论。
如果您使用O_CLOEXEC
及其广泛的支持功能系列(总共21个功能),您将需要查看如何在生成的过程中关闭文件描述符(open()
,等)。
请注意,使用open()
比使用FD_CLOEXEC
更安全由于多种原因。一种是如果您要强制文件描述符大于通常,F_DUPFD_CLOEXEC
是唯一可行的方法。另一个是如果fcntl()
与posix_spawn()
相同(例如,两个posix_spawn()
),则posix_spawn_file_actions_addclose()
正确处理它(在复制posix_spawn_file_actions_addclose()
之前不会关闭dup2(a, b)
)而单独的close(b); dup(a, b)
和dup2()
严重失败。这是不可能的情况,但也不是不可能的情况。
您的代码中也有一些未使用的定义和未使用的变量。留下所有评论,并进行适当的修复,最后我得到:
a
运行时产生:
b
看起来不错。