新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > Linux內核開發之異步通知與異步I/O(二)

        Linux內核開發之異步通知與異步I/O(二)

        作者: 時間:2016-12-09 來源:網絡 收藏

          “曾經有一份真摯的愛情擺在面前,我卻不懂珍惜;曾經有一個承諾,我卻倍感珍惜,今天一定要好好講講..”

        本文引用地址:http://www.104case.com/article/201612/341380.htm

          講講啥,講講上節說的那個異步通知的例子唄,大家喜歡看代碼,咋們就先上代碼:

          struct globalfifo_dev

          {

          struct cdev cdev; /*cdev結構體*/

          unsigned int current_len; /*fifo有效數據長度*/

          unsigned char mem[GLOBALFIFO_SIZE]; /*全局內存*/

          struct semaphore sem; /*并發控制用的信號量*/

          wait_queue_head_t r_wait; /*阻塞讀用的等待隊列頭*/

          wait_queue_head_t w_wait; /*阻塞寫用的等待隊列頭*/

          struct fasync_struct *async_queue; /* 異步結構體指針,用于讀 */

          };

          /*文件釋放函數*/

          int globalfifo_release(struct inode *inode, struct file *filp)

          {

          /* 將文件從異步通知列表中刪除 */

          globalmem_fasync( - 1, filp, 0);

          return 0;

          }

          static int globalfifo_fasync(int fd, struct file *filp, int mode)

          {

          struct globalfifo_dev *dev = filp->private_data;

          return fasync_helper(fd, filp, mode, &dev->async_queue);

          }

          /*globalfifo寫操作*/

          static ssize_t globalfifo_write(struct file *filp, const char __user *buf,

          size_t count, loff_t *ppos)

          {

          struct globalfifo_dev *dev = filp->private_data; //獲得設備結構體指針

          int ret;

          DECLARE_WAITQUEUE(wait, current); //定義等待隊列

          down(&dev->sem); //獲取信號量

          add_wait_queue(&dev->w_wait, &wait); //進入寫等待隊列頭

          /* 等待FIFO非滿 */

          if (dev->current_len == GLOBALFIFO_SIZE)

          {

          if (filp->f_flags &O_NONBLOCK)

          //如果是非阻塞訪問

          {

          ret = - EAGAIN;

          goto out;

          }

          __set_current_state(TASK_INTERRUPTIBLE); //改變進程狀態為睡眠

          up(&dev->sem);

          schedule(); //調度其他進程執行

          if (signal_pending(current))

          //如果是因為信號喚醒

          {

          ret = - ERESTARTSYS;

          goto out2;

          }

          down(&dev->sem); //獲得信號量

          }

          /*從用戶空間拷貝到內核空間*/

          if (count > GLOBALFIFO_SIZE - dev->current_len)

          count = GLOBALFIFO_SIZE - dev->current_len;

          if (copy_from_user(dev->mem + dev->current_len, buf, count))

          {

          ret = - EFAULT;

          goto out;

          }

          else

          {

          dev->current_len += count;

          printk(KERN_INFO "written %d bytes(s),current_len:%dn", count, dev

          ->current_len);

          wake_up_interruptible(&dev->r_wait); //喚醒讀等待隊列

          /* 產生異步讀信號 */

          if (dev->async_queue)

          kill_fasync(&dev->async_queue, SIGIO, POLL_IN);

          ret = count;

          }

          out: up(&dev->sem); //釋放信號量

          out2:remove_wait_queue(&dev->w_wait, &wait); //從附屬的等待隊列頭移除

          set_current_state(TASK_RUNNING);

          return ret;

          }

          下面再給出測試程序:

          #include ...

          //接收到異步讀信號的動作

          void input_handler(int signum)

          {

          printf("Receive a signal from globalfifo,signalnum:%dn",signum);

          }

          int main()

          {

          int fd, oflags;

          fd = open("/dev/globalfifo", O_RDWR, S_IRUSR | S_IWUSR);

          if (fd != - 1)

          {

          //啟動信號驅動機制

          signal(SIGIO, input_handler); //讓input_handler()處理SIGIO信號

          fcntl(fd, F_SETOWN, getpid());

          oflags = fcntl(fd, F_GETFL);

          fcntl(fd, F_SETFL, oflags | FASYNC);

          while(1)

          {

          sleep(100);

          }

          }

          else

          {

          printf("device open failuren");

          }

          }

          當我們加載完驅動并創建完設備節點后,運行上述程序,每當通過echo向/dev/globalfilfo寫入新的數據后,input_handler將會被調用。如下所示:

          echo 0>/dev/globalfifo

          receive a signal from globalfifo ,signalnum:29

          echo 0>/dev/globalfifo

          receive a signal from globalfifo ,signalnum:29

          echo 0>/dev/globalfifo

          receive a signal from globalfifo ,signalnum:29

          通過上邊實際的例子,小王,明白了吧,我的承諾也兌現了,下次咱們可要開始更高級的東西了..



        關鍵詞: Linux 異步I/O

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 汾西县| 杭锦后旗| 漯河市| 汉中市| 汾阳市| 工布江达县| 泉州市| 磐安县| 加查县| 磴口县| 益阳市| 吴川市| 罗平县| 台北市| 芮城县| 克什克腾旗| 苍梧县| 澄城县| 安宁市| 公安县| 庆元县| 安福县| 桐庐县| 晋州市| 汉沽区| 保亭| 渝北区| 城口县| 林口县| 普兰店市| 安国市| 昭觉县| 砀山县| 渭南市| 靖西县| 临夏县| 临城县| 鹿邑县| 惠水县| 阿坝县| 遵化市|