POLL機制分析(韋東山的視頻總結及針對linux-2.6.30.4)

此爲部分內核代碼。

應用程序的poll   ->  sys_poll  ->  do_sys_poll   ->   (poll_initwait,和do_poll)

應用程序的部分代碼:

int main(int argc,char **argv){

        int fd;
        int val=1;
        unsigned char key_val;
        int ret;
        struct pollfd fds[1];//在poll.h中定義
        fd=open("/dev/buttons",O_RDWR);
        if(fd<0)
                printf("can't open!\n");
        fds[0].fd=fd;
        fds[0].events = POLLIN;      //POLLIN 不阻塞地可讀除高優先級外的數據

        while(1){

/* int poll (struct pollfd fdarry[ ],nfds_t nfds,int timeout); nfds是數組元素數 ,timeout 等待的毫秒數*/

            ret = poll(fds,1,5000);     
            if(ret == 0) {
                   printf("time out\n");
             }
           else{
                  read(fd,&key_val,1);
                  printf("key_val = 0x%x\n",key_val);//驅動程序中使用的是十六進制,這裏%x輸出
           }
      }
      return 0;

}

驅動程序裏的poll函數:

static unsigned  forth_drv_poll(struct file *file, poll_table *wait)
{
unsigned int mask=0;
poll_wait(file ,&button_waitq,wait); //不會休眠,掛載到隊列

if(ev_press)       //ev_press =1說明有中斷產生,mask返回非零值,

mask |= POLLIN ;  //不阻塞地可讀除高優先級外的數據
return mask;
}


內核框架:

出現兩次函數的,下面的是調用;


do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,struct timespec *end_time)

{

  /*
  * Structures and helpers for sys_poll/sys_poll
  */

struct poll_wqueues table;
struct poll_wqueues *pwd=&table;

int  fdcount;

  1. poll_initwait(pwq);//初始化;

/*把poll_initwait(pwq)展開

 *poll_initwait(pwq)

 *{
*pwq->polling_task = current;
*pwq->error = 0;
*pwq->table = NULL;

*pwq->inline_index = 0;

  * init_poll_funcptr(&pwq->pt, __pollwait);

 *init_poll_funcptr(poll_table *pt, __pollwait){

 *   pt->qproc = __pollwait;

 *}

 *}

 
 *結果爲table.pt.gbroc=_pollwait
 *   table.error = 0;
 *        table.table = NULL;
 *   polling_task = current;

 *}

  1. fdcount = do_poll(nfds, head, &table, end_time);
/* do_poll(nfds, head, &table, end_time);展開

 *do_poll(nfds, head, &table, end_time)

 *{
 *    for (;;) {

 *         struct poll_list *walk;

 *    poll_table* pt = &table->pt;

 *         for (walk = head; walk != NULL; walk = walk->next) {

* struct pollfd * pfd, * pfd_end;
* pfd = walk->entries;
* pfd_end = pfd + walk->len;

 *         for (; pfd != pfd_end; pfd++) {

 *        if (do_pollfd(pfd, pt)) { 

/*

 *   do_pollfd(pfd, pt)展開,

 *  mask = file->f_op->poll(file,&table->pt);調用驅動poll函數,

* pfd->revents = mask;       

* return mask;

      *     把驅動程序的poll函數展開:   

* forth_drv_poll(file,&table->pt ){

* poll_wait(file ,&button_waitq,&table->pt); 

                  *}                     

  *poll_wait(file ,&button_waitq,&table->pt);展開

  *           &table->ptwait->qproc(file,&button_waitq ,&table->pt);   

  *由 上面初始化時 : table.pt.gbroc=_pollwait 

  *相當於_pollwait(file,&button_waitq , &table->pt);   //掛載到隊列,

 */

            count++;          //如果驅動程序poll返回非零,count自加                   

                    pt = NULL;
 *}
 *}

 *}

 *}

 *if (count || timed_out)
 *break;
 *//不滿足,休眠
 *if (!poll_schedule_timeout(wait, TASK_INTERRUPTIBLE, to, slack))
 *   timed_out = 1;

 *}

}






發佈了36 篇原創文章 · 獲贊 7 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章