linux字符驱动之初见

转载 2015年11月18日 15:07:59

http://blog.csdn.net/lwj103862095/article/details/17468587

学习驱动也有长达一年多的时间了,受益最深的就是看韦东山老师的视频,如今已经几乎将二期三期的视频全部看完,甚至已经将二期视频看过好几遍,为了再次加深印象,我将韦老师的源码自己全部编写一遍。将所有遇到的问题,记录在此。觉得看了韦老师的视频,再看其他视频都是弱爆了。由于是文章记录,不可能写的非常详细,只摘录关键点,想具体详细的深入,还请去看韦老大的视频吧。

这篇文章是主要是讲解字符驱动的框架,并没有涉及高级字符驱动。

一、字符驱动框架

------------------------------------------------------------------------

APP:     open               read                   write

------------------------------------------------------------------------

C 库

------------------------------------------------------------------------

      system_open    system_read       system_write


------------------------------------------------------------------------

KERNEL:

      led_open           led_read               led_wirte

------------------------------------------------------------------------


问:应用程序open如何找到驱动程序的open函数

答:应用程序的open通过C库的open函数,通过系统调用的system_open函数,进而通过swi val指令,进入内核,通过一定的办法来找到驱动程序的open函数。

问:通过什么样的方法来找到驱动程序的open函数

答:通过一个注册函数+设备节点

注册函数如下(旧的注册函数,新的以后再说):

register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)

参数1:主设备号(重要)

参数2:名字(不重要)

参数3:file_operations结构体(重要)

设备节点:

可以手工创建也可以自动创建,这里暂且只说手工创建

mknod  /dev/xxx  c  252  0

具体什么含义,我就不多说了,看视频吧,很简单。


问:应用程序一般是由main函数开始执行,那么驱动程序一般是先执行什么?

答:通过一个宏,指定驱动程序的入口函数,当装载驱动时就会执行入口函数。

例如:module_init(first_drv_init);  //用于修饰入口函数

自然地,驱动程序的出口函数,则是在卸载驱动时就会执行出口函数。

例如:module_exit(first_drv_exit);  //用于修饰出口函数


驱动源程序如下:

  1. #include <linux/kernel.h>  
  2. #include <linux/fs.h>  
  3. #include <linux/init.h>  
  4. #include <linux/delay.h>  
  5. #include <asm/uaccess.h>  
  6. #include <asm/irq.h>  
  7. #include <asm/io.h>  
  8. #include <linux/module.h>  
  9.   
  10.   
  11. int major;  
  12. static int first_drv_open(struct inode * inode, struct file * filp)  
  13. {  
  14.     printk("first_drv_open\n");  
  15.     return 0;  
  16. }  
  17. static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)  
  18. {  
  19.     printk("first_drv_write\n");  
  20.     return 0;  
  21. }  
  22.   
  23. /* File operations struct for character device */  
  24. static const struct file_operations first_drv_fops = {  
  25.     .owner      = THIS_MODULE,  
  26.     .open       = first_drv_open,  
  27.     .write      = first_drv_write,  
  28. };  
  29.   
  30. /* 驱动入口函数 */  
  31. static int first_drv_init(void)  
  32. {  
  33.     /* 主设备号设置为0表示由系统自动分配主设备号 */  
  34.     major = register_chrdev(0, "first_drv", &first_drv_fops);  
  35.     return 0;  
  36. }  
  37.   
  38. /* 驱动出口函数 */  
  39. static void first_drv_exit(void)  
  40. {  
  41.     unregister_chrdev(major, "first_drv");  
  42. }  
  43.   
  44. module_init(first_drv_init);  //用于修饰入口函数  
  45. module_exit(first_drv_exit);  //用于修饰出口函数      
  46.   
  47. MODULE_AUTHOR("LWJ");  
  48. MODULE_DESCRIPTION("Just for Demon");  
  49. MODULE_LICENSE("GPL");  //遵循GPL协议  

Makefile源码如下:

  1. ifneq ($(KERNELRELEASE),)  
  2.   
  3. obj-m := first_drv.o  
  4.   
  5. else  
  6.       
  7. KDIR := /home/opt/EmbedSky/linux-2.6.30.4  
  8.   
  9. all:  
  10.     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-  
  11. clean:  
  12.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  
  13.   
  14. endif  

