一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

內核驅動之ioctl接口的實現

 心不留意外塵 2016-06-17

http://blog.csdn.net/skyflying2012/article/details/8210799

2012

大部分驅動需要 -- 除了讀寫設備的能力 -- 通過設備驅動進行各種硬件控制的能力. 大部分設備可進行超出簡單的數據傳輸之外的操作; 用戶空間必須常常能夠請求, 例如, 設備鎖上它的門, 彈出它的介質, 報告錯誤信息, 改變波特率, 或者自我銷毀. 這些操作常常通過 ioctl 方法來支持, 它通過相同名子的系統調用來實現.

在用戶空間, ioctl 系統調用有下面的原型:

int ioctl(int fd, unsigned long cmd, ...);

ioctl 驅動方法有和用戶空間版本不同的原型:

int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);

inode filp 指針是對應應用程序傳遞的文件描述符 fd 的值, 和傳遞給 open 方法的相同參數. cmd 參數從用戶那里不改變地傳下來, 并且可選的參數 arg 參數以一個 unsigned long 的形式傳遞, 不管它是否由用戶給定為一個整數或一個指針. 如果調用程序不傳遞第 3 個參數, 被驅動操作收到的 arg 值是無定義的. 因為類型檢查在這個額外參數上被關閉, 編譯器不能警告你如果一個無效的參數被傳遞給 ioctl, 并且任何關聯的錯誤將難以查找.

ioctl 命令數字應當在這個系統是唯一的, 為了阻止向錯誤的設備發(fā)出正確的命令而引起的錯誤. 為幫助程序員創(chuàng)建唯一的 ioctl 命令代碼, 這些編碼已被劃分為幾個位段.

定義 ioctl 命令號的正確方法使用 4 個位段, 它們有下列的含義. 這個列表中介紹的新符號定義在 <linux/ioctl.h>.

type

魔數. 只是選擇一個數(在參考了 ioctl-number.txt之后)并且使用它在整個驅動中. 這個成員是 8 位寬(_IOC_TYPEBITS).

number

(順序). 它是 8 (_IOC_NRBITS).

direction

數據傳送的方向,如果這個特殊的命令涉及數據傳送. 可能的值是 _IOC_NONE(沒有數據傳輸), _IOC_READ, _IOC_WRITE, _IOC_READ|_IOC_WRITE (數據在2個方向被傳送). 數據傳送是從應用程序的觀點來看待的; _IOC_READ 意思是從設備讀, 因此設備必須寫到用戶空間. 注意這個成員是一個位掩碼, 因此 _IOC_READ _IOC_WRITE 可使用一個邏輯 AND 操作來抽取.

size

涉及到的用戶數據的大小. 這個成員的寬度是依賴體系的, 但是常常是 13 或者 14 . 你可為你的特定體系在宏 _IOC_SIZEBITS 中找到它的值. 你使用這個 size 成員不是強制的 - 內核不檢查它 -- 但是它是一個好主意. 正確使用這個成員可幫助檢測用戶空間程序的錯誤并使你實現向后兼容, 如果你曾需要改變相關數據項的大小. 如果你需要更大的數據結構, 但是, 你可忽略這個 size 成員. 我們很快見到如何使用這個成員.

定義宏來幫助建立命令號, 如下:

 _IO(type,nr)(給沒有參數的命令),

_IOR(type, nre, datatype)(給從驅動中讀數據的),

_IOW(type,nr,datatype)(給寫數據),

 _IOWR(type,nr,datatype)(給雙向傳送).

type number 成員作為參數被傳遞, 并且 size 成員通過應用 sizeof datatype 參數而得到.

驅動中來解碼這個號: _IOC_DIR(nr), _IOC_TYPE(nr), _IOC_NR(nr), _IOC_SIZE(nr).

 

/* Ioctlün */

#define MEM_IOC_MAGIC 'k'  

 

#define MEM_IOC_RESET    _IO(MEM_IOC_MAGIC, 0)     

#define MEM_IOC_GET      _IOR(MEM_IOC_MAGIC, 1, int)

#define MEM_IOC_SET      _IOW(MEM_IOC_MAGIC, 2, int)

 

使用 ioctl 參數

