色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux內(nèi)核開發(fā)之異步通知與異步I/O(二)

          Linux內(nèi)核開發(fā)之異步通知與異步I/O(二)

          作者: 時(shí)間:2016-12-09 來源:網(wǎng)絡(luò) 收藏

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

          本文引用地址:http://cafeforensic.com/article/201612/341380.htm

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

            struct globalfifo_dev

            {

            struct cdev cdev; /*cdev結(jié)構(gòu)體*/

            unsigned int current_len; /*fifo有效數(shù)據(jù)長(zhǎng)度*/

            unsigned char mem[GLOBALFIFO_SIZE]; /*全局內(nèi)存*/

            struct semaphore sem; /*并發(fā)控制用的信號(hào)量*/

            wait_queue_head_t r_wait; /*阻塞讀用的等待隊(duì)列頭*/

            wait_queue_head_t w_wait; /*阻塞寫用的等待隊(duì)列頭*/

            struct fasync_struct *async_queue; /* 異步結(jié)構(gòu)體指針,用于讀 */

            };

            /*文件釋放函數(shù)*/

            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; //獲得設(shè)備結(jié)構(gòu)體指針

            int ret;

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

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

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

            /* 等待FIFO非滿 */

            if (dev->current_len == GLOBALFIFO_SIZE)

            {

            if (filp->f_flags &O_NONBLOCK)

            //如果是非阻塞訪問

            {

            ret = - EAGAIN;

            goto out;

            }

            __set_current_state(TASK_INTERRUPTIBLE); //改變進(jìn)程狀態(tài)為睡眠

            up(&dev->sem);

            schedule(); //調(diào)度其他進(jìn)程執(zhí)行

            if (signal_pending(current))

            //如果是因?yàn)樾盘?hào)喚醒

            {

            ret = - ERESTARTSYS;

            goto out2;

            }

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

            }

            /*從用戶空間拷貝到內(nèi)核空間*/

            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); //喚醒讀等待隊(duì)列

            /* 產(chǎn)生異步讀信號(hào) */

            if (dev->async_queue)

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

            ret = count;

            }

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

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

            set_current_state(TASK_RUNNING);

            return ret;

            }

            下面再給出測(cè)試程序:

            #include ...

            //接收到異步讀信號(hào)的動(dòng)作

            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)

            {

            //啟動(dòng)信號(hào)驅(qū)動(dòng)機(jī)制

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

            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");

            }

            }

            當(dāng)我們加載完驅(qū)動(dòng)并創(chuàng)建完設(shè)備節(jié)點(diǎn)后,運(yùn)行上述程序,每當(dāng)通過echo向/dev/globalfilfo寫入新的數(shù)據(jù)后,input_handler將會(huì)被調(diào)用。如下所示:

            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

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



          關(guān)鍵詞: Linux 異步I/O

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