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

Linux 設備驅動 ====> 字符驅動

開始從頭學起linux 設備驅動,當然是先從字符驅動看起。

相關閱讀:Linux 設備驅動 ====> 並發控制 --- 原子操作 http://www.linuxidc.com/Linux/2012-03/57580.htm

下面仿照著書上的例子,寫了一個misc 字符驅動。

  1. [email protected]:/home/jay/globalmem# tree globalmem/  
  2. globalmem/  
  3. ├── globalmem.c  
  4. └── Makefile  
首先咱來看下Makefile, 其實這東西都一個模子,
  1. KVERS   =   $(shell uname -r)  
  2.   
  3. obj-m   +=  globalmem.o  
  4.   
  5. build:  kernel_modules  
  6.   
  7. kernel_modules:  
  8.     make -C /lib/modules/$(KVERS)/build/ M=$(CURDIR) modules  
  9.   
  10. clean:  
  11.     make -C /lib/modules/$(KVERS)/build/ M=$(CURDIR) clean  
然後是我們的驅動文件globalmem.c,我們從init函數看起
  1. int globalmem_init(void)  
  2. {  
  3.     int result;  
  4.     globalmem_devp = kmalloc(sizeof(struct globalmem_dev) ,GFP_KERNEL);  
  5.     if(!globalmem_devp) {  
  6.         result = -ENOMEM;  
  7.         goto fail_malloc;  
  8.     }  
  9.     memset(globalmem_devp, 0, sizeof(struct globalmem_dev));  
  10.       
  11.     globalmem_devp->mdev = mdev_struct;  
  12.   
  13.     result = misc_register(&(globalmem_devp->mdev));  
  14.     if(result<0)  
  15.         return result;  
  16.     else  
  17.         return 0;  
  18.   
  19. fail_malloc:  
  20.     return result;  
  21. }  
首先是給我們的全局指針變量分配內存
  1. globalmem_devp = kmalloc(sizeof(struct globalmem_dev) ,GFP_KERNEL);  
  2. if(!globalmem_devp) {  
  3.     result = -ENOMEM;  
  4.     goto fail_malloc;  
  5. }  
  6. memset(globalmem_devp, 0, sizeof(struct globalmem_dev));  
看下這個指針的定義
  1. struct globalmem_dev {  
  2.     struct miscdevice mdev;  
  3.     unsigned char mem[GLOBALMEM_SIZE];  
  4. };  
  5.   
  6. struct globalmem_dev *globalmem_devp;  
globalmem_dev結構體中內嵌了一個miscdevice結構體,這個結構體就是描述我們的misc字符驅動的結構體,若想注冊一個misc 字符設備就必須包含有這樣一個結構體,
  1. struct miscdevice  {  
  2.     int minor;  
  3.     const char *name;  
  4.     const struct file_operations *fops;  
  5.     struct list_head list;  
  6.     struct device *parent;  
  7.     struct device *this_device;  
  8. };  
這個結構體描述了這個驅動的信息,包含次設備號, 文件操作結構體,驅動名稱等。

內存分配結束之後是調用misc_register來注冊我們的misc驅動,使用misc字符驅動相對於標准的字符驅動寫起來簡單。

然後是exit函數,跟init相反:

  1. void globalmem_exit(void)  
  2. {  
  3.     misc_deregister(&(globalmem_devp->mdev));  
  4.     if(globalmem_devp)  
  5.         kfree(globalmem_devp);  
  6. }  
  7.   
  8. module_init(globalmem_init);  
  9. module_exit(globalmem_exit);  
千萬別忘了最後要釋放我們分配的內存。

然後使我們的miscdevice和fops結構體

  1. static const struct file_operations globalmem_fops = {  
  2.     .owner = THIS_MODULE,  
  3.     .open = globalmem_open,  
  4.     .release = globalmem_release,  
  5.     .unlocked_ioctl = globalmem_ioctl,  
  6.     .read = globalmem_read,  
  7.     .write = globalmem_write,  
  8. };  
  9.   
  10. static struct miscdevice mdev_struct = {  
  11.     .minor = MISC_DYNAMIC_MINOR,  
  12.     .name = "globalmem",  
  13.     .fops = &globalmem_fops,  
  14. };  
這裡主要是這個file_operations接頭體的定義,這裡主要是把這個結構體中我們想要實現的讀,寫等方法與對應的回調函數掛鉤起來。
Copyright © Linux教程網 All Rights Reserved