[置顶] epoll 事件处理的技术内核分析

epoll高效机制其实就是内核回调,我们知道linux把socket也是当成file处理的,只是底层驱动不一样。

先来看看内核文件结构:

struct file_operations {
       struct module *owner;
       loff_t (*llseek) (struct file *, loff_t, int);
       ssize_t (*read) (struct file *, char *, size_t, loff_t *);
       ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
       int (*readdir) (struct file *, void *, filldir_t);
       unsigned int (*poll) (struct file *, struct poll_table_struct *);
       int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
       ..


可以看到结构体中有一个 poll 函数,这部分由驱动实现,其核心函数是:
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
	if (p && wait_address)
		p->qproc(filp, wait_address, p);
}

polltable 其实不是表,是一个结构体:
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
	poll_queue_proc qproc;
} poll_table;


包含一个回调函数,当驱动有事件的时候,会调用这个回调。
 
 
由此可以将epoll 内核实现分成两层:业务层和驱动层。
业务层实现epoll的各个函数,并将新增文件加到驱动层中,驱动层实现有事件时通知业务层。
业务层有两个函数与驱动层交互:
设置队列函数A,异步回调函数B
poll_table pt;
pt.qproc = A;


当新增一个文件 sockt1 时,会调用
tfile->f_op->poll(socket1, &pt );


A立即调用,A要负责创建一个队列元素,该队列元素包含异步回调函数B,并将该元素插入到驱动层队列中。
当驱动层有事件时,会回调B,B再将对应socket1 插入到通知列表中,由epoll_wait 取走。
 
 
这样,epoll 的内核实现就清晰了,希望对大家有所帮助。
 
 

你可能感兴趣的:(源码,分析,epoll,内核,事件处理)