我对两个程序的交互有问题:
计划I 必须定期检查是否有来自计划II的数据。这应该是非阻塞的。
程序II 可以在多个实例中运行,因此是并行的。它将一些数据发送到程序I然后退出。数据的确切顺序并不重要,如果在1秒后接收到1秒后发送的数据就足够了。
我的第一种方法是使用FIFO: "服务器"
int main()
{
int fd;
unlink("/tmp/ctl_fifo");
if (mkfifo("/tmp/ctl_fifo", 0666) == -1)
{
printf("Error creating FIFO\n");
}
while (true)
{
if ((fd = open("/tmp/ctl_fifo", O_RDONLY | O_NONBLOCK)) < 0)
{
printf("Error opening FIFO\n");
}
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 2000;
fd_set set;
FD_ZERO(&set);
FD_SET(fd, &set);
select(fd + 1, &set, NULL, NULL, &timeout);
if (FD_ISSET(fd, &set))
{
char buf[20];
int r = read(fd,buf, sizeof(buf));
printf("%s\n", buf);
}
sleep(1);
}
return 0;
}
&#34;客户机&#34;
int main()
{
while (true)
{
int fd;
fd = open("/tmp/ctl_fifo", O_WRONLY);
if (fd < 0)
{
printf("Error opening fifo\n");
}
char buf[] = "Blablubb";
write(fd, buf, sizeof(buf));
sleep(0.1);
}
return 0;
}
问题在于数据可能会被扰乱。输出看起来像这样:
Blablubb
ablubb
ubb
b
Blablubb
...
我的问题是:我做错了什么?有没有办法确保数据不会被扰乱?或者是否有完全不同的方法来处理这个问题?
答案 0 :(得分:2)
首先,您有严重的资源泄漏;每次你的循环运行时open
一个新流,并在循环结束时迭代流泄漏,漂浮在稀薄的空气中,好像它从未存在过......问题是它确实存在,并且你没有close
它。
其次,当您使用O_NONBLOCK
打开您的信息流时,您不需要使用select
。
read
会在没有任何内容可读时立即返回(错误值),并使用O_NONBLOCK
打开流。
int r = read(fd,buf, sizeof(buf));
printf("%s\n", buf);
read
会返回ssize_t
(签名等效于size_t
)。因此int r
应为ssize_t r
。
继续(从前一段)到printf
...
printf("%s\n", buf); // THIS IS WRONG!
您需要先检查r
,然后开始。完全有可能没有收到任何字节,buf
包含纯垃圾。也可以合并两个写入(并且最终只能打印其中一个)。
为了简单起见,我建议您一次接收(并打印)一个字节,除非您收到'\0'
;打印'\n
&#39;而不是'\0'
。像这样:
int fd = open("/tmp/ctl_fifo", O_RDONLY | O_NONBLOCK);
if (fd < 0)
{
printf("Error opening FIFO\n");
}
for (;;)
{
unsigned char c;
ssize_t r = read(fd, &c, 1);
if (r < 0 && errno == EAGAIN) {
/* read sets EAGAIN when no data is available on otherwise valid
* non-blocking streams, and returns -1... so we continue looping
* when that happens */
continue;
}
if (r <= 0) {
/* Any value less than zero without errno == EAGAIN should terminate
* ... and r == 0 means EOF */
break;
}
putchar(c == '\0' ? '\n' : c);
}
close(fd);