poll函数源码详细分析 http://blog.csdn.net/lmh12506/article/details/7556297

废话不多,相信看篇文章的都用pollepoll,先来看poll统调用的源

  1. asmlinkage long sys_poll(struct pollfd __user * ufds, unsigned int nfds, long timeout)  
  2. {  
  3. struct poll_wqueues table;  
  4. int fdcount, err;  
  5. unsigned int i;  
  6. struct poll_list *head;  
  7. struct poll_list *walk;  
  8.   
  9. /* Do a sanity check on nfds ... */  
  10. if (nfds > current->files->max_fdset && nfds > OPEN_MAX) //(1)  
  11. return -EINVAL;  
  12.   
  13. if (timeout) { //(2)  
  14. /* Careful about overflow in the intermediate values */  
  15. if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ)  
  16. timeout = (unsigned long)(timeout*HZ+999)/1000+1;  
  17. else /* Negative or overflow */  
  18. timeout = MAX_SCHEDULE_TIMEOUT;  
  19. }  
  20.   
  21. poll_initwait(&table); //(3)  
  22.   
  23. head = NULL;  
  24. walk = NULL;  
  25. i = nfds;  
  26. err = -ENOMEM;  
  27. while(i!=0) { //(4)  
  28. struct poll_list *pp;  
  29. pp = kmalloc(sizeof(struct poll_list)+  
  30. sizeof(struct pollfd)*  
  31. (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i),  
  32. GFP_KERNEL);  
  33. if(pp==NULL)  
  34. goto out_fds;  
  35. pp->next=NULL;  
  36. pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i);  
  37. if (head == NULL)  
  38. head = pp;  
  39. else  
  40. walk->next = pp;  
  41.   
  42. walk = pp;  
  43. if (copy_from_user(pp->entries, ufds + nfds-i,   
  44. sizeof(struct pollfd)*pp->len)) {  
  45. err = -EFAULT;  
  46. goto out_fds;  
  47. }  
  48. i -= pp->len;  
  49. }  
  50. fdcount = do_poll(nfds, head, &table, timeout);  
  51. (5)  
  52.   
  53. /* OK, now copy the revents fields back to user space. */  
  54. walk = head;  
  55. err = -EFAULT;  
  56. while(walk != NULL) {  
  57. (6)  
  58. struct pollfd *fds = walk->entries;  
  59. int j;  
  60.   
  61. for (j=0; j < walk->len; j++, ufds++) {  
  62. if(__put_user(fds[j].revents, &ufds->revents))  
  63. goto out_fds;  
  64. }  
  65. walk = walk->next;  
  66. }  
  67. err = fdcount;  
  68. if (!fdcount && signal_pending(current))  
  69. err = -EINTR;  
  70. out_fds:  
  71. walk = head;  
  72. while(walk!=NULL) {  
  73. struct poll_list *pp = walk->next;  
  74. kfree(walk);  
  75. walk = pp;  
  76. }  
  77. poll_freewait(&table);  
  78. return err;  
  79. }  


 

(1)里是检查文件描述符集的最大个数是否符合要求。

(2)检查timeout行一些理。

(3)里的函数初始化poll_wqueuestable

1. void poll_initwait(structpoll_wqueues *pwq)

2. {

3. init_poll_funcptr(&pwq->pt, __pollwait);

4. pwq->error = 0;

5. pwq->table = NULL;

6. }

可以看到,函数里面初始化了poll_wqueues构体,我接着看他有什么内涵。

1. struct poll_wqueues {

2. poll_table pt;

3. struct poll_table_page * table;

4. int error;

5. };

每一个poll_wqueue对应每一个poll用。pt外的接口。

接着看poll_table:

1. typedef struct poll_table_struct {

2. poll_queue_proc qproc;

3. } poll_table;

可以看到,初始化的候把__pollwait函数赋给poll_table里面的poll理函数(字面翻)。个函数在poll_wait函数里面用,在驱动里面的poll函数就会用到poll_wait函数。__pollwait是干什么的呢?里引用一下人的

里有人会什么要一个数目0的数,那是方便找到接着的下一个构体。

回到sys_poll接着往下看。

(4)个循的作用就是把要听的文件描述符从用户态拷到内核中。注意到因为这里建立了一个表,如果要听的描述符很多,超,需要分配多个,可能会影响性能的。

(5)里有个do_poll函数。看源

  1. static int do_poll(unsigned int nfds, struct poll_list *list,  
  2. struct poll_wqueues *wait, long timeout)  
  3. {  
  4. int count = 0;  
  5. poll_table* pt = &wait->pt;  
  6.   
  7. if (!timeout)  
  8. pt = NULL;  
  9.   
  10. for (;;) {  
  11. struct poll_list *walk;  
  12. set_current_state(TASK_INTERRUPTIBLE);  
  13. walk = list;  
  14. while(walk != NULL) {  
  15. do_pollfd( walk->len, walk->entries, &pt, &count);  
  16. walk = walk->next;  
  17. }  
  18. pt = NULL;  
  19. if (count || !timeout || signal_pending(current))  
  20. break;  
  21. count = wait->error;  
  22. if (count)  
  23. break;  
  24. timeout = schedule_timeout(timeout);  
  25. }  
  26. __set_current_state(TASK_RUNNING);  
  27. return count;  
  28. }  


 

do_pollfd就是针对每个传进来的fd用它各自对应poll函数,化一下程,如下:
struct file* file = fget(fd);
file->f_op->poll
file, &(table->pt));
如果fd对应的是某个socketdo_pollfd用的就是网络设备驱动实现poll;如果fd对应的是某个ext3
件系上的一个打开文件,那do_pollfd用的就是ext3文件系统驱动实现poll一句file-
>f_op->poll
设备驱动程序实现的,那设备驱动程序的poll实现通常又是什么子呢?其设备驱动
程序的实现是:poll_wait,即以设备自己的等待参数(通设备都有自己的等待列,不
然一个不支持异步操作的设备人很郁structpoll_table的回函数。

 

(6)就是把果拷回用户态

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值