为不阻塞且可以重用的子进程创建非阻塞管道
Creating non blocking pipes to child that does not block and can be reused
我正在尝试使用管道创建进程间通信总线。
我可以向客户端发送消息,也可以在客户端接收消息。
我还尝试创建另一个方向相反的管道,child-> parent。
但是我需要这种通信是非阻塞的,我想在两个方向上发送消息,中间有一些未定义的时间间隔。
看来我不能发送超过一条消息,我认为这是由于 fclose();
关闭了流,但是如果我删除关闭,程序将停止工作...
如何使此代码通过管道实现非阻塞双向父 -> 子通信?
稍后我想使用 exec() 连接一个子二进制文件,并将这个二进制文件的标准输入、标准输出连接到我的父级,这样我就可以将消息传递给子级的标准输入并通过 "childParent"描述符。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define READ_SIDE 0
#define WRITE_SIDE 1
/* Read characters from the pipe and echo them to stdout. */
void
read_from_pipe (int file)
{
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
}
/* Write some random text to the pipe. */
void
write_to_pipe (int file, char * message)
{
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, message);
//fprintf (stream, "goodbye, world!\n");
//Dont forget to close
fclose (stream);
}
void end(){
//kill process and close pipes
}
int
main (void)
{
pid_t pid;
int parentToChild[2];
int childToParent[2];
/* Create the pipes. */
if (pipe (parentToChild))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
if (pipe (childToParent))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
/* Create the child process. */
pid = fork ();
if (pid == (pid_t) 0)
{
/* This is the child process.
Close other end first. */
close(childToParent[READ_SIDE]);
close (parentToChild[WRITE_SIDE]);
read_from_pipe (parentToChild[READ_SIDE]);
write_to_pipe(childToParent[WRITE_SIDE], "Child sent message to parent");
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
/* The fork failed. */
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
/* This is the parent process.
Close other end first. */
close(childToParent[WRITE_SIDE]);
close (parentToChild[READ_SIDE]);
write_to_pipe (parentToChild[WRITE_SIDE],"Parent sent message to child");
read_from_pipe(childToParent[READ_SIDE]);
//Send more messages...
return EXIT_SUCCESS;
}
}
更新
似乎有时通信只以一种方式发生,这取决于我猜哪个进程首先到达 read/write。
有几个问题需要考虑。首先,管道有一个有限的
最大长度(4096 在遥远的过去很常见);任何写一个
管道中的数据多于将阻塞的数据,任何读取也是如此
来自空管。这些是管道工作方式的基础,所以
当你谈到非阻塞时,你必须考虑到它们
(或者使用异步IO)。
其次,如果你真的需要在这个层面上控制事情,你可能
想考虑使用 Posix 级 IO,而不是流。如果你这样做
使用流(iostream 或 FILE*
),那么你必须考虑
考虑他们使用的缓冲。特别是,当您想确定
数据输出到管道,需要flush (fflush
on
FILE*
)。关于发送多个消息,以及
如果没有 fclose
,代码将无法工作,将 fclose
替换为
fflush
应该是解决此问题所需的全部内容。
当我在做的时候:你使用 fprintf
输出是非常
危险的。如果您收到来自外部来源的消息,并且
(可能)不知道它包含什么,你应该使用 fputs
来输出
它,或者可能是 fprintf( fd, "%s\n", message )
之类的东西(如果你
想追加一个新行)。正如您所做的那样,如果消息包含
a '%'
,会发生奇怪的事情。更一般地说,你应该更喜欢
更安全的 iostream,但对于像这样简单的事情,它不会
很重要。对于你实际做的事情,Posix 级 IO 是
可能恰到好处,或者更合适。 Posix级IO,你
没有得到任何格式或缓冲:但是因为你没有使用
格式化功能,以及缓冲它是您问题的一部分...
我正在尝试使用管道创建进程间通信总线。 我可以向客户端发送消息,也可以在客户端接收消息。
我还尝试创建另一个方向相反的管道,child-> parent。
但是我需要这种通信是非阻塞的,我想在两个方向上发送消息,中间有一些未定义的时间间隔。
看来我不能发送超过一条消息,我认为这是由于 fclose();
关闭了流,但是如果我删除关闭,程序将停止工作...
如何使此代码通过管道实现非阻塞双向父 -> 子通信?
稍后我想使用 exec() 连接一个子二进制文件,并将这个二进制文件的标准输入、标准输出连接到我的父级,这样我就可以将消息传递给子级的标准输入并通过 "childParent"描述符。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define READ_SIDE 0
#define WRITE_SIDE 1
/* Read characters from the pipe and echo them to stdout. */
void
read_from_pipe (int file)
{
FILE *stream;
int c;
stream = fdopen (file, "r");
while ((c = fgetc (stream)) != EOF)
putchar (c);
fclose (stream);
}
/* Write some random text to the pipe. */
void
write_to_pipe (int file, char * message)
{
FILE *stream;
stream = fdopen (file, "w");
fprintf (stream, message);
//fprintf (stream, "goodbye, world!\n");
//Dont forget to close
fclose (stream);
}
void end(){
//kill process and close pipes
}
int
main (void)
{
pid_t pid;
int parentToChild[2];
int childToParent[2];
/* Create the pipes. */
if (pipe (parentToChild))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
if (pipe (childToParent))
{
fprintf (stderr, "Pipe failed.\n");
return EXIT_FAILURE;
}
/* Create the child process. */
pid = fork ();
if (pid == (pid_t) 0)
{
/* This is the child process.
Close other end first. */
close(childToParent[READ_SIDE]);
close (parentToChild[WRITE_SIDE]);
read_from_pipe (parentToChild[READ_SIDE]);
write_to_pipe(childToParent[WRITE_SIDE], "Child sent message to parent");
return EXIT_SUCCESS;
}
else if (pid < (pid_t) 0)
{
/* The fork failed. */
fprintf (stderr, "Fork failed.\n");
return EXIT_FAILURE;
}
else
{
/* This is the parent process.
Close other end first. */
close(childToParent[WRITE_SIDE]);
close (parentToChild[READ_SIDE]);
write_to_pipe (parentToChild[WRITE_SIDE],"Parent sent message to child");
read_from_pipe(childToParent[READ_SIDE]);
//Send more messages...
return EXIT_SUCCESS;
}
}
更新 似乎有时通信只以一种方式发生,这取决于我猜哪个进程首先到达 read/write。
有几个问题需要考虑。首先,管道有一个有限的 最大长度(4096 在遥远的过去很常见);任何写一个 管道中的数据多于将阻塞的数据,任何读取也是如此 来自空管。这些是管道工作方式的基础,所以 当你谈到非阻塞时,你必须考虑到它们 (或者使用异步IO)。
其次,如果你真的需要在这个层面上控制事情,你可能
想考虑使用 Posix 级 IO,而不是流。如果你这样做
使用流(iostream 或 FILE*
),那么你必须考虑
考虑他们使用的缓冲。特别是,当您想确定
数据输出到管道,需要flush (fflush
on
FILE*
)。关于发送多个消息,以及
如果没有 fclose
,代码将无法工作,将 fclose
替换为
fflush
应该是解决此问题所需的全部内容。
当我在做的时候:你使用 fprintf
输出是非常
危险的。如果您收到来自外部来源的消息,并且
(可能)不知道它包含什么,你应该使用 fputs
来输出
它,或者可能是 fprintf( fd, "%s\n", message )
之类的东西(如果你
想追加一个新行)。正如您所做的那样,如果消息包含
a '%'
,会发生奇怪的事情。更一般地说,你应该更喜欢
更安全的 iostream,但对于像这样简单的事情,它不会
很重要。对于你实际做的事情,Posix 级 IO 是
可能恰到好处,或者更合适。 Posix级IO,你
没有得到任何格式或缓冲:但是因为你没有使用
格式化功能,以及缓冲它是您问题的一部分...