字元裝置驅動 globalmem 宋寶華第6章

2021-09-18 01:13:21 字數 4994 閱讀 1641

1.在模組的載入中要實現裝置號的申請與cdev的註冊。

先用int register_chrdev_region(dev_t from, unsigned count, const char *name)或者int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)申請裝置號。

在第乙個函式register_chrdev_region中from是指希望申請的裝置號,count是希望申請的裝置號的數目,name是裝置名。

在第二個函式alloc_chrdev_region中,是動態申請裝置號,即自動分配系統空閒的裝置號。dev是裝置號位址,baseminor是申請的裝置的第乙個次裝置號,count是希望申請的裝置號的數目,name是裝置名。

核心中有cdev結構體,描述乙個字元裝置。結構體定義如下

struct cdev ;
習慣上,工程師為裝置定義乙個裝置相關的結構體(包含裝置涉及的cdev和私有資料和訊號量)

struct ***_dev_t ***_dev;
然後用初始化函式void cdev_init(struct cdev *cdev, const struct file_operations *fops)來初始化cdev的成員。

cdev的註冊是通過 int cdev_add(struct cdev *, dev_t, unsigned)向系統新增乙個cdev。

2.模組的解除安裝要實現裝置號的釋放和cdev的登出

若在模組載入函式中申請了裝置結構體內存則要釋放裝置結構體內存。

void cdev_del(struct cdev *)用來登出cdev。

void unregister_chrdev_region(dev_t from, unsigned count)用來釋放裝置號。

載入和解除安裝裝置驅動源**如下:

/* 初始化並註冊cdev */

static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)

/* 裝置驅動模組載入函式 */

int globalmem_init(void)

if (result < 0)

return result;

/* 動態申請裝置結構體的記憶體 */

globalmem_devp = kmalloc(sizeof(struct globalmem_dev), gfp_kernel);

if (!globalmem_devp)

memset (globalmem_devp, 0, sizeof(struct globalmem_dev));

globalmem_setup_cdev(globalmem_dev, 0);

return 0;

fail_malloc:

unregister_chrdev_region(devno, 1);

return result;

}/* 模組解除安裝函式 */

void globalmem_exit(void)

module_author("fourier");

module_license("dual bsd/gpl");

module_param(globalmem_major, int, s_irugo);

module_init(globalmem_init);

module_exit(globalmem_exit);

當載入裝置的時候(執行insmod globalmem.ko時),通過module_init來執行globalmem_init函式來載入裝置。

載入步驟:

1. 申請裝置號

2. 動態申請裝置結構體的記憶體 (包含了cdev結構體的記憶體)

3. 呼叫cdev_init來初始化cdev結構體,關聯file_operations檔案操作結構體

4. 向核心註冊cdev

當解除安裝裝置的時候(執行rmmod globalmem時),通過module_exit來執行globalmem_exit函式來解除安裝裝置。

解除安裝步驟:

1. 核心登出cdev

2. 釋放裝置結構體內存

3. 釋放裝置號

file_operations檔案操作結構體的成員是字元裝置驅動與核心的介面,是使用者對linux進行系統呼叫的最終落實者。
大多數字元裝置驅動會實現read()、write()、ioctl()函式。

函式的原型在核心中已經實現(返回值和傳參已經確定,只需填充就可以)

如以下實現open、release、read、ioctl函式

/* 檔案開啟函式 */

int globalmem_open(struct inode *inode, struct file *filp)

/* 檔案釋放函式 */

int globalmem_release(struct inode *inode, struct file *filp)

/* ioctl 裝置控制函式 */

static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)

return 0;

}/* 讀函式 */

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)

else

return ret;

}

以上函式通過file_operations檔案操作結構體與核心相聯絡。

/* 檔案操作結構體 */

static const struct file_operations globalmem_fops = ;

file_operations檔案操作結構體在初始化cdev結構體的時候與cdev相聯絡。

例如,當系統呼叫globalmem裝置的open時,核心找到該裝置結構體(即cdev結構體),進而找到該裝置的file_operations 結構體,進而再找到.open的globalmem_open函式。

#include #include #include #include #include #include #include #include #include #include #include #define globamem_size 0x1000

#define mem_clear 0x1

#define globalmem_major 250

static int globalmem_major = globalmem_major;

/* globalmem裝置結構體 */

struct globalmem_dev ;

struct globalmem_dev *globalmem_devp;

/* 檔案開啟函式 */

int globalmem_open(struct inode *inode, struct file *filp)

/* 檔案釋放函式 */

int globalmem_release(struct inode *inode, struct file *filp)

/* ioctl 裝置控制函式 */

static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)

return 0;

}/* 讀函式 */

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)

else

return ret;

}/* 檔案操作結構體 */

static const struct file_operations globalmem_fops = ;

/* 初始化並註冊cdev */

static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)

/* 裝置驅動模組載入函式 */

int globalmem_init(void)

if (result < 0)

return result;

/* 動態申請裝置結構體的記憶體 */

globalmem_devp = kmalloc(sizeof(struct globalmem_dev), gfp_kernel);

if (!globalmem_devp)

memset (globalmem_devp, 0, sizeof(struct globalmem_dev));

globalmem_setup_cdev(globalmem_dev, 0);

return 0;

fail_malloc:

unregister_chrdev_region(devno, 1);

return result;

}/* 模組解除安裝函式 */

void globalmem_exit(void)

module_author("fourier");

module_license("dual bsd/gpl");

module_param(globalmem_major, int, s_irugo);

module_init(globalmem_init);

module_exit(globalmem_exit);

字元裝置之globalmem

首先推薦一篇博文 然後寫寫我遇到的困難與收穫吧。1.make冒出來的第乙個錯誤就是找不到asm system.h檔案,因為在3.3.0之後的核心版本中asm system.h檔案被asm switch to.h檔案代替啦 啦啦啦。2.ioctl unlocked ioctl compat ioctl...

裝置驅動例項 字元裝置驅動

在整個linux裝置驅動學習中,字元裝置驅動較為基礎。通過對它的學習,對裝置驅動進一步加深了解 cdev 結構體struct cdev 講下比較重要的成員變數 dev t dev 定義了32位的裝置號,其中12位是主裝置號,20位是從裝置號。獲取主裝置號 major dev t dev 獲取從裝置號...

字元裝置驅動

字元裝置驅動 概述 塊裝置 字元裝置以及網路裝置中塊裝置和網路裝置一般都會硬體配置完備,對於程式設計師而言,能夠更多操作的就是字元裝置。設定字元裝置的一般步驟 1.初始化硬體 2.定義fops file operations 3.申請cdev,掛載fops 3.加入cdev 函式cdev add 主...