在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > arm驅(qū)動(dòng)linux異步通知與異步IO

            arm驅(qū)動(dòng)linux異步通知與異步IO

            作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
            《[arm驅(qū)動(dòng)]linux異步通知異步IO》涉及內(nèi)核驅(qū)動(dòng)函數(shù)二個(gè),內(nèi)核結(jié)構(gòu)體一個(gè),分析了內(nèi)核驅(qū)動(dòng)函數(shù)二個(gè);可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)模板二個(gè),可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)三個(gè)

            描述:設(shè)備文件IO訪問:阻塞與非阻塞io訪問,poll函數(shù)提供較好的解決設(shè)備訪問的機(jī)制,但是如果有了異步通知整套機(jī)制就更加完整了

            本文引用地址:http://www.biyoush.com/article/201611/318221.htm

            一、阻塞 I/O,非阻塞IO,異步I/O

            1、阻塞 I/O :掛起進(jìn)程一直等待設(shè)備可訪問后再訪問

            2、非阻塞IO:進(jìn)程進(jìn)行對(duì)設(shè)備訪問一次,不可訪問時(shí),繼續(xù)執(zhí)行下一條指令
            3、異步I/O:非常類似于硬件上“中斷”的概念(硬件去call軟件,內(nèi)核去call應(yīng)用程序);信號(hào)是在軟件層次上對(duì)中斷機(jī)制的一種模擬;

            a)原理:信號(hào)是異步的,一個(gè)進(jìn)程不必通過任何操作來等待信號(hào)的到達(dá);事實(shí)上:進(jìn)程也不知道信號(hào)到底什么時(shí)候到達(dá);“一個(gè)進(jìn)程收到一個(gè)異步通知信號(hào)"與"處理器收到一個(gè)中斷請(qǐng)求"原理是一樣的;

            4、異步I/O通知隊(duì)列(async_queue):內(nèi)核通過“內(nèi)核異步通知的程序 fasync()函數(shù)”將設(shè)備文件fd描述符加入異步通知隊(duì)列(內(nèi)核異步通知的鏈表)。當(dāng)fd有I/O操作發(fā)生時(shí)內(nèi)核通過kill_fasync()釋放(產(chǎn)生) SIGIO 信號(hào),從而達(dá)到主動(dòng)通知注冊(cè)過SIG_IO信號(hào)的應(yīng)用程序。

            5、異步通知對(duì)象:首先它是設(shè)備文件,其次要注冊(cè)過fasync()函的文件;異步通知對(duì)象不是不是普通文件(不是隨便的/tmp/text.txt),因?yàn)槠胀ㄎ募]有在內(nèi)核中實(shí)現(xiàn)fasync()函數(shù)和kill_fasync()
            二、異步通訊應(yīng)用程序部分
            模板一)設(shè)備文件的異步通知應(yīng)用程序

            voidinput_handler(intnum){//信號(hào)處理函數(shù)
            }
            //打開目標(biāo)設(shè)備
            fd = open("設(shè)備文件路徑如/dev/xxx", O_RDWR);
            //設(shè)置好目標(biāo)設(shè)備的SIGIO信號(hào)處理程序;等待內(nèi)核kill_fasync()釋放 SIGIO 信號(hào)
            signal(SIGIO,input_handler);
            //使當(dāng)前進(jìn)程變成文件的主人,這樣才能使文件中的信號(hào)發(fā)到當(dāng)前進(jìn)程
            fcntl(fd, F_SETOWN, getpid());
            //獲得當(dāng)前fd的flag值
            oflags = fcntl(fd, F_GETFL);
            /*設(shè)置設(shè)備文件描述符號(hào)fd的FASYNC異步通知標(biāo)志,
            即給fd添加異步通知模式,fasync()函數(shù)將fd加入異步IO通知隊(duì)列*/
            fcntl(fd, F_SETFL, oflags | FASYNC);

            圖示一、異步通知工作過程圖

            實(shí)例一)以標(biāo)準(zhǔn)輸入輸出設(shè)備異步通知

            #include
            #include
            #include
            #include
            #include
            #define MAX_LEN 100
            voidinput_handler(intnum)
            {
            chardata[MAX_LEN];
            intlen;
            len = read(STDIN_FILENO, &data, MAX_LEN);
            data[len] = 0;
            printf("input available :%sn", data);
            }
            voidsetFdAsync(intfd){
            intoflags;
            //當(dāng)前進(jìn)程變成文件的主人
            fcntl(fd, F_SETOWN, getpid());
            //本程序中fd = STDIN_FILENO標(biāo)準(zhǔn)輸入設(shè)備設(shè)備文件描述符號(hào);普通文件內(nèi)核中沒有實(shí)現(xiàn)FASYNC,不能使用異步通知
            oflags = fcntl(fd, F_GETFL);//
            //FASYNC在glibc 的fcntl.h文件中可以看到這樣的定義 #define FASYNC O_ASYNC
            fcntl(fd, F_SETFL, oflags | FASYNC);
            }
            voidmain(){
            intfd = STDIN_FILENO;//STDIN_FILENO輸入輸出設(shè)備描述符號(hào),一般是鍵盤
            signal(SIGIO,input_handler);//設(shè)置好目標(biāo)設(shè)備的SIGIO信號(hào)處理程序;等待內(nèi)核kill_fasync()釋放 SIGIO 信號(hào)
            setFdAsync(fd);
            while(1);
            }

            運(yùn)行結(jié)果:

            efgwrfgregr
            input available :efgwrfgregr
            sfsdf
            input available :sfsdf
            //本程序電腦上運(yùn)行時(shí),由于系統(tǒng)對(duì)STDIN_FILENO有特殊保護(hù),while里面的程序運(yùn)行了兩次,進(jìn)程就被系統(tǒng)掛機(jī)休眠,此時(shí)cpu消耗為0;
            //但我在arm開發(fā)板上的linux2.6內(nèi)核運(yùn)行時(shí),while正常,進(jìn)程不被掛起,估計(jì)是沒鍵盤的原因...,也待解

            三、驅(qū)動(dòng)程序部分
            驅(qū)動(dòng)程序:一項(xiàng)數(shù)據(jù)結(jié)構(gòu)和兩個(gè)函數(shù)
            結(jié)構(gòu)體一)一項(xiàng)數(shù)據(jù)結(jié)構(gòu)----- fasync_struct結(jié)構(gòu)體
            內(nèi)核源碼一)fasync_struct結(jié)構(gòu)體內(nèi)核源碼

            struct fasync_struct {
            int magic;//啟用設(shè)備文件鏡像,監(jiān)聽文件是否變化(這個(gè)說法我猜的)
            int fa_fd;//文件描述符
            struct fasync_struct *fa_next; /* 異步通知單鏈表 */
            //filp是進(jìn)程通過PCB中的文件描述符表找到該fd所指向的文件指針;在fopen流操作中使用file結(jié)構(gòu)體指針?biāo)膬?yōu)點(diǎn)是帶有I/O緩存
            struct file *fa_file;
            //struct file表示該進(jìn)程打開的文件,其中有一個(gè)owner屬性,用來表示打開設(shè)備文件的進(jìn)程
            };

            兩個(gè)函數(shù)
            內(nèi)核部分函數(shù)一)fasync_helper處理設(shè)備文件異步通知的標(biāo)志(O_ASYNC或FASYNC),將fd加入異步通知隊(duì)列函數(shù)

            fasync_helper(int fd, struct file * filp, int on, struct fasync_struct * * fapp);

            內(nèi)核源碼二)fasync_helper內(nèi)核源碼分析

            //第一次因?yàn)閛n = MODE = oflag | FASYNC,on!=0所以執(zhí)行if (on)對(duì)struct fasync_struct **fapp進(jìn)行初始化,
            //當(dāng)程序釋放設(shè)備使用myfasync_drv_fasync(-1, file, 0),就執(zhí)行g(shù)oto out釋放中斷
            int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fapp)
            {
            struct fasync_struct *fa, **fp;
            struct fasync_struct *new = NULL;
            int result = 0;
            if (on) {//第一次分配fapp空間
            new = kmem_cache_alloc(fasync_cache, GFP_KERNEL);
            if (!new)
            return -ENOMEM;
            }
            write_lock_irq(&fasync_lock);
            for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) {//第一次初始化fapp
            if (fa->fa_file == filp) {
            if(on) {
            fa->fa_fd = fd;
            kmem_cache_free(fasync_cache, new);
            } else {
            *fp = fa->fa_next;
            kmem_cache_free(fasync_cache, fa);
            result = 1;
            }
            goto out;
            }
            }
            if (on) {
            new->magic = FASYNC_MAGIC;
            new->fa_file = filp;
            new->fa_fd = fd;
            new->fa_next = *fapp;
            *fapp = new;
            result = 1;
            }
            out:
            write_unlock_irq(&fasync_lock);
            return result;
            }
            EXPORT_SYMBOL(fasync_helper);

            釋放信號(hào)函數(shù)
            內(nèi)核部分函數(shù)二)kill_fasync(struct fasync_struct * * fp, int sig, int band)
            參數(shù):sig就是我們要發(fā)送的信號(hào);band(帶寬),一般都是使用POLL_IN,表示設(shè)備可讀,如果設(shè)備可寫,使用POLL_OUT
            內(nèi)核源碼三)釋放(產(chǎn)生)異步讀信號(hào)函數(shù)

            void __kill_fasync(struct fasync_struct *fa, int sig, int band)
            {
            while (fa) {
            struct fown_struct * fown;
            //如果設(shè)備文件鏡像不存在如設(shè)備文件不存在(被刪除或改名)或取消了注冊(cè)FASYNC;鏡像映射失敗跳出kill_fasync,不產(chǎn)生信號(hào)
            if (fa->magic != FASYNC_MAGIC) {
            printk(KERN_ERR "kill_fasync: bad magic number in "
            "fasync_struct!n");
            return;
            }
            fown = &fa->fa_file->f_owner;
            /* Dont send SIGURG to processes which have not set a
            queued signum: SIGURG has its own default signalling
            mechanism. */
            if (!(sig == SIGURG && fown->signum == 0))
            send_sigio(fown, fa->fa_fd, band);
            fa = fa->fa_next;
            }
            }
            EXPORT_SYMBOL(__kill_fasync);

            模板二)信號(hào)的異步通知機(jī)制模板

            struct VirtualDisk{
            struct cdev cdev;
            //...其他全局變量....
            struct fasync_struct *async_queue;//異步結(jié)構(gòu)體指針
            };
            /*異步讀信號(hào)*/
            static int myfasync_drv_fasync(int fd, struct file *file, int mode){
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            //....................
            return fasync_helper(fd, file, mode, &devp->async_queue);
            }
            static ssize_t myfasync_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            //...............
            //產(chǎn)生異步讀信號(hào)SIGIO
            if(devp->async_queue)kill_fasync(&devp->async_queue, SIGIO, POLL_IN);
            return 0;
            }
            static int myfasync_drv_release(struct inode *inode, struct file *file)
            {
            /*當(dāng)設(shè)備關(guān)閉時(shí),需要將fasync_struct從異步隊(duì)列中刪除/*
            myfasync_drv_fasync(-1, file, 0);
            return 0;
            }

            實(shí)例二)驅(qū)動(dòng)程序完整實(shí)例:

            //“myfasync_drv”,"myfasync_","myfasync_drv"
            #include //模塊所需的大量符號(hào)和函數(shù)定義
            #include
            #include //文件系統(tǒng)相關(guān)的函數(shù)和頭文件
            #include //指定初始化和清除函數(shù)
            #include
            #include //cdev結(jié)構(gòu)的頭文件包含
            #include
            #include
            //#include //包含驅(qū)動(dòng)程序使用的大部分內(nèi)核API的定義,包括睡眠函數(shù)以及各種變量聲明
            #include //在內(nèi)核和用戶空間中移動(dòng)數(shù)據(jù)的函數(shù)
            #include
            #include
            #include
            #include
            #define VIRTUALDISK_SIZE 0x1000//4k
            #define MEM_CLEAR 0x1
            #define VIRTUALDISK_MAJOR 250
            int VirtualDisk_major = VIRTUALDISK_MAJOR;
            struct fasync_struct *async_queue;//異步結(jié)構(gòu)體指針
            struct VirtualDisk{
            struct cdev cdev;//詳細(xì)看cdev機(jī)制
            unsigned char mem[VIRTUALDISK_SIZE ];
            long count; /*記錄設(shè)備目前被多少設(shè)備打開*/

            };
            static struct class *myfasync_class;
            static struct class_device *myfasync_class_dev;
            struct VirtualDisk *VirtualDiskp;
            static int myfasync_drv_fasync(int fd, struct file *file, int mode){
            printk("myfasync_drv_fasync %dn", fd);
            return fasync_helper(fd, file, mode, &async_queue);
            }
            static int myfasync_drv_open(struct inode *inode, struct file *file)
            {
            printk("myfasync_drv openn");
            file->private_data = VirtualDiskp;
            VirtualDiskp->count++; /*增加設(shè)備打開次數(shù)*/
            return 0;
            }
            static int myfasync_drv_release(struct inode *inode, struct file *file)
            {
            printk("myfasync_drv releasen");
            VirtualDiskp->count--; /*減少設(shè)備打開次數(shù)*/
            myfasync_drv_fasync(-1, file, 0);//當(dāng)設(shè)備關(guān)閉時(shí),需要將fasync_struct從異步隊(duì)列中刪除
            return 0;
            }
            /*seek文件定位函數(shù):seek()函數(shù)對(duì)文件定位的起始地址可以是文件開頭(SEEK_SET,0)、當(dāng)前位置(SEEK_CUR,1)、文件尾(SEEK_END,2)*/
            static loff_t myfasync_drv_llseek(struct file *file, loff_t offset, int origin){
            loff_t ret = 0;/*返回的位置偏移*/

            switch (origin)
            {
            case SEEK_SET: /*相對(duì)文件開始位置偏移*/
            if (offset < 0)/*offset不合法*/
            {
            ret = - EINVAL; /*無效的指針*/
            break;
            }
            if ((unsigned int)offset > VIRTUALDISK_SIZE)/*偏移大于設(shè)備內(nèi)存*/
            {
            ret = - EINVAL; /*無效的指針*/
            break;
            }
            file->f_pos = (unsigned int)offset; /*更新文件指針位置*/
            ret = file->f_pos;/*返回的位置偏移*/
            break;
            case SEEK_CUR: /*相對(duì)文件當(dāng)前位置偏移*/
            if ((file->f_pos + offset) > VIRTUALDISK_SIZE)/*偏移大于設(shè)備內(nèi)存*/
            {
            ret = - EINVAL;/*無效的指針*/
            break;
            }
            if ((file->f_pos + offset) < 0)/*指針不合法*/
            {
            ret = - EINVAL;/*無效的指針*/
            break;
            }
            file->f_pos += offset;/*更新文件指針位置*/
            ret = file->f_pos;/*返回的位置偏移*/
            break;
            default:
            ret = - EINVAL;/*無效的指針*/
            break;
            }
            return ret;
            }
            /*設(shè)備控制函數(shù):ioctl()函數(shù)接受的MEM_CLEAR命令,這個(gè)命令將全局內(nèi)存的有效數(shù)據(jù)長(zhǎng)度清零,對(duì)于設(shè)備不支持的命令,ioctl()函數(shù)應(yīng)該返回-EINVAL*/
            static int myfasync_drv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
            struct VirtualDisk *devp = file->private_data;/*獲得設(shè)備結(jié)構(gòu)體指針*/

            switch (cmd)
            {
            case MEM_CLEAR:/*設(shè)備內(nèi)存清零*/
            memset(devp->mem, 0, VIRTUALDISK_SIZE);
            printk(KERN_INFO "VirtualDisk is set to zeron");
            break;
            default:
            return - EINVAL;
            }
            return 0;
            }
            /*讀函數(shù):讀寫函數(shù)主要是讓設(shè)備結(jié)構(gòu)體的mem[]數(shù)組與用戶空間交互數(shù)據(jù),并隨著訪問字節(jié)數(shù)變更返回用戶的文件讀寫偏移位置*/
            static ssize_t myfasync_drv_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
            {
            unsigned long p = *ppos; /*記錄文件指針偏移位置*/
            unsigned int countt = count;/*記錄需要讀取的字節(jié)數(shù)*/
            int ret = 0; /*返回值*/
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            printk("myfasync_drv readn");
            /*分析和獲取有效的讀長(zhǎng)度*/
            if (p >= VIRTUALDISK_SIZE ) /*要讀取的偏移大于設(shè)備的內(nèi)存空間*/
            return 0;/*讀取地址錯(cuò)誤*/
            if (countt > VIRTUALDISK_SIZE - p)/*要讀取的字節(jié)大于設(shè)備的內(nèi)存空間*/
            countt = VIRTUALDISK_SIZE - p;/*將要讀取的字節(jié)數(shù)設(shè)為剩余的字節(jié)數(shù)*/
            /*內(nèi)核空間->用戶空間交換數(shù)據(jù)*/
            if (copy_to_user(buf, (void*)(devp->mem + p), countt))
            {
            ret = - EFAULT;
            }
            else
            {
            *ppos += countt;
            ret = countt;
            printk("read %d bytes(s) is %ldn", countt, p);
            }
            printk("bytes(s) is %sn", devp->mem);
            return ret;
            }
            /*
            file 是文件指針,count 是請(qǐng)求的傳輸數(shù)據(jù)長(zhǎng)度,buff 參數(shù)是指向用戶空間的緩沖區(qū),這個(gè)緩沖區(qū)或者保存要寫入的數(shù)據(jù),或者是一個(gè)存放新讀入數(shù)據(jù)的空緩沖區(qū),該地址在內(nèi)核空間不能直接讀寫,ppos 是一個(gè)指針指向一個(gè)"long offset type"對(duì)象, 它指出用戶正在存取的文件位置. 返回值是一個(gè)"signed size type。寫的位置相對(duì)于文件開頭的偏移。
            */
            static ssize_t myfasync_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
            {
            unsigned long p = *ppos; /*記錄文件指針偏移位置*/
            int ret = 0; /*返回值*/
            unsigned int countt = count;/*記錄需要寫入的字節(jié)數(shù)*/
            struct VirtualDisk *devp = file->private_data; /*獲得設(shè)備結(jié)構(gòu)體指針*/
            printk("myfasync_drv writen");
            /*分析和獲取有效的寫長(zhǎng)度*/
            if (p >= VIRTUALDISK_SIZE )/*要寫入的偏移大于設(shè)備的內(nèi)存空間*/
            return 0;/*寫入地址錯(cuò)誤*/
            if (countt > VIRTUALDISK_SIZE - p)/*要寫入的字節(jié)大于設(shè)備的內(nèi)存空間*/
            countt = VIRTUALDISK_SIZE - p;/*將要寫入的字節(jié)數(shù)設(shè)為剩余的字節(jié)數(shù)*/
            /*用戶空間->內(nèi)核空間*/
            if (copy_from_user(devp->mem + p, buf, countt))
            ret = - EFAULT;
            else
            {
            *ppos += countt;/*增加偏移位置*/
            ret = countt;/*返回實(shí)際的寫入字節(jié)數(shù)*/
            printk("written %u bytes(s) from%lu, buffer is %sn", countt, p, devp->mem);
            }
            if(async_queue){
            kill_fasync(&async_queue, SIGIO, POLL_IN);
            printk("write kill_fasyncn");
            }
            return ret;
            }
            static struct file_operations myfasync_drv_fops = {
            .owner = THIS_MODULE, /* 這是一個(gè)宏,推向編譯模塊時(shí)自動(dòng)創(chuàng)建的__this_module變量 */
            .open = myfasync_drv_open,
            .read = myfasync_drv_read,
            .write = myfasync_drv_write,
            .release = myfasync_drv_release,
            .llseek = myfasync_drv_llseek,
            .ioctl = myfasync_drv_ioctl,
            .fasync = myfasync_drv_fasync,
            };
            /*將 cdev 結(jié)構(gòu)嵌入一個(gè)你自己的設(shè)備特定的結(jié)構(gòu),你應(yīng)當(dāng)初始化你已經(jīng)分配的結(jié)構(gòu)使用以上函數(shù),有一個(gè)其他的 struct cdev 成員你需要初始化. 象 file_operations 結(jié)構(gòu),struct cdev 有一個(gè)擁有者成員,應(yīng)當(dāng)設(shè)置為 THIS_MODULE,一旦 cdev 結(jié)構(gòu)建立, 最后的步驟是把它告訴內(nèi)核, 調(diào)用:
            cdev_add(&dev->cdev, devno, 1);*/
            static void VirtualDisk_setup_cdev(struct VirtualDisk *dev, int minorIndex){
            int err;
            int devno = MKDEV(VirtualDisk_major, minorIndex);
            cdev_init(&dev->cdev, &myfasync_drv_fops);
            dev->cdev.owner = THIS_MODULE;
            err = cdev_add(&dev->cdev, devno, 1);
            if(err){
            printk("error %d cdev file addedn", err);
            }
            }
            static int myfasync_drv_init(void)
            {
            int result;
            dev_t devno = MKDEV(VirtualDisk_major, 0);
            if(VirtualDisk_major){
            result = register_chrdev_region(devno, 1, "myfasync_drv");
            }else{
            result = alloc_chrdev_region(&devno, 0, 1, "myfasync_drv");
            VirtualDisk_major = MAJOR(devno);
            }
            if(result < 0 ){
            return result;
            }
            VirtualDiskp = kmalloc(sizeof(struct VirtualDisk), GFP_KERNEL);
            if(!VirtualDiskp){
            result = -ENOMEM;
            goto fail_malloc;
            }
            memset(VirtualDiskp, 0, sizeof(struct VirtualDisk));
            VirtualDisk_setup_cdev(VirtualDiskp, 0);
            myfasync_class = class_create(THIS_MODULE, "myfasync_drv");
            if (IS_ERR(myfasync_class))
            return PTR_ERR(myfasync_class);
            myfasync_class_dev = class_device_create(myfasync_class, NULL, MKDEV(VirtualDisk_major, 0), NULL, "myfasync_drv"); /* /dev/xyz */
            if (IS_ERR(myfasync_class_dev))
            return PTR_ERR(myfasync_class_dev);
            return 0;
            fail_malloc:
            unregister_chrdev_region(devno, 1);
            return result;

            }
            static void myfasync_drv_exit(void)
            {
            cdev_del(&VirtualDiskp->cdev);
            kfree(VirtualDiskp);
            unregister_chrdev_region(MKDEV(VirtualDisk_major, 0), 1);
            class_device_unregister(myfasync_class_dev);
            class_destroy(myfasync_class);
            }
            module_init(myfasync_drv_init);
            module_exit(myfasync_drv_exit);
            MODULE_LICENSE("GPL");

            Makefile

            #myfasync_drv.c
            KERN_DIR = /workspacearm/linux-2.6.2.6
            all:
            make -C $(KERN_DIR) M=`pwd` modules
            cp myfasync_drv.ko /opt/fsmini/
            clean:
            make -C $(KERN_DIR) M=`pwd` modules clean
            rm -rf timerlists.order
            obj-m += myfasync_drv.o

            實(shí)例三)驅(qū)動(dòng)程序?qū)?yīng)的測(cè)試的應(yīng)用程序部分

            #include
            #include
            #include
            #include
            #include
            int myfd;
            int lenthe;
            void input_handler(int num)
            {
            char data[80];
            int len;
            lseek(myfd, -lenthe, SEEK_CUR);//移動(dòng)偏移量到寫之前位置
            len = read(myfd, data, lenthe);
            //data[len] = ;
            printf("myfd = %d, len = %d buffuer input available :%sn",myfd, len, data);
            }
            void setFdAsync(int fd){
            int oflags;
            //當(dāng)前進(jìn)程變成文件的主人
            fcntl(fd, F_SETOWN, getpid());
            //本程序中fd = STDIN_FILENO標(biāo)準(zhǔn)輸入設(shè)備設(shè)備文件描述符號(hào);普通文件內(nèi)核中沒有實(shí)現(xiàn)FASYNC,不能使用異步通信
            oflags = fcntl(fd, F_GETFL);//
            //FASYNC在glibc 的fcntl.h文件中可以看到這樣的定義 #define FASYNC O_ASYNC
            fcntl(fd, F_SETFL, oflags | FASYNC);
            }
            int main(){
            myfd = open("/dev/myfasync_drv", O_RDWR);//STDIN_FILENO輸入輸出設(shè)備描述符號(hào),一般是鍵盤
            printf("fd = %d,pid = %d", myfd, getpid());
            signal(SIGIO,input_handler);//設(shè)置好目標(biāo)設(shè)備的SIGIO信號(hào)處理程序;等待內(nèi)核kill_fasync()釋放 SIGIO 信號(hào)
            setFdAsync(myfd);
            printf("before whilen");
            while(1){
            char buffer[80];
            lenthe = read(STDIN_FILENO, buffer, 80);
            write(myfd, buffer, lenthe);
            }
            return 0;
            }

            我的Makefile

            objs := $(patsubst %c, %o, $(shell ls *.c))
            myarmgcc := /workspacearm/armlinuxgcc2626/bin/arm-linux-gcc
            mybutton.bin:$(objs)
            $(myarmgcc) -o $@ $^
            cp *.bin /opt/fsmini/
            %.o:%.c
            $(myarmgcc) -c -o $@ $<
            clean:
            rm -f *.bin *.o

            實(shí)驗(yàn)結(jié)果

            # insmod myfasync_drv.ko
            # ./mybutton.bin
            myfasync_drv open//對(duì)應(yīng)應(yīng)用程序myfd = open("/dev/myfasync_drv",調(diào)用了內(nèi)核驅(qū)動(dòng)open函數(shù)
            myfasync_drv_fasync 3//對(duì)應(yīng)應(yīng)用程序fcntl(fd, F_SETFL, oflags | FASYNC);調(diào)用了內(nèi)核驅(qū)動(dòng)的myfasync_drv_fasync()函數(shù)
            //
            fd = 3,pid = 793before while//while前的進(jìn)程信息輸出
            hello//鍵盤輸入hello
            myfasync_drv write//調(diào)用驅(qū)動(dòng)程序write函數(shù)
            written 6 bytes(s) from0, buffer is hello//驅(qū)動(dòng)程序write函數(shù)內(nèi)部輸出
            write kill_fasync//內(nèi)涵write函數(shù)中,執(zhí)行kill_fasync(&async_queue, SIGIO, POLL_IN);釋放SIGIO信號(hào)
            myfasync_drv read//此時(shí)應(yīng)用程序收到中斷,應(yīng)用程序執(zhí)行read函數(shù),read對(duì)應(yīng)內(nèi)核驅(qū)動(dòng)的read
            read 6 bytes(s) is 0//內(nèi)核驅(qū)動(dòng)read打印輸出
            bytes(s) is hello //內(nèi)核驅(qū)動(dòng)read打印輸出

            myfd = 3, len = 6 buffuer input available :hello//應(yīng)用程序input_handler函數(shù)輸出驅(qū)動(dòng)的寫入值
            //下面是while第二次執(zhí)行
            it is ok
            myfasync_drv write
            written 9 bytes(s) from6, buffer is hello
            it is ok

            write kill_fasync
            myfasync_drv read
            read 9 bytes(s) is 6
            bytes(s) is hello
            it is ok

            myfd = 3, len = 9 buffuer input available :it is ok
            //按ctrl+c退出程序,會(huì)執(zhí)行myfasync_drv_release中myfasync_drv_fasync(-1, file, 0),釋放本進(jìn)程的異步通知
            myfasync_drv release
            myfasync_drv_fasync -1

            #

            四、異步IO缺陷:當(dāng)有多個(gè)文件發(fā)送異步通知信號(hào)給一個(gè)進(jìn)程時(shí),進(jìn)程無法知道是哪個(gè)文件發(fā)送的信號(hào),這時(shí)候“設(shè)備文件 ”還是要借助poll機(jī)制完成IO;(應(yīng)用程序中使用select)



            評(píng)論


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

            關(guān)閉