使用 select() 和 O_NONBLOCK 从 FIFO 读取两个连续的写入
Reading two consecutive writes from a FIFO using select() and O_NONBLOCK
我正在尝试写两个连续的字符串。问题是在 reader.
上使用 O_NONBLOCK
时 reader 一直在问候 EAGAIN
知道为什么它在使用 O_NONBLOCK 时不起作用,不应该 select()
处理这个块吗?
reader.c
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main() {
int fd;
char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR | O_NONBLOCK);
write(fd, "12345678", strlen("12345678"));
write(fd, "HelloWorld", strlen("HelloWorld"));
close(fd);
return 0;
}
writer.c
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
char buf[BUFSIZ] = { 0 }, buf2[BUFSIZ] = { 0 };
int read1 = 0, read2 = 0;
int main() {
int fd = 0, a = 0, b = 0 ;
char *myfifo= "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd_set set;
if ((fd = open(myfifo, O_RDWR | O_NONBLOCK)) < 0)
exit(1);
while (1) {
FD_ZERO(&set);
FD_SET(fd, &set);
if ((select(fd+1, &set, NULL, NULL, NULL)) < 1)
exit(1);
if (FD_ISSET(fd, &set)) {
int total = 0;
if ((total = read(fd, buf + read1, sizeof(uint32_t) * 2) - read1) <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
read1 += total;
if ((total = read(fd, buf2 + read2, BUFSIZ - read2)) <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
read2 += total;
fprintf(stderr, "%s %d, %d, %s\n", buf, a, b, buf2);
memset(buf, 0, BUFSIZ);
memset(buf2, 0, BUFSIZ);
read1 = read2 = 0;
}
}
return 0;
}
您在循环中两次调用 fd 上的 read
,有可能第一个 read
读取可用数据,第二个 read
将失败并返回 EAGAIN
。
在执行任何 read
之前,您应该使用 select 测试准备情况,而不仅仅是第一个。因为 fifos 是流,这意味着,您必须维护自己的不同数据片段的边界。
char buf[BUFSIZ];
if (FD_ISSET(fd, &set)) {
int total = 0;
int off = 0;
total = read(fd, buf, sizeof buf);
if (total <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
// retrieve the data based on how many bytes you have read
if (total >= sizeof(uint32_t) * 2) {
...
}
}
另外,fifo的读端建议用O_RDONLY
打开,写端用O_WRONLY
打开
我正在尝试写两个连续的字符串。问题是在 reader.
上使用O_NONBLOCK
时 reader 一直在问候 EAGAIN
知道为什么它在使用 O_NONBLOCK 时不起作用,不应该 select()
处理这个块吗?
reader.c
#include <fcntl.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
int main() {
int fd;
char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR | O_NONBLOCK);
write(fd, "12345678", strlen("12345678"));
write(fd, "HelloWorld", strlen("HelloWorld"));
close(fd);
return 0;
}
writer.c
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
char buf[BUFSIZ] = { 0 }, buf2[BUFSIZ] = { 0 };
int read1 = 0, read2 = 0;
int main() {
int fd = 0, a = 0, b = 0 ;
char *myfifo= "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd_set set;
if ((fd = open(myfifo, O_RDWR | O_NONBLOCK)) < 0)
exit(1);
while (1) {
FD_ZERO(&set);
FD_SET(fd, &set);
if ((select(fd+1, &set, NULL, NULL, NULL)) < 1)
exit(1);
if (FD_ISSET(fd, &set)) {
int total = 0;
if ((total = read(fd, buf + read1, sizeof(uint32_t) * 2) - read1) <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
read1 += total;
if ((total = read(fd, buf2 + read2, BUFSIZ - read2)) <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
read2 += total;
fprintf(stderr, "%s %d, %d, %s\n", buf, a, b, buf2);
memset(buf, 0, BUFSIZ);
memset(buf2, 0, BUFSIZ);
read1 = read2 = 0;
}
}
return 0;
}
您在循环中两次调用 fd 上的 read
,有可能第一个 read
读取可用数据,第二个 read
将失败并返回 EAGAIN
。
在执行任何 read
之前,您应该使用 select 测试准备情况,而不仅仅是第一个。因为 fifos 是流,这意味着,您必须维护自己的不同数据片段的边界。
char buf[BUFSIZ];
if (FD_ISSET(fd, &set)) {
int total = 0;
int off = 0;
total = read(fd, buf, sizeof buf);
if (total <= 0) {
fprintf(stderr, "%s\n", strerror(errno));
continue;
}
// retrieve the data based on how many bytes you have read
if (total >= sizeof(uint32_t) * 2) {
...
}
}
另外,fifo的读端建议用O_RDONLY
打开,写端用O_WRONLY
打开