测试程序如下:

  1. #include <stdio.h>  
  2. #include <sys/types.h>  
  3. #include <sys/stat.h>  
  4. #include <fcntl.h>  
  5. #include <unistd.h>  
  6.   
  7. int main(void)  
  8.   
  9. {  
  10.     int fd;  
  11.     int val = 1;  
  12.     fd = open("/dev/xxx",O_RDWR);  
  13.     if(fd < 0)  
  14.     {  
  15.         printf("open error\n");  
  16.     }  
  17.       
  18.     write(fd,&val,4);  
  19.       
  20.     return 0;  
  21. }  

开发板上的测试步骤如下:

  1. [WJ2440]# insmod first_drv.ko   
  2. [WJ2440]# ./first_test   
  3. open error  
  4. [WJ2440]# cat proc/devices   
  5. Character devices:  
  6.   1 mem  
  7.   4 /dev/vc/0  
  8.   4 tty  
  9.   5 /dev/tty  
  10.   5 /dev/console  
  11.   5 /dev/ptmx  
  12.   7 vcs  
  13.  10 misc  
  14.  13 input  
  15.  14 sound  
  16.  29 fb  
  17.  81 video4linux  
  18.  89 i2c  
  19.  90 mtd  
  20. 116 alsa  
  21. 128 ptm  
  22. 136 pts  
  23. 180 usb  
  24. 188 ttyUSB  
  25. 189 usb_device  
  26. 204 tq2440_serial  
  27. <span style="color:#ff0000;">252 first_drv</span>  
  28. 253 usb_endpoint  
  29. 254 rtc  
  30.   
  31. Block devices:  
  32. 259 blkext  
  33.   7 loop  
  34.   8 sd  
  35.  31 mtdblock  
  36.  65 sd  
  37.  66 sd  
  38.  67 sd  
  39.  68 sd  
  40.  69 sd  
  41.  70 sd  
  42.  71 sd  
  43. 128 sd  
  44. 129 sd  
  45. 130 sd  
  46. 131 sd  
  47. 132 sd  
  48. 133 sd  
  49. 134 sd  
  50. 135 sd  
  51. 179 mmc  
  52. [WJ2440]# mknod /dev/xxx c 252 0  
  53. [WJ2440]# ls -l /dev/xxx   
  54. crw-r--r--    1 root     root      252,   0 Jan  1 20:49 /dev/xxx  
  55. [WJ2440]# ./first_test   
  56. first_drv_open  
  57. first_drv_write  
  58. [WJ2440]#   

驱动环境的搭建详情请参考:

http://blog.csdn.net/lwj103862095/article/details/17465835


相关文章推荐

linux 字符设备驱动-led

  • 2017年07月25日 15:07
  • 6KB
  • 下载

Linux驱动之字符设备的简单分析

Linux驱动之字符设备的简单分析及函数实现
  • ljmiaw
  • ljmiaw
  • 2017年07月16日 21:23
  • 170

Linux字符设备驱动程序分析与设计

  • 2015年06月08日 11:33
  • 1.86MB
  • 下载

Linux字符设备驱动LED源码

  • 2016年12月30日 15:25
  • 87KB
  • 下载

“手把手教你学linux驱动开发”OK6410系列之02---虚拟字符设备

上一篇文章我们介绍了如何在linux下编写一个模块,并加载到内核空间。通过实验我们了解了大体的流程以及模块的工作原理。本篇文章我们将介绍如何编写一个虚拟的字符设备驱动程序。        之所以称之...

linux字符设备驱动模型

  • 2014年03月26日 23:16
  • 3KB
  • 下载

linux下简单字符设备驱动

  • 2014年04月07日 22:27
  • 3KB
  • 下载

LINUX字符设备驱动程序实例

我是通过UBUNTU10.10测试该驱动程序的,系统内核为linux-2.6.35-22(可使用uname -r 命令来查看当前内核的版本号) 下载安装LINUX内核,需要下载和本机一样版本的内核源...

linux字符设备驱动

  • 2012年02月17日 19:13
  • 29KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux字符驱动之初见
举报原因:
原因补充:

(最多只允许输入30个字)