在看 scull 驅動的 ioctl 代碼之前, 我們需要涉及的另一點是如何使用這個額外的參數. 如果它是一個整數, 就容易: 它可以直接使用. 如果它是一個指針, 但是, 必須小心些.

當用一個指針引用用戶空間, 我們必須確保用戶地址是有效的. 試圖存取一個沒驗證過的用戶提供的指針可能導致不正確的行為, 一個內核 oops, 系統崩潰, 或者安全問題. 它是驅動的責任來對每個它使用的用戶空間地址進行正確的檢查, 并且返回一個錯誤如果它是無效的.

copy_from_user copy_to_user 函數, 它們可用來安全地移動數據到和從用戶空間. 這些函數也可用在 ioctl 方法中, 但是 ioctl 調用常常包含小數據項, 可通過其他方法更有效地操作. 開始, 地址校驗(不傳送數據)由函數 access_ok 實現, 它定義在 <asm/uaccess.h>:

int access_ok(int type, const void *addr, unsigned long size);

第一個參數應當是 VERIFY_READ 或者 VERIFY_WRITE, 依據這個要進行的動作是否是讀用戶空間內存區(qū)或者寫它. addr 參數持有一個用戶空間地址, size 是一個字節(jié)量. 例如, 如果 ioctl 需要從用戶空間讀一個整數, size sizeof(int). 如果你需要讀和寫給定地址, 使用 VERIFY_WRITE, 因為它是 VERIRY_READ 的超集.

不象大部分的內核函數, access_ok 返回一個布爾值: 1 是成功(存取沒問題) 0 是失敗(存取有問題). 如果它返回假, 驅動應當返回 -EFAULT 給調用者.

ioctl 命令的實現

 

long mem_ioctl( struct file *filp, unsigned int cmd, unsigned long arg)

{

    struct mem_dev *dev = filp->private_data;

    int ret = 0, err = 0;

 

    /* ünēАД */

    if (_IOC_TYPE(cmd) != MEM_IOC_MAGIC)

        return -ENOTTY;

    if (_IOC_NR(cmd) > MEM_IOC_MAXNR)

        return -ENOTTY;

   

    /* n */

    if (_IOC_DIR(cmd) & _IOC_READ) 

        err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));

    else if (_IOC_DIR(cmd) & _IOC_WRITE)       

        err =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));

    if (err)       

        return -EFAULT;

 

    /*

    switch(cmd)

    {

    case MEM_IOC_RESET:

        dev->size = 0;

        break;

       

    case MEM_IOC_GET:

        ret = put_user(dev->size, (int __user *) arg);

        break;

       

    case MEM_IOC_SET:

        ret = get_user(dev->size, (int __user *) arg);

        break;

       

    default:   

        return -EINVAL;    

    }

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产爆操白丝美女在线观看| 美国女大兵激情豪放视频播放| 亚洲伊人久久精品国产| 日韩女优视频国产一区| 一区二区在线激情视频| 国产女高清在线看免费观看| 一区二区日本一区二区欧美| 国内精品伊人久久久av高清| 国产伦精品一区二区三区精品视频 | 亚洲精品熟女国产多毛| 欧美美女视频在线免费看| 欧美日韩乱码一区二区三区| 免费高清欧美一区二区视频| 暴力性生活在线免费视频| 国产精品欧美在线观看| 免费精品一区二区三区| 字幕日本欧美一区二区| 日韩免费午夜福利视频| 午夜福利视频日本一区| 国产又粗又长又爽又猛的视频| 欧美黑人黄色一区二区| 亚洲男女性生活免费视频| 国产中文字幕一区二区| 精品国产91亚洲一区二区三区 | 精品人妻一区二区三区四区久久| 日韩美成人免费在线视频| 欧美日韩精品久久亚洲区熟妇人 | 东北女人的逼操的舒服吗| 91日韩欧美国产视频| 亚洲精品国男人在线视频| 国产二级一级内射视频播放| 黄片三级免费在线观看| 噜噜中文字幕一区二区| 国产亚洲欧美一区二区| 五月综合激情婷婷丁香| 东京热男人的天堂一二三区| 欧美大粗爽一区二区三区| 风间中文字幕亚洲一区| 精品日韩av一区二区三区| 国产传媒免费观看视频| 少妇一区二区三区精品|