開始從頭學起linux 設備驅動,當然是先從字符驅動看起。
相關閱讀:Linux 設備驅動 ====> 並發控制 --- 原子操作 http://www.linuxidc.com/Linux/2012-03/57580.htm
下面仿照著書上的例子,寫了一個misc 字符驅動。
- [email protected]:/home/jay/globalmem# tree globalmem/
- globalmem/
- ├── globalmem.c
- └── Makefile
首先咱來看下Makefile, 其實這東西都一個模子,
- KVERS = $(shell uname -r)
-
- obj-m += globalmem.o
-
- build: kernel_modules
-
- kernel_modules:
- make -C /lib/modules/$(KVERS)/build/ M=$(CURDIR) modules
-
- clean:
- make -C /lib/modules/$(KVERS)/build/ M=$(CURDIR) clean
然後是我們的驅動文件globalmem.c,我們從init函數看起
- int globalmem_init(void)
- {
- int result;
- globalmem_devp = kmalloc(sizeof(struct globalmem_dev) ,GFP_KERNEL);
- if(!globalmem_devp) {
- result = -ENOMEM;
- goto fail_malloc;
- }
- memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
-
- globalmem_devp->mdev = mdev_struct;
-
- result = misc_register(&(globalmem_devp->mdev));
- if(result<0)
- return result;
- else
- return 0;
-
- fail_malloc:
- return result;
- }
首先是給我們的全局指針變量分配內存
- globalmem_devp = kmalloc(sizeof(struct globalmem_dev) ,GFP_KERNEL);
- if(!globalmem_devp) {
- result = -ENOMEM;
- goto fail_malloc;
- }
- memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
看下這個指針的定義
- struct globalmem_dev {
- struct miscdevice mdev;
- unsigned char mem[GLOBALMEM_SIZE];
- };
-
- struct globalmem_dev *globalmem_devp;
globalmem_dev結構體中內嵌了一個miscdevice結構體,這個結構體就是描述我們的misc字符驅動的結構體,若想注冊一個misc 字符設備就必須包含有這樣一個結構體,
- struct miscdevice {
- int minor;
- const char *name;
- const struct file_operations *fops;
- struct list_head list;
- struct device *parent;
- struct device *this_device;
- };
這個結構體描述了這個驅動的信息,包含次設備號, 文件操作結構體,驅動名稱等。
內存分配結束之後是調用misc_register來注冊我們的misc驅動,使用misc字符驅動相對於標准的字符驅動寫起來簡單。
然後是exit函數,跟init相反:
- void globalmem_exit(void)
- {
- misc_deregister(&(globalmem_devp->mdev));
- if(globalmem_devp)
- kfree(globalmem_devp);
- }
-
- module_init(globalmem_init);
- module_exit(globalmem_exit);
千萬別忘了最後要釋放我們分配的內存。
然後使我們的miscdevice和fops結構體
- static const struct file_operations globalmem_fops = {
- .owner = THIS_MODULE,
- .open = globalmem_open,
- .release = globalmem_release,
- .unlocked_ioctl = globalmem_ioctl,
- .read = globalmem_read,
- .write = globalmem_write,
- };
-
- static struct miscdevice mdev_struct = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = "globalmem",
- .fops = &globalmem_fops,
- };
這裡主要是這個file_operations接頭體的定義,這裡主要是把這個結構體中我們想要實現的讀,寫等方法與對應的回調函數掛鉤起來。