epoll_create函数实现源码分析 http://blog.youkuaiyun.com/lmh12506/article/details/7556188

本文详细剖析了epoll_create函数的内部实现原理,包括文件描述符的创建过程、eventpoll结构体的初始化等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/lmh12506/article/details/7556188

  2370人阅读  评论(0)  收藏  举报

昨晚分析了poll,通阅读可以发现poll操作有很多可以化的地方。epolleventpoll称,他的效率是非常高的,我今天来看看他的实现。他的实现FS/Eventpoll.c,代1500多行,呵呵,怕了吧。

大家都知道,epoll有三个系统调用,C封装成以下三个:

1.  int epoll_create(int size);

2.  int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

3.  int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);

epoll的源码这么多,我就干脆跟着他三个走着瞧。今天先搞定第一个---epoll_create

第一个是

  1. /* 
  2. * It opens an eventpoll file descriptor by suggesting a storage of "size" 
  3. * file descriptors. The size parameter is just an hint about how to size 
  4. * data structures. It won't prevent the user to store more than "size" 
  5. * file descriptors inside the epoll interface. It is the kernel part of 
  6. * the userspace epoll_create(2). 
  7. */  
  8. asmlinkage long sys_epoll_create(int size)  
  9. {  
  10. int error, fd;  
  11. struct inode *inode;  
  12. struct file *file;  
  13.   
  14. DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",  
  15. current, size));  
  16.   
  17. /* Sanity check on the size parameter */  
  18. error = -EINVAL;  
  19. if (size <= 0)  
  20. goto eexit_1;  
  21.   
  22. /* 
  23. * Creates all the items needed to setup an eventpoll file. That is, 
  24. * a file structure, and inode and a free file descriptor. 
  25. */  
  26. error = ep_getfd(&fd, &inode, &file); //(1)  
  27. if (error)  
  28. goto eexit_1;  
  29.   
  30. /* Setup the file internal data structure ( "struct eventpoll" ) */  
  31. error = ep_file_init(file); //(2)  
  32. if (error)  
  33. goto eexit_2;  
  34.   
  35.   
  36. DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",  
  37. current, size, fd));  
  38.   
  39. return fd;  
  40.   
  41. eexit_2:  
  42. sys_close(fd);  
  43. eexit_1:  
  44. DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",  
  45. current, size, error));  
  46. return error;  
  47. }  



(1)里用到了一个ep_getfd函数,从注知道,个函数建立eventpoll相关的file,当然,一个file要包括文件描述符、inode有文件象,也是我们传的三个参数。废话,看源


  1. /* 
  2. * Creates the file descriptor to be used by the epoll interface. 
  3. */  
  4. static int ep_getfd(int *efd, struct inode **einode, struct file **efile)  
  5. {  
  6. struct qstr this;  
  7. char name[32];  
  8. struct dentry *dentry;  
  9. struct inode *inode;  
  10. struct file *file;  
  11. int error, fd;  
  12.   
  13. /* Get an ready to use file */  
  14. error = -ENFILE;  
  15. file = get_empty_filp();  
  16. if (!file)  
  17. goto eexit_1;  
  18.   
  19. /* Allocates an inode from the eventpoll file system */  
  20. inode = ep_eventpoll_inode();  
  21. error = PTR_ERR(inode);  
  22. if (IS_ERR(inode))  
  23. goto eexit_2;  
  24.   
  25. /* Allocates a free descriptor to plug the file onto */  
  26. error = get_unused_fd();  
  27. if (error < 0)  
  28. goto eexit_3;  
  29. fd = error;  
  30.   
  31. /* 
  32. * Link the inode to a directory entry by creating a unique name 
  33. * using the inode number. 
  34. */  
  35. error = -ENOMEM;  
  36. sprintf(name, "[%lu]", inode->i_ino);  
  37. this.name = name;  
  38. this.len = strlen(name);  
  39. this.hash = inode->i_ino;  
  40. dentry = d_alloc(eventpoll_mnt->mnt_sb->s_root, &this);  
  41. if (!dentry)  
  42. goto eexit_4;  
  43. dentry->d_op = &eventpollfs_dentry_operations;  
  44. d_add(dentry, inode);  
  45. file->f_vfsmnt = mntget(eventpoll_mnt);  
  46. file->f_dentry = dentry;  
  47. file->f_mapping = inode->i_mapping;  
  48.   
  49. file->f_pos = 0;  
  50. file->f_flags = O_RDONLY;  
  51. file->f_op = &eventpoll_fops;  
  52. file->f_mode = FMODE_READ;  
  53. file->f_version = 0;  
  54. file->private_data = NULL;  
  55.   
  56. /* Install the new setup file into the allocated fd. */  
  57. fd_install(fd, file);  
  58.   
  59. *efd = fd;  
  60. *einode = inode;  
  61. *efile = file;  
  62. return 0;  
  63.   
  64. eexit_4:  
  65. put_unused_fd(fd);  
  66. eexit_3:  
  67. iput(inode);  
  68. eexit_2:  
  69. put_filp(file);  
  70. eexit_1:  
  71. return error;  
  72. }  


