国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

查看: 3125|回復(fù): 0
打印 上一主題 下一主題

Linux字符設(shè)備驅(qū)動(dòng)程序工作機(jī)理分析

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2016-4-11 15:26:05 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
關(guān)鍵詞: Linux , 字符設(shè)備
1 本文主題
    本文主要分析Linux字符設(shè)備驅(qū)動(dòng)程序的工作機(jī)理。主要內(nèi)容以及代碼片段來源于《LDD3》,俺只是從另外一個(gè)角度來講述。
    見過很多關(guān)于驅(qū)動(dòng)程序的書,基本上都是告訴你怎么做,然后你STEP BY STEP,然后運(yùn)行完后結(jié)果就出來了,可是其背后到底是如何工作的呢?雖說《LDD3》也講了很多原理性的東西,但是我覺得這個(gè)問題其描述得并不明確。
2 關(guān)于scull
    scull是《LDD3》的一個(gè)字符設(shè)備驅(qū)動(dòng)程序,其加載之后會(huì)在文件系統(tǒng)下生成/dev/scull文件,在shell下可以對(duì)其進(jìn)行一系列的操作,例如可以使用cp、dd或者輸入輸出重定向等命令來訪問這個(gè)文件,也就是訪問這個(gè)字符設(shè)備。
3 /dev/scull是如何生成的
    該文件是在驅(qū)動(dòng)程序模塊加載時(shí)生成的,具體實(shí)現(xiàn)是在scull_load(可以到www.oreilly.com下載,或者《LDD3_中文》的P51)這個(gè)腳本里。
    在shellinsmodscull.ko之后,系統(tǒng)會(huì)在/proc/devices文件里生成設(shè)備名以及與之對(duì)應(yīng)的主設(shè)備號(hào)信息,scull_load腳本根據(jù)該信息mknod/dev/scull文件節(jié)點(diǎn)。
    注意下mknod時(shí)給的參數(shù)信息,其中注明了主設(shè)備號(hào)以及次設(shè)備號(hào)信息。
4 shell下操作/dev/scull是如何關(guān)聯(lián)到我們自己編寫的scull模塊的
    這個(gè)問題一直困擾了我很久,不過現(xiàn)在我基本上算是弄明白了。
4.1 先回顧下scull模塊程序的初始化操作里做了什么事情。
   
    搞驅(qū)動(dòng)的都知道,初始化的時(shí)候需要進(jìn)行設(shè)備注冊(cè),核心代碼如下:
    static void scull_setup_cdev(struct scull_dev *dev, int index)
    {
        int err, devno = MKDEV(scull_major, scull_minor + index);

        cdev_init(&dev->cdev, &scull_fops);
        dev->cdev.owner = THIS_MODULE;
        dev->cdev.ops = &scull_fops;
        err = cdev_add(&dev->cdev, devno, 1);
        ...
    }
   
    scull_fops是一個(gè)數(shù)組,其中保存了我們的scull實(shí)際的操作:
    struct file_operation scull_fops = {
        ...
        .open = scull_open,
        .read = scull_read,
        .write = scull_write,
        .release = scull_release,
        cdevstruct cdev類型(該類型由系統(tǒng)定義)的變量,其嵌入在struct scull_dev(該類型由scull模塊定義)中:
    struct scull_dev{
        ...
        struct cdev cdev;
        ...
    }
      從這句代碼
    cdev_add(&dev->cdev, devno, 1);
    我們可以發(fā)現(xiàn),設(shè)備號(hào)devno已經(jīng)和內(nèi)核內(nèi)部結(jié)構(gòu)cdev關(guān)聯(lián)起來了。
4.2 /dev/scull設(shè)備的打開操作

    /dev/scull是文件系統(tǒng)中的一個(gè)設(shè)備文件,其在內(nèi)核中由sturct inode結(jié)構(gòu)表示。
   
    一般說來,inode結(jié)構(gòu)下由兩個(gè)元素和驅(qū)動(dòng)程序有關(guān):
    dev_t i_rdev;                 這個(gè)是設(shè)備號(hào)
    struct cdev *i_cdev;          這里是一個(gè)指針,struct cdev是字符設(shè)備在內(nèi)核里的表示,注意我們?cè)?/font>4.1小節(jié)里也提到了這個(gè)結(jié)構(gòu)。
     也就是說,系統(tǒng)在打開/dev/scull之前僅知道inode信息。在4.1小節(jié)里已經(jīng)說過了,設(shè)備號(hào)和內(nèi)核內(nèi)部結(jié)構(gòu)cdev關(guān)聯(lián)起來了,因此cdev下的ops也和設(shè)備號(hào)關(guān)聯(lián)起來了,ops已經(jīng)初始化為scull_fops。所以我們才能夠通過inode中的設(shè)備號(hào)i_rdev定位到此時(shí)打開的是哪一個(gè)設(shè)備,從而去調(diào)用相應(yīng)設(shè)備的open操作。
  看看open函數(shù)的原型吧:
    int (*open)(struct inode*, struct file*);
    第一個(gè)參數(shù)是struct inode類型的指針,該指針由內(nèi)核傳遞過來,是設(shè)備文件在內(nèi)核中的表示。
    第二個(gè)參數(shù)struct file類型的指針,open之后,設(shè)備文件在內(nèi)核中就以struct file結(jié)構(gòu)來表示了。
