- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个应用程序,该应用程序使用 fifos 进行 IPC,并使用事件通知 API(例如 epoll 或 kqueue)来监视 fifos 以获取要读取的数据。
应用程序期望,如果 fifo 的写入器终止,则读取器将通过事件通知 API 接收事件,从而允许读取器注意到写入器已终止。
我目前正在将此应用程序移植到 macos,但我在使用 kqueue 时遇到了一些奇怪的行为。我已经能够创建此行为的重现器:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/errno.h>
static int child() {
char child_fifo_path[64];
char parent_fifo_path[64];
printf("Child %d\n", getpid());
sprintf(child_fifo_path, "/tmp/child-%d", getpid());
sprintf(parent_fifo_path, "/tmp/parent-%d", getpid());
mkfifo(child_fifo_path, 0644);
mkfifo(parent_fifo_path, 0644);
int parent_fd = open(parent_fifo_path, O_RDONLY);
if (parent_fd == -1) {
perror("open");
return EXIT_FAILURE;
}
unsigned char parent_val;
read(parent_fd, &parent_val, 1);
printf("Received %hhx from parent\n", parent_val);
int child_fd = open(child_fifo_path, O_WRONLY);
if (child_fd == -1) {
perror("open");
return EXIT_FAILURE;
}
write(child_fd, &parent_val, 1);
printf("Wrote %hhx to parent\n", parent_val);
close(parent_fd);
close(child_fd);
return EXIT_SUCCESS;
}
static int parent(pid_t child_pid) {
char child_fifo_path[64];
char parent_fifo_path[64];
printf("Parent %d\n", getpid());
sprintf(child_fifo_path, "/tmp/child-%d", child_pid);
sprintf(parent_fifo_path, "/tmp/parent-%d", child_pid);
int result = -1;
while (result == -1) {
struct stat buf;
result = stat(child_fifo_path, &buf);
if (result == -1) {
if (errno != ENOENT) {
perror("open");
return EXIT_FAILURE;
}
}
}
unsigned char val = 20;
int parent_fd = open(parent_fifo_path, O_WRONLY);
if (parent_fd == -1) {
perror("open");
return EXIT_FAILURE;
}
write(parent_fd, &val, 1);
printf("Wrote %hhx to child\n", val);
int child_fd = open(child_fifo_path, O_RDONLY);
if (child_fd == -1) {
perror("open");
close(parent_fd);
return EXIT_FAILURE;
}
int kq = kqueue();
struct kevent event;
EV_SET(&event, child_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
result = kevent(kq, &event, 1, NULL, 0, NULL);
if (result == -1) {
perror("kevent");
close(child_fd);
close(parent_fd);
return EXIT_FAILURE;
}
int done = 0;
while (!done) {
memset(&event, 0, sizeof(event));
printf("Waiting for events\n");
result = kevent(kq, NULL, 0, &event, 1, NULL);
if (result == -1) {
perror("kevent");
close(child_fd);
close(parent_fd);
return EXIT_FAILURE;
}
if (event.ident == child_fd) {
if (event.flags & EV_EOF) {
printf("Child exited\n");
done = 1;
}else if ( event.data > 0 ) {
unsigned char child_val;
result = read(child_fd, &child_val, 1);
if (result == -1) {
perror("read");
return EXIT_FAILURE;
}
printf("Received %hhx from child\n", child_val);
}
}
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
pid_t child_pid = fork();
if (child_pid == -1) {
perror("fork");
return EXIT_FAILURE;
}
if (child_pid) {
return parent(child_pid);
} else {
return child();
}
}
此重现器 fork 一个子进程,该子进程创建 2 个 fifo:/tmp/parent-$CHILD_PID
和 /tmp/child-$CHILD_PID
。父进程等待 /tmp/parent-$CHILD_PID
创建,然后向其中写入一个字节。子进程打开 /tmp/parent-$CHILD_PID
并阻止读取父进程写入的字节。完成后,子进程将通过 /tmp/child-$CHILD_PID
将相同的字节写入父进程。父级使用 kqueue 来观察对 /tmp/child-$CHILD_PID
的写入。
这一系列事件运行良好。
当子进程关闭其引用 /tmp/child-$CHILD_PID
的文件时,会出现此问题。我发现这个事件没有通过 kqueue 报告给父级。
最有趣的部分:这段代码在 FreeBSD 上的工作方式符合我的预期。
版本信息:
Mac OS X:10.11.6
FreeBSD 10.4-RELEASE-p3
在这种情况下,macos 上的 kqueue 和 FreeBSD 上的 kqueue 有区别吗?如果是这样,是否有一些文档记录了这种差异?
最佳答案
这不是您问题的最佳答案,但我希望可以帮助您找到使用 kqueue 时可能影响代码行为的其他差异。之间macOS和 FreeBSD
就我而言,我使用 kqueue EVFILT_VNODE
来检查更改,但根据操作系统,我需要定义不同的标志 openModeDir使用syscall.Open
对于 macOS ( openmode_darwin.go ),我使用这个:
openModeDir = syscall.O_EVTONLY | syscall.O_DIRECTORY
openModeFile = syscall.O_EVTONLY
对于 FreeBSD ( openmode.go ),我使用:
openModeDir = syscall.O_NONBLOCK | syscall.O_RDONLY | syscall.O_DIRECTORY
openModeFile = syscall.O_NONBLOCK | syscall.O_RDONLY
来自macOS docs open(2) ,这是标志描述:
O_EVTONLY descriptor requested for event notifications only
来自 FreeBSD open(2) ,没有 O_EVTONLY
。
把所有这些放在一起,这就是我调用 kqueue 的方式:
...
watchfd, err := syscall.Open(dir, openModeDir, 0700)
if err != nil {
return err
}
kq, err := syscall.Kqueue()
if err != nil {
syscall.Close(watchfd)
return err
}
ev1 := syscall.Kevent_t{
Ident: uint64(watchfd),
Filter: syscall.EVFILT_VNODE,
Flags: syscall.EV_ADD | syscall.EV_ENABLE | syscall.EV_CLEAR,
Fflags: syscall.NOTE_WRITE | syscall.NOTE_ATTRIB,
Data: 0,
}
...
我正在使用go ,但正如之前提到的,希望能给您在处理 Kqueue
时提供一个想法,就我而言,这个简单的标志更改会产生影响。
关于c - Mac OS 和 FreeBSD 之间 kqueue 处理 fifo 的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49481723/
使用 kqueue 注册事件时与该事件相关的 ID 提供类型;例如,文件描述符用于标识文件以 watch int kq; struct kevent ke; kq = kqueue(); fd = o
我正在尝试编写一个小程序来发送和接收 UDP 流量并通过 HTTP 接口(interface)接收命令。 HTTP 服务器位于一个 multiprocessing.Process 中; UDP 服务器
我正在尝试使用 kqueue 观察目录大小的变化,这可能吗?这样做的原因是因为我正在监视目录,每当事件触发时,我都会统计目录并比较上次修改时间等,以确定是否发生了内容修改、添加、删除或重命名事件。我的
我使用 kquque 来监控桌面: 标志 - EV_ADD | EV_CLEAR fflags - 注意删除 |注_写 |注意_扩展 |注_属性 |注意_LINK |注意_RENAME | NOTE_
kqueue(在 OS X 上)对读/写常规文件有用吗?我知道 epoll 不对 Linux 上的常规文件有用,所以我想知道 kqueue 是否也是如此。 编辑:我不是说读/写文件,显然 read()
好的:我正在 iPhone OS 应用程序中实现文件共享,当然这意味着文件系统监控。耶! 基本上,当用户将文件操作到 iTunes 中我的应用程序部分时,操作系统会在我可以访问的目录中进行复制和/或删
我正在 mac os x 上使用 Kqueues,并尝试监视文件夹 所以我使用了 EVFILT_VNODE 过滤器,并且我想在删除文件时收到通知,我尝试了 NOTE_DELETE 但它仅检测文件何时通
在 MacOS 中,我使用 O_NONBLOCK 设置了一个读+写套接字来连接到远程服务器。我使用 kqueue 来等待和协调 I/O 事件。对 connect() 的调用立即触发 EINPROGRE
在 mac 上我使用 kqueue,它表明 udata 未更改。但是,kevent 调用的 event_data 返回的数组正在进行一些修改。什么可能导致这种情况?我将指针传递给转换为 void* 的
我在做什么 我正在实现一个基于 python/kqueue (FreeBSD) 的解决方案来跟踪对特定日志文件的更改,当满足 KQ_NOTE_WRITE fflag 时,对文件的更改将由我的 pyth
kqueue mechanism有一个事件标志,EV_RECEIPT ,根据链接的手册页: ... is useful for making bulk changes to a kqueue with
我编写了并发应用程序并发现了错误: buildFdSets: file descriptor out of range 我发现这是一个进程中文件描述符数量的操作系统限制,在我的 FreeBSD 中是
我很难理解如何将 kqueue 用于用户空间事件。 我寻找 2 个用例。 用例 1:手动重置事件 用例 2:自动重置事件 我想我了解如何使用 kqueue() 和 kevent(),但我不清楚传递给
我正在学习有关 kqueue 的教程(特别是 http://eradman.com/posts/kqueue-tcp.html 和 https://wiki.netbsd.org/tutorials/
我知道,如果远程主机优雅地关闭连接,epoll将报告EPOLLIN,并且调用read或recv不会阻塞,并且将返回0字节(即流结束)。 但是,如果连接未正常关闭,并且 write 或 send 操作失
我的开发机器是 MacBook(当然有 kqueue)。然而,在生产环境中,我们运行的是 Linux(当然使用 epoll)。显然,要了解我的代码的性能特征,我需要使用 epoll 运行它。也就是说,
如果一个线程(比如 X)正在等待 epoll_wait(),另一个线程(比如 Y)是否可以调用 epoll_ctl() 来注册对文件的兴趣描述符 9。之前在线程X中调用epoll_wait()能否返回
我正在努力在 epoll 和 kqueue 标志之间画一条平行线,特别是 EPOLLONESHOT EPOLLET EPOLLEXCLUSIVE 和 EV_CLEAR/EV_DISPATCH/EV_O
Python Epoll 有一个名为 epoll.unregister 的函数,它从 epoll 对象中删除已注册的文件描述符。有谁知道Kqueue中与此类似的功能是什么。对于 kqueue 我只能找
我试图了解 kqueue 中 EV_DISABLE 和 EV_ENABLE 的用例。 int KQueue = kqueue(); struct kevent ev = { .ident = fd
我是一名优秀的程序员,十分优秀!