乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Linux內(nèi)核開(kāi)發(fā)之阻塞非阻塞IO----輪詢(xún)操作

       rookie 2012-04-10

      “小王,來(lái)聊聊,今天面試的情況怎么樣,應(yīng)該挺順利的吧..”看著小王平淡的眉頭,我問(wèn)道。

      “唉,別提了,你說(shuō),我的運(yùn)氣咋這差呢,面試前你不是給我講了有關(guān)阻塞的問(wèn)題嗎,我見(jiàn)了面試官是吧,還跟他好好的用今天排隊(duì)的例子說(shuō)了有關(guān)阻塞的問(wèn)題,但是..”小王哀聲嘆氣地說(shuō)到。

      “別但是了,怎么啦..”

      “可問(wèn)題是面試官壓根就沒(méi)打算問(wèn)我有關(guān)阻塞的問(wèn)題及解決方案,但是問(wèn)我說(shuō):這樣吧,你給我說(shuō)說(shuō)在Linux設(shè)備驅(qū)動(dòng)中有關(guān)非阻塞的方法,我這一聽(tīng),傻眼了不是,你剛好給我講的是阻塞的東西,可人家偏要問(wèn)我有關(guān)非阻塞的問(wèn)題,我..”小王欲哭無(wú)淚啊..

      “怎么這樣呢,算了,機(jī)會(huì)多的是,亡羊補(bǔ)牢,我現(xiàn)在就給你說(shuō)說(shuō)有關(guān)非阻塞的問(wèn)題----Linux設(shè)備驅(qū)動(dòng)程序之阻塞非阻塞IO----輪詢(xún)操作”。

      通過(guò)上一節(jié),我們都明白了,有關(guān)阻塞的相關(guān)知識(shí)(不知道,那我沒(méi)轍了,飯送到嘴,你還挑食,難不成我拿把起子把嘴撬開(kāi)不成,自己看上一篇吧),現(xiàn)在就來(lái)聊聊對(duì)

      立面非阻塞。

      使用非阻塞I/O的應(yīng)用程序通常會(huì)使用select()和poll()系統(tǒng)調(diào)用查詢(xún)是否可對(duì)設(shè)備進(jìn)行無(wú)阻塞的訪(fǎng)問(wèn),這兩個(gè)系統(tǒng)調(diào)用最終又會(huì)引發(fā)設(shè)備驅(qū)動(dòng)中的poll()函數(shù)被執(zhí)行

      ,所以我們的問(wèn)題就集中到了如何編寫(xiě)設(shè)備驅(qū)動(dòng)中的poll()函數(shù)就可以了。二話(huà)不說(shuō),先來(lái)看看設(shè)備驅(qū)動(dòng)中的poll()函數(shù)原型:

      unsigned int (*poll)(struct file *filp, struct poll_table *wait);

      這個(gè)函數(shù)要進(jìn)行下面兩項(xiàng)工作。首先,對(duì)可能引起設(shè)備文件狀態(tài)變化的等待隊(duì)列調(diào)用poll_wait(),將對(duì)應(yīng)的等待隊(duì)列頭添加到poll_table.然后,返回表示是否能對(duì)設(shè)備進(jìn)行無(wú)阻塞讀寫(xiě)訪(fǎng)問(wèn)的掩碼。在上面提到了一個(gè)poll_wait()函數(shù),它的原型:

      void poll_wait(struct file *filp, wait_queue_head_t *queue, poll_table *wait);

      它的作用就是把當(dāng)前進(jìn)程添加到wait參數(shù)指定的等待列表(poll_table)中。需要注意的是這個(gè)函數(shù)是不會(huì)引起阻塞的,呵呵,誰(shuí)給它取得個(gè)名字帶wait的,給咱們添這么多麻煩。

      “等等,你先停停,你是高手,我可是菜鳥(niǎo)呢,你先給我說(shuō)說(shuō)poll_table結(jié)構(gòu)吧,心里總是想它是什么..”小王打斷我道。

      行行,說(shuō)起這個(gè)結(jié)構(gòu),我也是費(fèi)了一番周折,它定義在“include/linux/poll.h, line 38“,具體如下:

      typedef struct poll_table_struct {
          poll_queue_proc qproc;
          unsigned long key;
      } poll_table;   看看,其實(shí)沒(méi)什么吧,不要想的太復(fù)雜了
      經(jīng)過(guò)以上驅(qū)動(dòng)程序的poll()函數(shù)應(yīng)該返回設(shè)備資源的可獲取狀態(tài),即POLLIN,POLLOUT,POLLPRI,POLLERR,POLLNVAL等宏的位"或"結(jié)果.每個(gè)宏的含義都表示設(shè)備的一種狀態(tài),如:
      常量 說(shuō)明
      POLLIN 普通或優(yōu)先級(jí)帶數(shù)據(jù)可讀
      POLLRDNORM 普通數(shù)據(jù)可讀
      POLLRDBAND 優(yōu)先級(jí)帶數(shù)據(jù)可讀
      POLLPRI 高優(yōu)先級(jí)數(shù)據(jù)可讀
      POLLOUT 普通數(shù)據(jù)可寫(xiě)
      POLLWRNORM 普通數(shù)據(jù)可寫(xiě)
      POLLWRBAND 優(yōu)先級(jí)帶數(shù)據(jù)可寫(xiě)
      POLLERR 發(fā)生錯(cuò)誤
      POLLHUP 發(fā)生掛起
      POLLNVAL 描述字不是一個(gè)打開(kāi)的文件
      "小王,你明白了沒(méi).."看著小王眨巴眨巴的小眼睛,我說(shuō)。
      "呵呵,你干脆給我來(lái)個(gè)典型模板,行不?"小王苛求道。
      行,沒(méi)問(wèn)題,你現(xiàn)在特殊時(shí)期,我是有求必應(yīng)。請(qǐng)看下邊:
      static unsigned int XXX_poll(struct file *filp, poll_table *wait)
      {
          unsigned int mask = 0;
              struct XXX_dev *dev = filp->private_data;     //獲得設(shè)備結(jié)構(gòu)指針
          ...
          poll_wait(filp, &dev->r_wait, wait);    //加讀等待對(duì)列頭
          poll_wait(filp ,&dev->w_wait, wait);    //加寫(xiě)等待隊(duì)列頭
          
          if(...)//可讀
          {
                mask |= POLLIN | POLLRDNORM;    //標(biāo)識(shí)數(shù)據(jù)可獲得if(...)//可寫(xiě)
          {
                mask |= POLLOUT | POLLRDNORM;    //標(biāo)識(shí)數(shù)據(jù)可寫(xiě)入
           }
          ..
          return mask;
      }

      "小王,這次看明白了吧,要是還看不明白,我就再給你講講用戶(hù)空間的輪詢(xún)編程,兩個(gè)結(jié)合起來(lái)也許好懂點(diǎn),行不"。我補(bǔ)充道。

      在用戶(hù)程序中,select()和poll()本質(zhì)上是一樣的, 不同只是引入的方式不同,前者是在BSD UNIX中引入的,后者是在System V中引入的。用的比較廣泛的是select

      系統(tǒng)調(diào)用。原型如下:

      int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptionfds, struct timeval *timeout);

      其中readfs,writefds,exceptfds分別是select()監(jiān)視的讀,寫(xiě)和異常處理的文件描述符集合,numfds的值是需要檢查的號(hào)碼最高的文件描述符加1,timeout則是一個(gè)時(shí)間上限值,超過(guò)該值后,即使仍沒(méi)有描述符準(zhǔn)備好也會(huì)返回。

      struct timeval
      {
          int tv_sec;    //秒
          int tv_usec;   //微秒
      }
      涉及到文件描述符集合的操作主要有以下幾種:
      1)清除一個(gè)文件描述符集   FD_ZERO(fd_set *set);
      2)將一個(gè)文件描述符加入文件描述符集中    FD_SET(int fd,fd_set *set);
      3)將一個(gè)文件描述符從文件描述符集中清除  FD_CLR(int fd,fd_set *set);
      4)判斷文件描述符是否被置位    FD_ISSET(int fd,fd_set *set);

      最后我們利用上面的文件描述符集的相關(guān)來(lái)寫(xiě)個(gè)驗(yàn)證添加了設(shè)備輪詢(xún)的驅(qū)動(dòng),把上邊兩塊聯(lián)系起來(lái):

      必要的頭文件
       
      #define FIFO_CLEAR 0x1
      #define BUFFER_LEN 20
      main()
      {
        int fd, num;
        char rd_ch[BUFFER_LEN];
        fd_set rfds,wfds;
        /*以非阻塞方式打開(kāi)/dev/polltest設(shè)備文件*/
        fd = open("/dev/polltest", O_RDONLY | O_NONBLOCK);
        if (fd !=  - 1)
        { /*FIFO清0*/
          if (ioctl(fd, FIFO_CLEAR, 0) < 0)
          {
            printf("ioctl command failed\n");
          }
          while (1)
          {
            FD_ZERO(&rfds);
            FD_ZERO(&wfds);
            FD_SET(fd, &rfds);
            FD_SET(fd, &wfds);
            select(fd + 1, &rfds, &wfds, NULL, NULL);
            /*數(shù)據(jù)可獲得*/
            if (FD_ISSET(fd, &rfds))
            {
            	printf("Device can be read now\n");
            }
            /*數(shù)據(jù)可寫(xiě)入*/
            if (FD_ISSET(fd, &wfds))
            {
            	printf("Device can be written now\n");
            }      
          }
        }
        else
        {
          printf("Device open failure now\n");
        }
      } 

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多