應用程式觀點:
應用程式透過一組標準化的呼叫就可以來間接操作硬體
ex: open("/dev/Lucky1", ....) , read(), write() ioctl()
Example:
strace cat /dev/input/mice
(strace可以看到system call)
===============================================
Device Driver扮演的角色:
以實際的硬體動作來實現"系統呼叫"所定義的功能
模組化:驅動程式跟核心分開製作, 且再有需要時, 才在執行期將驅動程式"insert"到核心裡
===============================================
機制 Mechanism & 法則 Policy
機制:要提供甚麼能力?
法則:如何只用這個能力?
留下 How to use it?(Policy) 的問題給application
Policy-free的驅動程式, 盡量徹底發揮硬體能力(Sync, Async, Multiple opened, ....)
===============================================
分類:
Character Device
有device node
"Direct Data Channel" to H/W
Device node可以直接被讀寫
ex: /dev/tty1
Block Device
有device node
Transfer Blocks data => 可以適合拿來high speed H/W
"No Direct channel"所以不可以直接access
ex: /dev/sda 要以File System來存取
Network Interface
沒有device node
沒有read/write operation,使用packet transmission fuction
系統會自行負責packet
===============================================
來掛載最簡單的Driver吧~
-----------------------------------------------------------------------------------------------------
hello.c
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Lucky Chang");
static char* name="Quanta";
module_param(name, charp, 0);
static int __init hello_init(void) {
printk(KERN_ALERT "Hello, %s\n",name);
return 0;
}
static void __exit hello_exit(void) {
printk(KERN_ALERT "Bye\n");
}
module_init(hello_init);
module_exit(hello_exit);
-----------------------------------------------------------------------------------------------------
P.S.
function前面加static?
此function只有此file看的到 (OOP的 private 觀念)
__init ?
讓kernel知道該函式僅用於初始期間, 當module被順利載入, 模組裝載器會丟掉初始函式, 將記憶體空出來做其他用途
__exit ?
讓kernel知道該函式僅用於卸載期間, 如果這個模組要直接嵌在核心裡, 或核心設定不容許卸載, 則標示__exit的函式就可以丟掉了
printk() ?
當執行到driver時, 以進入kernel mode, 並無法使用標準C函式庫的library
printk()函式定義在Linux核心內, 再沒有C函式庫的協助下, 自己執行自己
KERN_ALERT代表訊息優先度
寫Driver一定會用到的Macros
module_init( init_func );
module_exit( clean_func );
module_param(name, type, perm)
type: byte, short, ushort, int, uint, long, ulong, charp, bool
ex:
static char* name="Quanta"
module_param(name, charp, 0:
static int address=0;
module_param(address, int, 0);
EXPORT_SYMBOL( name ); //加到kernel Symbol Table, 以後其他Driver or 誰就可以用到了
MODULE_LICENSE()
MODULE_AUTHOR( name ) //才能把自己的名字藏進去啊
Makefile
-----------------------------------------------------------------------------------------------------
# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g # "-O" is needed to expand inlines
else
DEBFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS) -I$(LDDINCDIR)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
obj-m := hello.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINCDIR=$(PWD)/../include modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif
-----------------------------------------------------------------------------------------------------
如何執行?
make
modinfo hello.ko
insmod hello.ko name="Lucky"
dmesg
rmmod hello
dmesg
加新功能 多一個數字參數
insmod hello.ko name="Lucky" count=5
===============================================
1 則留言:
小中中好帥!!!
張貼留言