mkfifo 使 2 个进程相互通信
mkfifo make 2 processes talk to each other
我正在尝试编写 2 个程序,它们将使用 fifo 管道相互通信。
我使用了示例 here(第 5.2 节),但我将那里的 mknod 更改为 mkfifo,并尝试将 gets 更改为 fgets。
这是代码(写入 fifo 的一个程序):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /*mkfifo, open */
#include <sys/wait.h>
#include <sys/stat.h> /* mkfifo, open */
#include <fcntl.h> /*open */
#define FIFO_PATH "/home/hana/Desktop"
#define BUFFER_SIZE 300
int main()
{
char buffer[BUFFER_SIZE];
int fd;
int wStatus;
mkfifo(FIFO_PATH, 666);
printf("waiting for readers\n");
fd = open(FIFO_PATH, O_RDWR);
while (fgets(buffer, BUFFER_SIZE, fd), !feof(stdin))
{
if ((wStatus = write(fd, buffer, strlen(buffer))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", wStatus);
}
return 0;
}
我收到编译错误:传递 fgets 的参数 3 从整数生成指针。
所以 fgets 期待 FILE* 而不是文件描述符。
我应该怎么办?改变一些东西以便 fgets 工作?使用另一个功能?
我正在用 gcc 编译(ansi,迂腐)。
谢谢
whjm 的回答是您诊断错误的原因,但我认为您的意思可能是
fgets(buffer, BUFFER_SIZE, stdin)
// ^^^^^
从管道读取数据然后立即将同样的内容写回管道是没有意义的。另外,如果你从不读 stdin
,feof(stdin)
永远不会是真的。
此外,使用 fgets 仅检查空结果,然后在循环外检查 eof:
while (fgets(...) != NULL)
{
...
}
if (!feof(stdin))
{
// error handling
}
mkfifo()
只是在文件系统中创建特殊节点。您可以以任何方式自由打开它。实际上有两种选择 - POSIX "non-buffered" I/O: open()/write()/read()
或标准缓冲 I/O: fopen()/fread()/fwrite()
。第一个系列对文件描述符进行操作,而第二个系列使用所谓的文件流:FILE
。您不能随意混合这些 API。只需选择一个并坚持下去。
与低级非缓冲 I/O 相比,标准 I/O 库提供了一些有用的额外功能。就像您尝试使用的 fgets()
一样。在这种情况下,使用标准流并将 open()
替换为:
是合理的
FILE* stream = fopen(FIFO_PATH, "r+");
因此程序将使用 FILE*
而不是普通文件描述符。另外write()
需要改成fwrite()
紧跟着fflush()
保证写入的数据传到FIFO。
P.S。在必要的情况下,可以 "wrap" 由 open()
(或其他东西)返回的低级描述符与标准 FILE*
。参见 fdopen()
。但这很像使用标准 I/O API 和无法用 fopen()
.
打开的特殊文件对象的解决方法
我正在尝试编写 2 个程序,它们将使用 fifo 管道相互通信。 我使用了示例 here(第 5.2 节),但我将那里的 mknod 更改为 mkfifo,并尝试将 gets 更改为 fgets。 这是代码(写入 fifo 的一个程序):
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h> /*mkfifo, open */
#include <sys/wait.h>
#include <sys/stat.h> /* mkfifo, open */
#include <fcntl.h> /*open */
#define FIFO_PATH "/home/hana/Desktop"
#define BUFFER_SIZE 300
int main()
{
char buffer[BUFFER_SIZE];
int fd;
int wStatus;
mkfifo(FIFO_PATH, 666);
printf("waiting for readers\n");
fd = open(FIFO_PATH, O_RDWR);
while (fgets(buffer, BUFFER_SIZE, fd), !feof(stdin))
{
if ((wStatus = write(fd, buffer, strlen(buffer))) == -1)
perror("write");
else
printf("speak: wrote %d bytes\n", wStatus);
}
return 0;
}
我收到编译错误:传递 fgets 的参数 3 从整数生成指针。 所以 fgets 期待 FILE* 而不是文件描述符。 我应该怎么办?改变一些东西以便 fgets 工作?使用另一个功能?
我正在用 gcc 编译(ansi,迂腐)。
谢谢
whjm 的回答是您诊断错误的原因,但我认为您的意思可能是
fgets(buffer, BUFFER_SIZE, stdin)
// ^^^^^
从管道读取数据然后立即将同样的内容写回管道是没有意义的。另外,如果你从不读 stdin
,feof(stdin)
永远不会是真的。
此外,使用 fgets 仅检查空结果,然后在循环外检查 eof:
while (fgets(...) != NULL)
{
...
}
if (!feof(stdin))
{
// error handling
}
mkfifo()
只是在文件系统中创建特殊节点。您可以以任何方式自由打开它。实际上有两种选择 - POSIX "non-buffered" I/O: open()/write()/read()
或标准缓冲 I/O: fopen()/fread()/fwrite()
。第一个系列对文件描述符进行操作,而第二个系列使用所谓的文件流:FILE
。您不能随意混合这些 API。只需选择一个并坚持下去。
与低级非缓冲 I/O 相比,标准 I/O 库提供了一些有用的额外功能。就像您尝试使用的 fgets()
一样。在这种情况下,使用标准流并将 open()
替换为:
FILE* stream = fopen(FIFO_PATH, "r+");
因此程序将使用 FILE*
而不是普通文件描述符。另外write()
需要改成fwrite()
紧跟着fflush()
保证写入的数据传到FIFO。
P.S。在必要的情况下,可以 "wrap" 由 open()
(或其他东西)返回的低级描述符与标准 FILE*
。参见 fdopen()
。但这很像使用标准 I/O API 和无法用 fopen()
.