看看open操作在scull里的實(shí)現(xiàn)吧:
    int scull_open(struct inode *inode, struct file *filp)
    {
        struct scull_dev *dev;

        dev = container_of(inode->i_cdev, struct scull_dev, cdev);
        filp->private_data = dev;
        ...
    }
    第一句代碼通過宏container_of把包裹inode->i_cdev的結(jié)構(gòu)提取出來了,該結(jié)構(gòu)就是在scull模塊里定以的struct scull_dev,其中包含了scull模塊所需要的私有信息。
    第二句代碼把該私有信息加入內(nèi)核數(shù)據(jù)結(jié)構(gòu)struct file,之前說過了,open后的文件在內(nèi)核里以struct file結(jié)構(gòu)表示。
4.3 /dev/scull的讀寫操作

    先看下讀寫操作的函數(shù)原型:
    ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write)(struct file*, char __user *, size_t, loff_t *);
    其參數(shù)內(nèi)容我不做過多解釋,注意其第一個(gè)參數(shù)是struct file類型的指針,該指針由內(nèi)核傳入,也就是open之后的那個(gè)文件指針。

    通過這個(gè)指針,能夠找到scull模塊的私有數(shù)據(jù)結(jié)構(gòu)struct scull_dev,并對(duì)其操作,我們可以從read/write操作在scull里的實(shí)現(xiàn)看到這個(gè)做法:
    ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
    {
        sturct scull_dev *dev = filp->private_data;
        int quantum = dev->quantum, qset = dev->qset;
        ...
    }
   
    ssize_t scull_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
    {
        sturct scull_dev *dev = filp->private_data;
        int quantum = dev->quantum, qset = dev->qset;
        ...
    }

u=2429609584,2450763625&fm=21&gp=0 - 副本.jpg (4.55 KB)

u=2429609584,2450763625&fm=21&gp=0 - 副本.jpg

10671746 - 副本.gif (36.64 KB)

10671746 - 副本.gif

本版積分規(guī)則

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲国产精品成人综合久久久 | 天海翼一区二区在线观看 | 男人天堂导航 | 亚洲人成亚洲精品 | 日本免费一区二区三区中文字幕 | 一区二区三区欧美视频 | 毛片特黄 | 狠狠色丁香九九婷婷综合五月 | xx欧美 | 中文字幕欧美视频 | 国产在线视频自拍 | 全天免费91计划网 | 成人香蕉视频 | 91亚洲精品国产自在现线 | 日本不卡视频免费 | 欧美亚洲另类在线 | www.av视频在线 | 中文字幕 视频一区 | 国产免费久久精品44 | 国产福利不卡一区二区三区 | 九九99久久精品国产 | 国产精品久久久久久免费播放 | 日韩欧美视频一区二区 | 日韩毛片免费线上观看 | 欧美在线观看a | 国产拍自 | 免费黄色在线观看 | 四虎久久久 | 亚洲国产成人精品青青草原100 | 免费在线日韩 | 国产亚洲福利精品一区二区 | 三级视频网| 久久亚洲国产成人亚 | 九九亚洲精品自拍 | 欧美3p大片在线观看完整版 | 99热精品在线播放 | 亚洲视频区 | 91精品导航在线网址 | 免费人成在线观看网站品爱网日本 | 男女啪啪抽搐一进一出免费看 | 亚洲第一免费播放区 |