歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

【Linux 驅動】設備驅動程序再理解

學習設備驅動編程也有一段時間了,也寫過了幾個驅動程序,因此有對設備驅動程序有了一些新的理解和認識,總結一下。學習設備驅動編程也有一段時間了,也寫過了幾個驅動程序,因此有對設備驅動程序有了一些新的理解和認識,總結一下。

★什麼是驅動程序

剛開始學習設備驅動程序的時候,產生了許多的問題。什麼是驅動程序?驅動程序是干嘛的?它是如何工作的?它又是如何跟操作系統聯系起來的?一系列的問題,現在有些地方還是不一定清楚,但是相比起剛開始的那個階段,感覺自己還是清楚了很多。

設備驅動程序說白了(實質)就是為應用程序提供一組操作硬件設備的接口。驅動程序是可以直接操作硬件上的資源,例如GPIO的各個寄存器,從而控制GPIO的方向(輸出或是輸入)、引腳的電平高低、中斷等等。驅動程序所做的事情大部分與直接在51單片機或是AVR單片機寫的程序的功能相似,與它們不同的是驅動程序向上是為操作系統提供統一的接口的。

字符設備驅動控制LED燈  http://www.linuxidc.com/Linux/2014-03/97757.htm

Linux下PCI設備驅動程序之注冊詳解 http://www.linuxidc.com/Linux/2014-02/97074.htm

裸機驅動與Linux設備驅動的區別 http://www.linuxidc.com/Linux/2013-08/88799.htm

Linux設備驅動開發詳解(第2版)源代碼 下載 http://www.linuxidc.com/Linux/2013-07/86977.htm

Linux設備驅動開發詳解(第2版)高清PDF http://www.linuxidc.com/Linux/2013-07/86976.htm

★file_operations結構體

驅動設備有很多種,那麼驅動它們的程序也會各有不同,那麼驅動程序怎樣向上提供統一的接口呢?最關鍵的就是這個結構體,它定義在include/linux/fs.h文件中

struct file_operations {
 struct module *owner;
 loff_t (*llseek) (struct file *, loff_t, int);
 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
 int (*readdir) (struct file *, void *, filldir_t);
 unsigned int (*poll) (struct file *, struct poll_table_struct *);
 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
 long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
 int (*mmap) (struct file *, struct vm_area_struct *);
 int (*open) (struct inode *, struct file *);
 int (*flush) (struct file *, fl_owner_t id);
 int (*release) (struct inode *, struct file *);
 int (*fsync) (struct file *, struct dentry *, int datasync);
 int (*aio_fsync) (struct kiocb *, int datasync);
 int (*fasync) (int, struct file *, int);
 int (*lock) (struct file *, int, struct file_lock *);
 ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 int (*check_flags)(int);
 int (*dir_notify)(struct file *filp, unsigned long arg);
 int (*flock) (struct file *, int, struct file_lock *);
 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
};

通過這個結構體將驅動程序中操作硬件資源的函數鏈接起來。那麼當操作系統知道了這個結構體之後,也就是知道了這個驅動程序。那麼操作系統如何知道這個結構體呢?

其實,Linux下設備大概可以分為兩種:字符設備、塊設備。內核中用2個全局變量存放這兩類驅動程序:

字符設備重要的結構體:

static struct char_device_struct {
 struct char_device_struct *next;
 unsigned int major;
 unsigned int baseminor;
 int minorct;
 char name[64];
 struct file_operations *fops;
 struct cdev *cdev;  /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];

當驅動程序調用register_chrdev(unsigned int major, const char * name, struct file_operations *fops)注冊函數就是將file_operations結構體存放到數組chrdevs[CHRDEV_MAJOR_HASH_SIZE]數組中,數組下標就是驅動主設備號,這樣驅動程序就能和內核有了關聯。

★設備文件

設備節點有什麼用呢?我們知道在Liunx下,設備都是以文件的形式存在的。驅動程序運行在內核中,應用程序訪問驅動程序是通過系統利用系統函數訪問設備文件。因此文件系統中一定要有一個設備文件與你的設備驅動程序相對應,這樣應用程序才能訪問你的設備驅動程序。

設備文件一般放在/dev目錄下面,你可以通過ls 命令查看。怎樣創建設備文件節點呢?

可以使用mknod命令,例如我要創建一個主設備號為103,次設備號為0的字符設備文件,則可以輸入:mknod /dev/XXX c 103 0 其中/dev/XXX中的XXX表示設備文件的名稱

Copyright © Linux教程網 All Rights Reserved