个函数的注都比全,简单提一下,况且因涉及到的函数太多,要深究起来涉及的知太多,也不可能逐一去列代。不过这个函数个人得比较经典,函数就是建一个文件的流程。

首先,我得拿到一个file构体,通内核分配;然后我要拿到inodeep_eventpoll_inode()就可以了;接着是get_unused_fd()拿到文件描述符;接着d_alloc()函数拿到一个dentryd_add(dentry, inode)函数把dentry建立hash里面并且inode;后面是继续填充文件filefd_install(fd, file)程注册文件,并通过这样的方式把文件描述符和文件象关起来。

(2)在跟踪ep_file_init函数之前,我先来看一下eventpoll构体:

  1. /* 
  2. * This structure is stored inside the "private_data" member of the file 
  3. * structure and rapresent the main data sructure for the eventpoll 
  4. * interface. 
  5. */  
  6. struct eventpoll {  
  7. /* Protect the this structure access */  
  8. rwlock_t lock;  
  9.   
  10. /* 
  11. * This semaphore is used to ensure that files are not removed 
  12. * while epoll is using them. This is read-held during the event 
  13. * collection loop and it is write-held during the file cleanup 
  14. * path, the epoll file exit code and the ctl operations. 
  15. */  
  16. struct rw_semaphore sem;  
  17.   
  18. /* Wait queue used by sys_epoll_wait() */  
  19. wait_queue_head_t wq;  
  20.   
  21. /* Wait queue used by file->poll() */  
  22. wait_queue_head_t poll_wait;  
  23.   
  24. /* List of ready file descriptors */  
  25. struct list_head rdllist;  
  26.   
  27. /* RB-Tree root used to store monitored fd structs */  
  28. struct rb_root rbr;  
  29. };  


也是相当清楚。eventpoll可以看得出来,是epoll的核心,它将会存你想要听的文件描述符,也是什么epoll高效之所在。

好,我回到sys_epoll_create函数,开始跟踪ep_file_init函数:


  1. static int ep_file_init(struct file *file)  
  2. {  
  3. struct eventpoll *ep;  
  4.   
  5. if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL)))  
  6. return -ENOMEM;  
  7.   
  8. memset(ep, 0, sizeof(*ep));  
  9. rwlock_init(&ep->lock);  
  10. init_rwsem(&ep->sem);  
  11. init_waitqueue_head(&ep->wq);  
  12. init_waitqueue_head(&ep->poll_wait);  
  13. INIT_LIST_HEAD(&ep->rdllist);  
  14. ep->rbr = RB_ROOT;  
  15.   
  16. file->private_data = ep;  
  17.   
  18. DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n",  
  19. current, ep));  
  20. return 0;  
  21. }  



也就是eventpoll构体的初始化。

sys_epoll_create函数大概就这样了,明天接着看sys_epoll_ctl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值