注: 參考整理自《Linux設備驅動開發詳解》下載見 http://www.linuxidc.com/Linux/2011-07/38211.htm
一 Linux 內核模塊 :
1. 查找系統中加載的模塊: lsmod ; 卸載模塊命令 : rmmod ; 裝載命令: insmod/modprobe(modprobe 會自動分析模塊間的依賴關系);
2. 模塊加載函數:利用__init 標識
static int __init ***_init(void)
{
................
}
module_init(***_init);
返回0表示加載成功, 失敗則返回一些錯誤代碼,參考<linux/errno.h>
在加載函數中一般用於初始化硬件,申請資源.....
3. 模塊卸載函數:利用__exit標識
static void __exit ***_exit(void)
{
.............
}
module_exit(***_exit);
注: 在卸載模塊的函數中,一般需要完成以下的幾件事情:
# 若模塊加載函數中注冊了***,則在模塊卸載函數中需注銷;
# 若在模塊加載函數中動態申請了內存,則在此亦需要釋放;
# 若在模塊加載中申請了一些硬件資源(如:IRQ, DMA channel, I/O ,memory),則在此需釋放;
4. 模塊參數 : module_param(參數名, 參數類型, 參數讀/寫權限)
注: 可以利用上述的方法在加載模塊時傳遞需要的參數。
5. 導出符號 : 記錄了該符號以及該符號所在的內存地址。
可以使用:
EXPORT_SYMBOL(符號名);
EXPORT_SYMBOL_GPL(符號名);
該功能在內核中使用較多,只要導出該符號,則其他的模塊在調用該符號時,只需聲明則可;這有點類似於跨文件的函數間調用。
6. 模塊聲明與描述:
MODULE_AUTHOR(author);
MODULE_DESCRIPTION(description);
MODULE_VERSION(version_string);
MODULE_DEVICE_TABLE(table_info);
MODULE_ALIAS(alternate_name);
7. 模塊的編譯 :
下面演示一個 Makefile :
#Makefile for wm8350_rtc
obj-m := wm8350_rtc.o
all:
make -C ../../../linux-2.6.26 M=`pwd` modules
clean:
make -C ../../../linux-2.6.26 M=`pwd` clean
rm -f modules.orde
分析: -C 表示Linux內核所在的目錄,需注意的是,這個目錄是之前設置好的用來編譯zImage的源碼;
M 表示指定的需要編譯成模塊的代碼源文件和Makefile 文件;
modules ----表示編譯為內核模塊。
二, Linux文件系統:
1. C中的文件操作: open , write, read, close,
2.在Linux的驅動開發中,需要關注的是如下兩個結構:
1) file_operations :應用程序和 VFS(virtual FS)之間通過系統調用鏈接,而VFS 和普通設備之間則通過file_operation的成員函數(如: read ,write, open ,close ,ioctl ...)
file 結構體 :參考: /linux/include/linux/fs.h:
- struct file {
- /*
- * fu_list becomes invalid after file_free is called and queued via
- * fu_rcuhead for RCU freeing
- */
- union {
- struct list_head fu_list;
- struct rcu_head fu_rcuhead;
- } f_u;
- struct path f_path;
- #define f_dentry f_path.dentry
- #define f_vfsmnt f_path.mnt
- const struct file_operations *f_op;
- atomic_t f_count;
- unsigned int f_flags;
- mode_t f_mode;
- loff_t f_pos;
- struct fown_struct f_owner;
- unsigned int f_uid, f_gid;
- struct file_ra_state f_ra;
-
- u64 f_version;
- #ifdef CONFIG_SECURITY
- void *f_security;
- #endif
- /* needed for tty driver, and maybe others */
- void *private_data;
-
- #ifdef CONFIG_EPOLL
- /* Used by fs/eventpoll.c to link all the hooks to this file */
- struct list_head f_ep_links;
- spinlock_t f_ep_lock;
- #endif /* #ifdef CONFIG_EPOLL */
- struct address_space *f_mapping;
- #ifdef CONFIG_DEBUG_WRITECOUNT
- unsigned long f_mnt_write_state;
- #endif
- };
另外可以參考一下 file_operation 的描述:
- 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 (*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);
- int (*setlease)(struct file *, long, struct file_lock **);
- }
2) inode : 包括文件訪問權限,屬主,組,大小,生成時間,訪問時間,最後修改時間等...
inode的結構體定義也是在include/linux/fs.h
3. ps: 可以使用 cat /proc/devices 查詢系統中注冊的設備。
三, sysfs --- Linux驅動開發使用得較多,尤其是需要顯示一些設備的信息時,而且Android中,sysfs的使用也很多。
1. 目的: sysfs 顯示設備驅動模型中各個模塊間的層次關系: ls /sys ---可以看到其頂級目錄 包括 :
block bus class devices firmware module power
其中: block ----顯示塊設備;
bus ----顯示系統中所有的總線;
class ----顯示系統中的設備類型;
device --顯示系統中所有的設備並根據設備掛接的總線類型組織成層次關系;
drivers ---包括內核中所有已注冊的設備驅動程序;