来自Kqueue维基百科页面:
Kqueue在内核和用户空间之间提供高效的输入和输出事件管道.因此,可以修改事件过滤器以及接收未决事件,同时每个主事件循环迭代仅使用对kevent(2)的单个系统调用.这与较旧的传统轮询系统调用形成对比,例如poll(2)和select(2)效率较低,尤其是在轮询大量文件描述符上的事件时
这听起来很不错.我为我的服务器定位FreeBSD,我正在处理大量的网络套接字fd - 在它们上面使用select()并确定从哪里读取数据.我宁愿使用kevent()调用来获得更高的性能,因为它就是它的用途!
我在这里阅读了关于FreeBSD的kevent的手册页,但它对我来说很神秘,而且我找不到解释它的好资源.使用kevent替换select的一个例子可以解决我的问题,也可以帮助我更好地了解如何使用kevent().
kqueue(在OS X上)是否对读/写常规文件有用?我知道,epoll的是不是在Linux上常规文件有用的,所以我想知道如果同样是kqueue的事实.
编辑:我不是指读/写文件,显然read()和write()都是为了这个.我的意思是,"kqueue实际上对检测文件何时可读/可写有用吗?"
当事件注册时,kqueue提供与该事件类型相关的ID; 例如,文件描述符用于标识要监视的文件
int kq;
struct kevent ke;
kq = kqueue();
fd = open(argv[1], O_RDONLY);
EV_SET(&ke, fd, EVFILT_VNODE, EV_ADD, NOTE_DELETE | NOTE_RENAME, 0, NULL);
kevent(kq, &ke, 1, NULL, 0, NULL);
while (1) {
kevent(kq, NULL, 0, &ke, 1, NULL);
/* respond to file system event */
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我还需要响应其他事件类型这样的信号,我们需要一个新的kqueue实例,以避免与ident参数的
冲突kevent().
kq_sig = kqueue();
struct kevent ke_sig;
/* set the handler and ignore SIGINT */
signal(SIGINT, SIG_IGN);
EV_SET(&ke_sig, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
kevent(kq_sig, &ke_sig, 1, …Run Code Online (Sandbox Code Playgroud) 我想编写一个OSX(Snow Leopard)应用程序,它可以在特定目录中的文件发生更改时接收通知,并且我希望访问已更改的特定文件的路径.
我知道我可以用做这一点File System Events还是kqueue.前者没有提供更改哪个特定文件的详细信息(要求我构建我正在观看的目录的快照,然后扫描它以找出更改的文件).后者不支持递归观看(要求我以递归方式将监视添加到父目录中的每个文件和目录).
我已经找到了可以为我处理快照/递归乐趣的库,但找不到任何库.UKKQueue对于低级别的kqueue东西看起来像是一个很好的包装器,但似乎没有做递归.同样的GTMFileSystemKQueue.SCEvents看起来像一个很好的包装,File System Events但似乎没有找到更改的特定文件.
是否有一个库可以满足我的要求并且适合这些技术的objc项目?
我在Node v0.5.9上运行以下命令:
var fs = require("fs");
fs.watch("/Users/username/testingFsWatcher/",function(event,file) {
console.dir(arguments);
});
Run Code Online (Sandbox Code Playgroud)
然后我做:
cd /Users/username/testingFsWatcher/>file1 - > { '0': 'rename', '1': null }mkdir new_folder - > { '0': 'rename', '1': null }>new_folder/file2 - >没有事件触发/输出touch file1 - >没有事件触发/输出rm file1 - > { '0': 'rename', '1': null }我注意到的两件事似乎不正确:子目录(new_folder)没有被监视,对监视文件的更新/修改不会触发change事件.查看节点代码并测试它们似乎应该是可能的.
那么,是否可以fs.watch观看目录及其所有子目录?是否至少可以从文件修改中获取事件?另外,从我所知道的,fs.watch支持kqueue哪一个eventid(在OSX中),是否有可能得到它eventid?
注意:我是专门使用fs.watch而不是fs.watchFile因为我需要观看整个目录(最好是所有的子目录:).
谢谢您的帮助!
今天我将一些代码从 select() 移植到 kqueue(),我注意到 kevent() 似乎没有 select() 的“异常设置”功能的模拟。
也就是说,select()的函数签名是:
int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout);
Run Code Online (Sandbox Code Playgroud)
...对于 kevent(),EVFILT_READ 对应于 (readfds),EVFILT_WRITE 对应于 (writefds),但我没有看到任何像 EVFILT_ERROR 对应于 (errorfds) 的内容。
kevent() 下是否真的不支持套接字错误条件,或者是否存在但以某种对我来说不明显的方式实现?
我目前正在使用 kqueue 来处理服务器进程中每个线程的多个客户端,因此我不希望在出现信号 SIGPIPE 时终止线程,我只想从 kqueue 中删除相应的 socked id。所以我的问题是:有没有办法在 Signalhandle 中获取相应的 socketid 并将其解析回进程以将其从事件 kqueue 中删除,或者我是否只需将 SIG_IGN SIGPIPE 并通过返回 -1 来处理删除发送?它会在超时时间后返回-1值还是立即返回发送-1?
最后,如果信号忽略是我的解决方案: id 必须在哪里放置声明
typedef void (*sig_t) (int);
sig_t
signal(int sig, sig_t func);
Run Code Online (Sandbox Code Playgroud)
它必须在 main 函数中吗?或者在相应线程的开头?或者只是作为全局元素?
该kqueue的机制有一个事件标志,EV_RECEIPT根据链接的手册页,其中:
...对于对kqueue进行批量更改而不会耗尽任何待处理事件非常有用.当作为输入传递时,它强制
EV_ERROR始终返回.成功添加过滤器后,数据字段将为零.
然而,我的理解是,在不消耗任何挂起事件的情况下对kqueue进行批量更改是很简单的,只需将nevents参数传递给0 kevent,从而不从队列中抽取任何事件.考虑到这一点,为什么需要EV_RECEIPT?
OS X的Apple文档中的一些示例代码实际上使用了EV_RECEIPT:
kq = kqueue();
EV_SET(&changes, gTargetPID, EVFILT_PROC, EV_ADD | EV_RECEIPT, NOTE_EXIT, 0, NULL);
(void) kevent(kq, &changes, 1, &changes, 1, NULL);
Run Code Online (Sandbox Code Playgroud)
但是,看到changes在kevent调用之后从未检查过数组,我完全不清楚为什么EV_RECEIPT在这种情况下使用它.
EV_RECEIPT真的有必要吗?它在什么情况下真的有用?
我的开发机器是MacBook(当然有kqueue).但是,在生产中我们正在运行Linux(当然使用epoll).显然,要了解我的代码的性能特征,我需要使用epoll来运行它.那就是说,我在kqueue下看到的表现与epoll看到的相当接近?或者在任何情况下性能可能会有显着差异?在大多数情况下,似乎kqueue和epoll在性能方面非常相似,但我还没有真正做过非常彻底的测试.
如果它有所作为,我在Python中使用龙卷风.
我遇到了一个问题,我不确定是否是来自kqueue的预期行为,或者是否是我做错的事情.
我需要使用kqueue为单个套接字文件描述符安装单独的事件.单独的事件是(sockfd,EVFILT_READ)和(sockfd,EVFILT_WRITE).然而,当我从kqueue中拉出事件后,我从kqueue获得两个事件,但两个事件都包含(event.filter&EVFILT_READ)和(event.filter&EVFILT_WRITE).
我需要将它们分开,否则我不知道哪个事件实际上是准备好的,可读的还是写的?
以下是我用一些示例代码来说明问题.请记住,这只是测试代码,以确定为什么我在每个事件中都得到两个过滤器标志.
int main(int argc, char ** argv) {
//listening_sockfd = setup listening socket
//setup kqueue and vars
int kq = kqueue();
int res = 0;
int bufres = 0;
struct timespec ts = {0};
struct timespec * tsp = &ts;
struct kevent ke2[2];
//install read for listening socket
struct kevent ke1;
bzero(&ke1,sizeof(ke1));
ke1.ident = listening_sockfd;
ke1.flags = EV_ADD;
ke1.filter = EVFILT_READ;
res = kevent(kq,&ke1,1,NULL,0,tsp);
while(1) {
new_client:
//wait for a client to connect
res = kevent(kq,NULL,0,&ke1,1,NULL);
if(res …Run Code Online (Sandbox Code Playgroud) kqueue ×10
c ×4
macos ×3
freebsd ×2
sockets ×2
asynchronous ×1
epoll ×1
fsevents ×1
node.js ×1
objective-c ×1
performance ×1
python ×1
select ×1
signals ×1
tornado ×1