linux 字符設備驅動模板

學習Linux設備驅動已經有一段時間了,但是發現學習後很多的知識點記憶模糊了,因此對學習過的知識進行了梳理和總結。

1.一般的驅動都是以模塊的形式存在的,那麼在字符設備的模塊加載函數中要完成設備號的申請(靜態、動態兩種方法)和cdev的註冊,而在卸載函數中實現設備號的釋放和cdev的註銷。

2. 驅動編寫模板:

/*
這個設備結構體是自己定義的結構體,包含字符設備結構體和自己定義的其他的成員。
*/
// 設備結構體
struct xxx_dev_t{

    struct cdev cdev;
    ...
}xxx_dev;

// 設備驅動模塊加載函數

static int __init xxx_init(void)
{
    ...
    cdev_init(&xxx_dev.cdev,&xxx_fops);// 這個字符設備初始化函數是最關鍵的設備和驅動的綁定,這樣才能使用驅動函數來操作字符設備。
    xxx_dev.cdev.owner=THIS_MODULE;
    // 獲取字符設備號
    if(xxx_major){
        register_chrdev_region(xxx_dev_no,1,DEV_NAME); // 先是知道設備號靜態的申請,不成功則動態的分配申請。
        }else{
           alloc_chrdev_region(&xxx_dev_no,0,1,DEV_NAME);
        }
}
// 註冊設備
ret=cdev_add(&xxx_dev_cdev,xxx_dev_no,1);
}

// 設備驅動模塊卸載函數
static void __exit xxx_exit(void)
{
    // 釋放佔用的設備號
    unregister_chrdev_region(xxx_dev_no,1);
       //    註銷設備
     cdev_del(&xxx_dev.cdev);
....
}

3.驅動操作成員函數的編寫,例如,open(),close(),read(),write(),release()等函數,先單獨的編寫在文件中,再賦給struct file_operations xxx_fops 結構體成員中。

// 讀設備
ssize_t xxx_read(strcut file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
    ...

    copy_to_user(buf,...,..);
}

ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
     ...
    copy_from_user(..., buf, ...);
     ...
}
/*
long xxx_ioctl() 函數等,根據自己的設備操作需求編寫函數;

**/
// 關鍵的驅動文件操作結構體

struct file_operations xxx_fops = {
    .owner = THIS_MODULE,
    .read = xxx_read,
    .write = xxx_write,
    .unlocked_ioctl= xxx_ioctl,

};

注意:(1)文件操作函數中從讀函數是從從內核空間讀到用戶空間讀數據,因此使用copy_to_user()函數,to 到用戶空間。

           (2)copy_from_user() 是把用戶空間的數據複製到內核空間,from。

            ( 3 ) 下面是字符設備的示意圖。

      (4)這個字符設備的模板是基本的字符設備、驅動的模板。一般的設備和驅動是以總線的形式來編寫的,例如虛擬總線,這個我們在下一次筆記中記錄學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章