一、CDEV結構
|
二、file_operation 結構
|
三、為cdev申請內存
接下來,我們就需要為cdev申請內存,然后再通過cdev_init 函數將cdev與file_operation結構體聯系起來,
|
最后通過cdev_add函數,將cdev添加到內核中
|
四、實例解析
1.自定義一個cdev結構體
如圖所示,上述代碼中,先自定義一個簡單的cdev結構體key_dev,然后再實例化key_device, 接下來就定義一個我們接下來要操作的數組key_buff[MEM_SIZE],MEM_SIZE為自定義的內存的大小。
2.在init函數中初始化cdev結構體
當我們的應用程序調用open函數打開設備時,
在init函數中初始化cdev結構體,為cdev結構體開辟內存,連接cdev與fops結構體,注冊cdev進入內核
3.一旦注冊入內核,我們就可以開始使用了
當我們的應用程序打開設備時,在open函數中將filp的private_data賦值為我們所分配的key_device的結構體
4.釋放cdev內存
當我們不用驅動時自然就要釋放我們剛剛開辟的內存。
如圖所示,首先刪除cdev結構體,然后再使用kfree來釋放cdev釋放申請的內存
5.編譯與測試
如圖所示,我們在應用程序中先使用write函數往數組中寫入'hello,Lover雪兒'的字符串,然后再使用read函數讀取內容,但是,必須注意一點,在每次read后者write前,必須先使用lseek函數中重定位指針。
附上驅動程序源代碼:
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 14 #define DEVICE_NAME 'cdev' 15 #define Driver_NAME 'key_cdev' 16 17 #define KEY_MAJOR 220 18 #define KEY_MINOR 0 19 #define COMMAND1 1 20 #define COMMAND2 2 21 #define MEM_SIZE 256 22 23 struct key_dev { 24 struct cdev cdev; 25 }; 26 struct key_dev *key_device; 27 static unsigned char key_buff[MEM_SIZE]; 28 29 //auto to create device node 30 static struct class *drv_class = NULL; 31 static struct class_device *drv_class_dev = NULL; 32 33 static int key_open(struct inode *inode,struct file *filp){ 34 filp->private_data = key_device; 35 return 0; 36 } 37 38 static int key_release(struct inode* inode,struct file *filp){ 39 return 0; 40 } 41 42 static ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){ 43 ssize_t ret = 0; 44 loff_t pos = *f_pos; 45 if(pos > MEM_SIZE) //如果文件指針偏移超出文件大小 46 return ret = 0; 47 if(count > (MEM_SIZE - pos)) 48 count = 256 - pos; //若內存不足,則寫到內存滿的位置 49 pos += count; 50 //讀出數據 51 if(copy_to_user(buf,key_buff + *f_pos,count)){ 52 return ret = -EFAULT; 53 } 54 *f_pos = pos; 55 return count; 56 } 57 58 static ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){ 59 ssize_t ret = -ENOMEM; 60 loff_t pos = *f_pos; //獲取當前文件指針偏移 61 if(pos > MEM_SIZE) //如果文件指針偏移超出文件大小 62 return ret; 63 if(count > (MEM_SIZE - pos)) 64 count = 256 - pos; //若內存不足,則寫到內存滿的位置 65 pos += count; 66 //從fops處開始寫入數據 67 if(copy_from_user(key_buff + *f_pos,buf,count)){ 68 ret = -EFAULT; 69 return ret; 70 } 71 *f_pos = pos; 72 return count; 73 } 74 75 static int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ 76 switch(cmd){ 77 case COMMAND1: printk('<0>ncommand 1 n'); break; 78 case COMMAND2: printk('<0>ncommand 2 n'); break; 79 default: printk('<0>command default n'); break; 80 } 81 return 0; 82 } 83 84 static loff_t key_llseek(struct file *filp, loff_t off, int whence){ 85 loff_t pos; 86 pos = filp->f_pos; //獲取文件指針當前位置 87 switch(whence){ 88 case 0: pos = off; break; //重定位到文件開頭
上一篇:IMX257 Linux內存空間內存分配
下一篇:【改進定時器】IMX257實現GPIO-IRQ定時器消抖驅動程序
推薦閱讀最新更新時間:2025-06-08 23:01
設計資源 培訓 開發板 精華推薦
- 使用 IXYS 的 MX878R 的參考設計
- RT8010A 1.5MHz、1A、高效PWM降壓DC/DC轉換器的典型應用,適用于固定電壓調節器
- DN05053/D、NCP1129、12 瓦、離線降壓穩壓器設計說明
- OP113ESZ耳機放大器多媒體聲音編解碼器典型應用
- 麥克風聲控模塊
- HV257DB1,基于HV257的高壓采樣保持陣列演示板
- 【藍橋杯練習題二】第十三屆藍橋杯EDA賽模擬題
- 基于stm32與paj7620u2傳感器的手勢識別模塊
- AVR2037,使用ADXL335加速度計的按鍵遙控(Key Remote)板
- NSV45015WT1G 用于基本交流應用的恒流 LED 驅動器的典型應用