歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux 設備驅動 ====> 字符驅動

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

日期:2017/3/1 10:25:38   编辑: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. obj-m += globalmem.o
  3. build: kernel_modules
  4. kernel_modules:
  5. make -C /lib/modules/$(KVERS)/build/ M=$(CURDIR) modules
  6. clean:
  7. 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. globalmem_devp->mdev = mdev_struct;
  11. result = misc_register(&(globalmem_devp->mdev));
  12. if(result<0)
  13. return result;
  14. else
  15. return 0;
  16. fail_malloc:
  17. return result;
  18. }
首先是給我們的全局指針變量分配內存
  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. 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. module_init(globalmem_init);
  8. 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. static struct miscdevice mdev_struct = {
  10. .minor = MISC_DYNAMIC_MINOR,
  11. .name = "globalmem",
  12. .fops = &globalmem_fops,
  13. };
這裡主要是這個file_operations接頭體的定義,這裡主要是把這個結構體中我們想要實現的讀,寫等方法與對應的回調函數掛鉤起來。
Copyright © Linux教程網 All Rights Reserved