1 |
struct ev_io { |
2 |
int fd; |
3 |
int events; |
4 |
struct ev_watcher_list *list; |
5 |
int active; |
6 |
int pending; |
7 |
int priority; |
8 |
void * data; |
9 |
void (*cb)( struct ev_loop *loop, struct ev_io *w, int revents); |
10 |
}; |
ev_io在触发EV_READ或者是EV_WRITE被调用
1 |
struct ev_timer { |
2 |
ev_tstamp at; |
3 |
ev_tstamp repeat; |
4 |
int active; |
5 |
int pending; |
6 |
int priority; |
7 |
void * data; |
8 |
void (*cb)( struct ev_loop *loop, struct ev_timer *w, int revents); |
9 |
}; |
ev_timer在特定的时间调用,并周期性进行,其基于单调时钟
(PS:单调时钟:此时间来源会严格的线性递增,一般linux会使用系统正常运行时间来表示,也就是从开机开始算起) 触发事件EV_TIMEOUT
1 |
struct ev_periodic { |
2 |
ev_tstamp offset; |
3 |
ev_tstamp interval; |
4 |
ev_tstamp (*reschedule_cb)( struct ev_periodic *w, ev_tstamp now); |
5 |
ev_tstamp at; |
6 |
int active; |
7 |
int pending; |
8 |
int priority; |
9 |
void * data; |
10 |
void (*cb)( struct ev_loop *loop, struct ev_periodic *w, int revents); |
11 |
}; |
ev_periodic在特定的时间调用,可能会在定期间隔反复调用,其基于UTC时间
(PS:UTC:协调时间 也就是从1970年1月1日00:00:00开始记时) 触发事件EV_PERIODIC
1 |
struct ev_signal { |
2 |
int signum; |
3 |
struct ev_watcher_list *next; |
4 |
int active; |
5 |
int pending; |
6 |
int priority; |
7 |
void * data; |
8 |
void (*cb)( struct ev_loop *loop, struct ev_signal *w, int revents); |
9 |
}; |
ev_signal当接收到指定的信号时调用 触发事件EV_SIGNAL
1 |
struct ev_child { |
2 |
int flag; |
3 |
int pid; |
4 |
int rpid; |
5 |
int rstatus; |
6 |
struct ev_watcher_list *next; |
7 |
int active; |
8 |
int pending; |
9 |
int priority; |
10 |
void * data; |
11 |
void (*cb)( struct ev_loop *loop, struct ev_child *w, int revents); |
12 |
}; |
ev_child当接收到SIGCHLD信号并且waitpid表示了给出的pid时调用 触发EV_CHILD事件
其不支持优先级
1 |
struct ev_stat { |
2 |
ev_timer timer; |
3 |
ev_tstamp interval; |
4 |
const char *path; |
5 |
ev_statdata prev; |
6 |
ev_statdata attr; |
7 |
int wd; |
8 |
struct ev_watcher_list *next; |
9 |
int active; |
10 |
int pending; |
11 |
int priority; |
12 |
void * data; |
13 |
void (*cb)( struct ev_loop *loop, struct ev_stat *w, int revents); |
14 |
}; |
ev_stat当每次指定的路径状态数据发生改变时调用 触发EV_STAT
1 |
struct ev_idle { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop *loop, struct ev_idle *w, int revents); |
7 |
}; |
ev_idle当啥事情都不需要做的时候调用,用来保持进程远离阻塞 触发EV_IDLE
1 |
struct ev_prepare { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop *loop, struct ev_prepare *w, int revents); |
7 |
}; |
ev_prepare每次执行mainloop主循环,在主循环之前调用 触发EV_PREPARE;
1 |
struct ev_check { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop *loop, struct ev_check *w, int revents); |
7 |
}; |
ev_check每次执行mainloop主循环,在主循环之后调用 触发EV_CHECK
1 |
struct ev_fork { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop *loop, struct ev_fork *w, int revents); |
7 |
}; |
ev_fok在fork行为被检测到,并且在检测子进程之前调用 触发EV_FORK;
1 |
struct ev_cleanup { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop *loop, struct ev_cheanup *w, int revents); |
7 |
}; |
ev_cleanup在主循被销毁之后调用 触发EV_CLEANUP
1 |
struct ev_embed { |
2 |
struct ev_loop* other; |
3 |
ev_io io; |
4 |
ev_prepare prepare; |
5 |
ev_check check; |
6 |
ev_timer timer; |
7 |
ev_periodic periodic; |
8 |
ev_idle idle; |
9 |
ev_fork fork; |
10 |
ev_cleanup cleanup; |
11 |
}; |
ev_embed用于将一个事件循环嵌套到另一个中,当事件循环处理事件的时候被调用
1 |
struct ev_async { |
2 |
sig_atomic_t volatile sent; |
3 |
int active; |
4 |
int pending; |
5 |
int priority; |
6 |
void * data; |
7 |
void (*cb)( struct ev_loop *loop, struct ev_async *w, int revents); |
8 |
}; |
ev_async当ev_async_send通过watcher调用时调用,触发EV_ASYNC
1 |
union ev_any_watcher { |
2 |
struct ev_watcher w; |
3 |
struct ev_watcher_list wl; |
4 |
struct ev_io io; |
5 |
struct ev_timer timer; |
6 |
struct ev_periodic periodic; |
7 |
struct ev_signal signal ; |
8 |
struct ev_child child; |
9 |
#if EV_STAT_ENABLE |
10 |
struct ev_stat stat; |
11 |
#endif |
12 |
#if EV_IDLE_ENABLE |
13 |
struct ev_idle idle; |
14 |
#endif |
15 |
struct ev_prepare prepare; |
16 |
struct ev_check check; |
17 |
#if EV_FORK_ENABLE |
18 |
struct ev_fork fork; |
19 |
#endif |
20 |
#if EV_CLEANUP_ENABLE |
21 |
struct ev_cleanup cleanup; |
22 |
#endif |
23 |
#if EV_EMBED_ENABLE |
24 |
struct ev_embed embed; |
25 |
#endif |
26 |
#if EV_ASYNC_ENABLE |
27 |
struct ev_async async; |
28 |
#endif |
29 |
}; |
该结构的存在用以强制类似结构的布局
1 |
struct ev_watcher { |
2 |
int active; |
3 |
int pending; |
4 |
int priority; |
5 |
void * data; |
6 |
void (*cb)( struct ev_loop* loop, struct ev_watcher *w, int revent); |
7 |
} |
8 |
9 |
struct ev_watcher_list { |
10 |
struct ev_wather_list *next; |
11 |
int active; |
12 |
int pending; |
13 |
int prioirty; |
14 |
void * data; |
15 |
void (*cb)( struct ev_loop* loop, struct ev_watcher_list *w, int revent); |
16 |
}; |
1 |
static unsigned int ev_linux_version( void ) |
通过使用utsname结构以及uname函数获取linux版本号
1 |
static void ev_printerr( const char *msg) |
输出错误新方法,实现很简单用write直接往STDERR写数据
1 |
void ev_set_syserr_cb( void (*cb)( const char *msg)) |
设置系统错误控制方法回调
1 |
static void ev_syserr( const char *msg) |
系统错误处理函数,首先判断msg是否为空,msg==NULL填充为”(libev) system error”,然后如果系统错误控制回调不为空 也就是通过上面方法设置的,就调用该控制回调 否则的话就格式化输出 并中断程序运行
1 |
static void * ev_realloc_emul( void *ptr, long size) |
作者分装的一个realloc,主要为了屏蔽不同平台的差异,比如 有些系统(如openBSD)不支持realloc(x,0)这种行为,于是作者进行了判定如果是含有__GLIBC__宏 那么就可以之间诶用realloc 否则的话当size为0则进行free操作
1 |
static void *(*alloc)( void *ptr, long size) = ev_realloc_emul; |
定义了一个变量,并赋值,啥变量 一个指向返回值是void* 参数是void*,long的函数指针 不过看着总觉得不爽 习惯于typedef的写法,另一方面也就是说alloc等价与ev_realloc_emul哦
1 |
void ev_set_allocator( void *(*cb)( void * ptr, long size)) |
设置alloc函数的实现,我们在上面的语句看到alloc的默认实现是啥,通过该函数可以改变其实现
1 |
inline_speed void * ev_realloc( void * ptr, long size) |
一个realloc的实现调用的alloc,比之增加错误日志输出 有意思的是这里有一个叫做inline_speed的宏,libev的作者在libev中大量使用了,使人看代码相当不爽的说
1 |
#if EV_FEATURE_CODE |
2 |
#define inline_speed static inline |
3 |
#else |
4 |
#define inline_speed static noinline |
5 |
#endif |
这里又一把宏定义,不过都是见名知义,EV_FEATURE_CODE默认情况是非0,也就是inline_speed默认为static inline
1 |
#define ev_malloc(size) ev_realloc(0,(size)) |
2 |
#define ev_free(ptr)m ev_realloc((ptr),0) |
我们看到ev_malloc以及ev_free其实也是通过ev_realloc实现的
1 |
typedef struct { |
2 |
ev_watcher_list* head; //监听者链表 |
3 |
unsigned char events; //监听的事件 |
4 |
unsigned char reify; //状态位 用来表示具体是EV_ANFD_REIFY还是EV_IOFDSET |
5 |
unsigned char emask; //epoll用来保存内核mask的值 |
6 |
unsigned char unused; //同名字 |
7 |
#if EV_USE_EPOLL |
8 |
unsigned int egen; |
9 |
#endif |
10 |
#if EV_SELECT_ISWINSOCKET || EV_USE_IOCP |
11 |
SOCKET handle |
12 |
#endif |
13 |
#if EV_USE_IOCP |
14 |
OVERLAPPED or,ow; |
15 |
#endif |
16 |
} ANFD; |
文件描述符信息结构
1 |
typedef struct { |
2 |
ev_watcher* w; |
3 |
int events; |
4 |
} ANPENDING; |
指定等待事件的监听者结构
1 |
typedef struct { |
2 |
ev_watcher_list* head; |
3 |
} ANFS; |
每个inotify-id对应的哈希表的每个节点的结构
1 |
typedef struct { |
2 |
ev_tstamp at; |
3 |
ev_watcher_time* w; |
4 |
} ANHE; |
堆结构的节点
1 |
struct ev_loop { |
2 |
ev_tstamp ev_rt_now; |
3 |
} |
1 |
ev_tstamp ev_time( void ) |
获取当前时间如果设置了EV_USE_REALTIME会考虑是否使用clock_gettime纳秒(have_realtiem如果为非负就使用 clock_gettime了) 否则使用gettimeofday 注意这里的时间都是和当前设置的时间是有关系的 也就是说如果我把系统时间修改了 可能得到过去的时间
另外这里用了一个宏expect_true 其原型是__builtin_expect((a) != 0, 1)也就是告诉编译器绝大多数情况下a != 0是满足的 方便编译器进行优化 同理相反的还有expect_false
1 |
inline_size ev_tstamp get_clock( void ) |
这个函数优先是使用CLOCK_MONOTONIC时间 也就是单调时间不会被修改减小 然后达不到要求 则调用ev_time来获取时间 inline_size就是 static inline
1 |
ev_tstamp ev_now( struct ev_loop *loop) |
获取当前时间时间 也就是loop->ev_rt_now
1 |
void ev_sleep(ev_tstamp delay) |
如果可以使用nanosleep则使用nanosleep 如果在window下使用Sleep,否则使用select实现
1 |
inline_size int array_next( int elem, int cur, int cnt) |
用来生成内存对齐大小的实际需要开辟的内存大
1 |
static ninline void * array_realloc( int elem, void *base, int *cur, int cnt) |
开辟或重新非配一定大小的内存块,该方法会调用上面的函数进行内存对齐大小 所以返回后的大小不一定会和想开辟的相等
1 |
array_init_zero(base,count) |
顾名思义初始化为0,通过memset实现
1 |
array_needsize(type,base,cur,cnt,init) |
分配需要大小的内存 就是分配出内存 并初始化为0
1 |
array_free(stem,idx) |