写入管道或管道
Posted
技术标签:
【中文标题】写入管道或管道【英文标题】:Writing to pipe or pipes 【发布时间】:2011-10-30 17:20:15 【问题描述】:理论上最好的方法是什么?我需要让用户输入要发送到管道的进程数,例如“3”,当它在每次迭代时循环三个 [三个什么?] 时,我需要创建一个进程,将它[what?]发送到管道并打印出来。
下次用户输入另一个数字时,比如“4”,它应该打印之前的 3 + 1.. 我正在处理这个,但不明白怎么做。这是我的代码。我只需要指导,无需尝试为我解决它(但建议将不胜感激)。
现在我可以通过管道发送一个并返回它,但随后管道关闭并且它不允许其他进程进入那里。
【问题讨论】:
您对您想要做什么的解释尚不清楚。请更仔细地表达您的要求。 如果程序正常运行,它的输出应该是什么样子?为什么要使用命名管道?如果您将拥有的管道数量是动态的,那么它们似乎是一个糟糕的选择,正如问题陈述所暗示的那样。 添加了作业标签。如果它毕竟不是家庭作业,请随意删除它。 是的,它是作业的一部分,我被卡住了,它应该显示我在程序“这个过程是......”中写的内容。另外,我需要使用命名管道,就像之前我们使用未命名的一样。所以基本上如果我输入“3”它应该打印我们传递给管道的三个进程ID @user975582:您对输出应该是什么样子的解释并不是特别有帮助。请编辑您的原始问题,并在一个部分中显示一个特定且完整的示例,说明如果程序正常运行,输出会是什么样子。 【参考方案1】:建议 #1:使用函数
使用函数,即使是小工作,例如:
void create_fifo(const char *name)
/* Create the first named - pipe */
int ret_val = mkfifo(name, 0666);
if ((ret_val == -1) && (errno != EEXIST))
perror("Error creating the named pipe");
exit(1);
现在您可以简单地在主程序中编写:
create_fifo(PIPE1);
create_fifo(PIPE5);
这减少了主程序中的混乱。它还遵循敏捷原则 DRY - 不要重复自己。
建议 #2:错误检查系统调用。
您这样做是为了创建 FIFO,这很好。你不为open()
电话,或read()
或write()
电话。你可能应该。我在我的程序中使用类似于以下的函数:
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
static const char *arg0 = "did not call err_setarg0(argv[0])";
void err_setarg0(const char *argv0)
arg0 = argv0;
void err_exit(const char *fmt, ...)
int errnum = errno; /* Capture errno before it is changed */
va_lists args;
fprintf(stderr, "%s: ", arg0);
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
exit(1);
然后您可以使用:
if ((rdfd1 = open(PIPE1, O_RDONLY)) < 0)
err_exit("Failed to open FIFO %s for reading: ", PIPE1);
if ((wrfd1 = open(PIPE5, O_WRONLY)) < 0)
err_exit("Failed to open FIFO %s for writing: ", PIPE5);
建议#3:做一个迭代服务器
您的服务器程序当前打开 FIFO 一次,然后从一个读取,写入另一个,然后终止。您需要围绕此代码的某些部分进行循环,可能是两个嵌套循环。您必须决定是否需要一个内部循环来读取直到 EOF。您还需要知道如何终止服务器。
建议 #4:也许服务器需要管道名称作为参数
您的服务器目前使用固定的 FIFO 名称。您可能需要它将输入和输出文件名作为命令行参数,这样当您的客户端生成多个服务器时,每个服务器都可以拥有自己的一组 FIFO,而不是所有进程共享相同的两个 FIFO,这将导致混乱和混乱。
确实,生成名称的需求使整个设计受到质疑 - 您确定使用 FIFO 是最好的方法吗?在我看来,匿名管道会更好地为您服务。您不必发明名称,服务器只需从其标准输入读取并将(修改的?)数据写入其标准输出,因此您甚至可以简单地使用 cat
或 tr
或 sed
或...作为您的服务器。
显然,如果您使用管道,则需要仔细检查,但您还需要仔细检查每个服务器的 FIFO 对。
【讨论】:
非常感谢,我会遵循您的指导方针,但它仍然没有回答我如何将多个进程传递给一个或多个管道并在客户端打印它们...... 循环是在服务器端还是在客户端? 另外,如何保持管道打开以继续接收请求? 我还建议他使用数组而不是 var1、var2、var3、var4 @Dave:是的,我完全同意数组而不是重复 varN。代码可能会受益于将两个文件描述符(可能是两个管道名称)和缓冲区捆绑到一个方便的单元中的小结构 - 然后它可以使用这些结构的数组。以及操作这些结构的各个方面的函数。以上是关于写入管道或管道的主要内容,如果未能解决你的问题,请参考以下文章