[a] 概述node
[b] kqueue / kevent / EV_SET數組
#include <sys/types.h> #include <sys/event.h> #include <sys/time.h> int kqueue(void)
//成功返回 kqueue 標識符,供 kevent 函數首個參數使用,出錯返回 -1 int kevent(int kq, const struct kevent *changelist, int nchange, struct kevent *eventlist, int nevent, const struct timespec *timeout)
//成功返回 eventlist 數組的元素個數,出錯信息寫入 struct kevent 中的 flag 字段,不能寫入的出錯信息返回 -1,若 timeout 超時,則返回 0 EV_SET(kev, ident, filter, flags, fflags, data, udata)
//kev 是指向 struct kevent 的指針,其他字段依次對應於 struct kevent 中的字段
struct kevent { uintptr_t ident; //event 標識符,根據 filter 的不一樣能夠爲 fd、pid 等 short filter; //監聽類別(目標),如 socket、process 等 u_short flags; //通用標誌,可用於保存返回信息 u_int fflags; //特定 filter 的專有標誌,可用於保存專有返回信息 intptr_t data; //特定 filter 存儲專有信息 void *udata; //進程預約義內容,常做識別用途,kqueue 不更改此項,原樣返回其內容 }
[c] filter 及專有規則app
#define EVFILT_READ (-1) #define EVFILT_WRITE (-2) #define EVFILT_AIO (-3) /* attached to aio requests */ #define EVFILT_VNODE (-4) /* attached to vnodes */ #define EVFILT_PROC (-5) /* attached to struct proc */ #define EVFILT_SIGNAL (-6) /* attached to struct proc */ #define EVFILT_TIMER (-7) /* timers */ #define EVFILT_PROCDESC (-8) /* attached to process descriptors */ #define EVFILT_FS (-9) /* filesystem events */ #define EVFILT_LIO (-10) /* attached to lio requests */
#define NOTE_DELETE 0x0001 /* vnode was removed */ #define NOTE_WRITE 0x0002 /* data contents changed, a write occurred on the file */ #define NOTE_EXTEND 0x0004 /* size increased */ #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ #define NOTE_OPEN 0x0080 /* vnode was opened */ #define NOTE_CLOSE 0x0100 /* file closed, fd did not allowed write */ #define NOTE_READ 0x0400 /* file was read */
#define NOTE_EXIT 0x80000000 /* process exited, exit status will be stored in 'data' */ #define NOTE_FORK 0x40000000 /* process forked */ #define NOTE_EXEC 0x20000000 /* process exec'd */ #define NOTE_TRACK 0x00000001 /* follow across forks */ #define NOTE_TRACKERR 0x00000002 /* could not track child */ #define NOTE_CHILD 0x00000004 /* am a child process */
[d] 通用標誌:flags異步
/* actions */ #define EV_ADD 0x0001 /* add event to kq (implies enable) */ #define EV_DELETE 0x0002 /* delete event from kq */ #define EV_ENABLE 0x0004 /* enable event */ #define EV_DISABLE 0x0008 /* disable event (not reported) */ #define EV_FORCEONESHOT 0x0100 /* enable _ONESHOT and force trigger */ /* flags */ #define EV_ONESHOT 0x0010 /* only report one occurrence */ #define EV_CLEAR 0x0020 /* clear event state after reporting */ #define EV_RECEIPT 0x0040 /* force EV_ERROR on success, data=0 */ #define EV_DISPATCH 0x0080 /* disable event after once reporting */ #define EV_SYSFLAGS 0xF000 /* reserved by system */ #define EV_DROP 0x1000 /* note should be dropped */ #define EV_FLAG1 0x2000 /* filter-specific flag */ #define EV_FLAG2 0x4000 /* filter-specific flag */ /* returned values */ #define EV_EOF 0x8000 /* EOF detected */ #define EV_ERROR 0x4000 /* error, data contains errno */
[e] 樣例 socket
#include <sys/types.h> #include "sys/event.h" #include <sys/time.h> #include <fcntl.h> #include <unistd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> char *t0 = "/tmp/test_0"; char *t1 = "/tmp/test_1"; void unlinktmp(int signo) { unlink(t0); unlink(t1); printf("%s, %s deleted! \n", t0, t1); exit(0); } int main(void) { struct kevent event[2]; struct kevent tevent[2]; int kq, ret; unsigned long fd_0, fd_1; struct sigaction act; act.sa_handler=unlinktmp; sigemptyset(&act.sa_mask); act.sa_flags=0; sigaction(SIGINT, &act, NULL); fd_0 = open(t0, O_WRONLY|O_CREAT|O_TRUNC, 0600); fd_1 = open(t1, O_WRONLY|O_CREAT|O_TRUNC, 0600); kq = kqueue(); if (kq == -1) { perror("kqueue()"); } EV_SET(&event[0], fd_0, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_LINK|NOTE_EXTEND, 0, NULL); EV_SET(&event[1], fd_1, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_LINK|NOTE_EXTEND, 0, NULL); kevent(kq, event, 2, NULL, 0, NULL); while(1) { ret = kevent(kq, NULL, 0, tevent, 2, NULL); if (ret < 0) { perror("kevent"); } else { for(int i = 0; i < ret; ++i) { if (tevent[i].fflags & NOTE_LINK) { printf("%s: link num changed! \n", tevent[i].ident == fd_0 ? t0 : t1); } else if (tevent[i].fflags & NOTE_EXTEND) { printf("%s: extanded! \n", tevent[i].ident == fd_0 ? t0 : t1); } else { printf("%s: nothing happened!\n", tevent[i].ident == fd_0 ? t0 : t1); } } } } }