(五)Linux之设备驱动模型
目錄
- (一)Linux內(nèi)核驅(qū)動簡介
- (二)雜項設備驅(qū)動模型
- (1)相關接口
- (2)雜項設備注冊過程
- (三)早期經(jīng)典字符設備驅(qū)動模型
- (1)相關接口
- (2)雜項設備注冊過程
- (二)雜項和早期經(jīng)典的區(qū)別
(一)Linux內(nèi)核驅(qū)動簡介
對于剛接觸linux驅(qū)動的同學來說,應該思考一個問題就是為什么要有Linux內(nèi)核驅(qū)動呢?原因就是Linux內(nèi)核對設備的驅(qū)動編寫進行了規(guī)范。
我們在linux系統(tǒng)的/dev目錄下可以查看設備節(jié)點文件,這些節(jié)點文件是怎么存在的也是值得思考的,本篇文章將會講解一個雜項設備驅(qū)動模型、早期經(jīng)典字符設備驅(qū)動模型,都是針對字符設備進行講解的。
通過ls選項看到,文件權限前面的符號表示該文件是字符設備文件、塊設備文件或者其他的,每一個設備文件都有一個主設備號和一個次設備號
驅(qū)動程序為程序員開發(fā)后放入內(nèi)核的功能模塊,所以驅(qū)動程序本身不屬于內(nèi)核的一部分,導致在向內(nèi)核添加驅(qū)動功能的時候需要向內(nèi)核提出申請,即注冊操作。
(二)雜項設備驅(qū)動模型
雜項設備:主設備號固定為10 的設備稱為在下個設備,Linux驅(qū)動中把無法歸類的五花八門的設備定義為混雜設備(用miscdevice結構體表述)。miscdevice共享一個主設備號MISC_MAJOR(即10),但次設備號不同。
(1)相關接口
int misc_register(struct miscdevice * misc)
int:返回值,成功返回0,失敗返回負數(shù) struct miscdevice * misc:設備結構體struct miscdevice {int minor; //次設備號 // 當minor的值為255的時候內(nèi)核會自動分配次設備號,// 一般采用此方法,因為自己指定容易和已有的次設備號沖突 const char *name; //設備節(jié)點名 const struct file_operations *fops;//文件操作指針結構體struct list_head list; //雜項設備鏈表,使用者不用關心struct device *parent; //父設備類,無需關心struct device *this_device; //本設備,無需關心const char *nodename; //節(jié)點名umode_t mode; //權限};注冊雜項設備需要關心的參數(shù):
int minor; //次設備號
const char *name; //設備節(jié)點名
const struct file_operations *fops;//文件操作指針結構體
struct file_operations結構體如下:
struct file_operations {struct module *owner; //一般賦值為THIS_MODULEloff_t (*llseek) (struct file *, loff_t, int);/*ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);char __user *:內(nèi)核空間讀取到文件中的數(shù)據(jù),直接傳遞到用戶空間調(diào)用的read接口中ssize_t read(int fd, void *buf, size_t count);buf中的數(shù)據(jù)即來源于 char __user **//*ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);const char __user *:用戶層調(diào)用的write接口向文件寫入的數(shù)據(jù)ssize_t write(int fd, const void *buf, size_t count);buf中的數(shù)據(jù)直接傳遞到了const char __user *size_t:數(shù)據(jù)的大小loff_t *指的是寫入數(shù)據(jù)的偏移量 */unsigned int (*poll) (struct file *, struct poll_table_struct *);long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);int (*open) (struct inode *, struct file *);int (*release) (struct inode *, struct file *);//內(nèi)核中的release等同于系統(tǒng)的closeint (*fsync) (struct file *, loff_t, loff_t, int datasync);int (*fasync) (int, struct file *, int);int (*lock) (struct file *, int, struct file_lock *); }; 以int (*open) (struct inode *, struct file *);為例: open指針指向的函數(shù)是用來接收系統(tǒng)層調(diào)用的open函數(shù)所傳遞的參數(shù)值 struct inode *:保存文件屬性的 struct file *:保存文件操作中的數(shù)據(jù)(2)雜項設備注冊過程
下面以一個例子講解,重點看注冊函數(shù)misc_register:
miscdevice.c
以上注冊和注銷都依賴于模塊化編程,不懂的可以參考:Linux內(nèi)核模塊化編程
編寫系統(tǒng)調(diào)用函數(shù)
misc_app.c
Makfile
CFLAG = -C TARGET = miscdevice APP=misc_app KERNEL = /mydriver/linux-3.5 obj-m +=$(TARGET).oall:make $(CFLAG) $(KERNEL) M=$(PWD)arm-linux-gcc -o $(APP) $(APP).c clean:make $(CFLAG) $(KERNEL) M=$(PWD) cleanrm $(APP)使用交叉編譯器編譯msic_app.c后,并且剛剛編寫的miscdevice.c編譯成模塊后
啟動tiny4412開發(fā)板查看
注意:
- 1、注冊成功會在根文件系統(tǒng)的dev目錄下產(chǎn)生一個指定的節(jié)點文件
- 2、設備驅(qū)動模型中的接口(文件操作接口)只有上層接口調(diào)用的時候才會有效果
- 3、操作驅(qū)動模型對應的設備只需序打開該設備對應的節(jié)點文件名
(三)早期經(jīng)典字符設備驅(qū)動模型
(1)相關接口
int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops) {return __register_chrdev(major, 0, 256, name, fops); }* @major: major device number or 0 for dynamic allocation* 主設備號或者0用來自動分配 * @baseminor: first of the requested range of minor numbers 默認為0 * 申請設備號的起始次設備號,在此處默認為0 * @count: the number of minor numbers required * 申請次設備號的個數(shù) * @name: name of this range of devices * 申請設備號對應的設備名 * @fops: file operations associated with this devices * 文件操作結構體static inline void unregister_chrdev(unsigned int major, const char *name)
static inline void unregister_chrdev(unsigned int major, const char *name) {__unregister_chrdev(major, 0, 256, name); }(2)雜項設備注冊過程
下面以例子進行講解,重點看注冊函數(shù)register_chrdev:
char_device.c: #include <linux/kernel.h> #include <linux/module.h> #include <linux/fs.h> int major =0; ssize_t chr_read (struct file * fp, char __user * buf, size_t size, loff_t * offset ) {printk(" this is read\n");return 0; } ssize_t chr_write (struct file * fp, char __user * buf, size_t size, loff_t * offset ) {printk(" this is write\n");return 0; } int chr_close (struct inode * node , struct file * file ) {printk(" this is close\n");return 0; } int chr_open (struct inode * node , struct file * file) {printk(" this is open\n");return 0; } struct file_operations fp={.read =chr_read, .write =chr_write,.release =chr_close,.open =chr_open, }; static int __init chardev_init(void) {major = register_chrdev(0, "ming", &fp);printk("this is module init,major =%d\n",major);return 0; } static void __exit chardev_cleanup(void) {unregister_chrdev(major,"ming");printk("this is module exit\n"); } module_init(chardev_init); module_exit(chardev_cleanup); MODULE_LICENSE("GPL");關于測試函數(shù)同雜項設備的misc_app.c和Makefile,在此不重復寫了,下面看現(xiàn)象
(二)雜項和早期經(jīng)典的區(qū)別
- 1、雜項設備的主設備號固定位10,,早期經(jīng)典設備的主設備號是0-255除10外
- 2、雜項設備的一個設備對應一個次設備號,而早期經(jīng)典的模型中,一旦申請成功,則該主設備號下的所有次設備號均對應一個設備,次設備號的范圍為0-255
本文章僅供學習交流用禁止用作商業(yè)用途,文中內(nèi)容來水枂編輯,如需轉(zhuǎn)載請告知,謝謝合作
微信公眾號:zhjj0729
微博:文藝to青年
總結
以上是生活随笔為你收集整理的(五)Linux之设备驱动模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 债券发行价格的计算公式 发行债券的形式
- 下一篇: 护理专科男生当兵在部队能考资格证吗?