epoll源码分析---1

当系统启动时,epoll进行初始化:

  1. static int __init eventpoll_init(void)
  2. {
  3.     mutex_init(&pmutex);
  4.     ep_poll_safewake_init(&psw);
  5.     epi_cache = kmem_cache_create(“eventpoll_epi”,sizeof(struct epitem),
  6.             0,SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|
  7.             SLAB_PANIC,NULL);
  8.     pwq_cache = kmem_cache_create(“eventpoll_pwq”,sizeof(struct
  9.              eppoll_entry),0,EPI_SLAB_DEBUG|SLAB_PANIC,NULL);
  10.     
  11.     return 0;
  12. }

上面的代码实现一些数据结构的初始化,通过fs/eventpoll.c中的注释可以看出,有三种类型的锁机制使用场景:

1.epmutex(mutex):用户关闭文件描述符,但是没有调用EPOLL_CTL_DEL

2.ep->mtx(mutex):用户态与内核态的转换可能会睡眠

3.ep->lock(spinlock):内核态与具体设备中断过程中的转换,poll回调

接下来就是使用slab分配器动态分配内存,第一个结构为当系统中添加一个fd时,就创建一epitem结构体,内核管理的基本数据结构:

  1. struct epitem
  2. {
  3.     struct rb_node rbn;//用于主结构管理的红黑树
  4.     struct list_head rdllink;//事件就绪队列
  5.     struct epitem *next;//用于主结构体中的链表
  6.     struct epoll_filefd ffd;//每个fd生成的一个结构
  7.     int nwait;//
  8.     struct list_head pwqlist;//poll等待队列
  9.     struct eventpoll *ep;//该项属于哪个主结构体
  10.     struct list_head fllink;//链接fd对应的file链表
  11.     struct epoll_event event;//注册的感兴趣的事件,也就是用户空间的epoll_event
  12.     }

而每个epoll fd对应的主要数据结构为:

  1. struct eventpoll {
  2.     spin_lock_t lock;//对本数据结构的访问
  3.     struct mutex mtx;//防止使用时被删除
  4.     wait_queue_head_t wq;//sys_epoll_wait() 使用的等待队列
  5.     wait_queue_head_t poll_wait;//file->poll()使用的等待队列
  6.     struct list_head rdllist;//事件满足条件的链表
  7.     struct rb_root rbr;//用于管理所有fd的红黑树
  8.     struct epitem *ovflist;//将事件到达的fd进行链接起来发送至用户空间
  9. }

该结构主要在epoll_create时进行创建:

  1. //原来使用的是hash表,所以有size,现在改为红黑树,故不使用.
  2. long sys_epoll_create(int size)
  3. {
  4.     int error,fd = -1;
  5.     struct eventpoll *ep;
  6.     struct inode *inode;
  7.     struct file *file;
  8.     
  9.     ….
  10.     error = -EINVAL;
  11.     //分配空间
  12.     if(size <= 0 || (error = ep_alloc(&ep)!=0))
  13.         goto errror_return;
  14.     //创建一个struct file结构,由于没有任何文件系统,为匿名文件,
  15.         并将主结构体放入file->private项中进行保存
  16.     error = anon_inode_getfd(&fd,&inode,&file,[eventpoll],
  17.             &eventpoll_fops,ep);
  18.     if(error)
  19.         goto error_free;
  20.     return fd;
  21.     ...
  22. }

上面注册的操作eventpoll_fops定义如下:

  1. static const struct file_operations eventpoll_fops = {
  2.     .release     =     ep_eventpoll_release;
  3.     .poll        =    ep_eventpoll_poll,
  4. }

这样说来,内核中维护了一棵红黑树,大致的结构如下:

epoll源码分析---1_第1张图片

你可能感兴趣的:(epoll源码分析---1)