【linux驱动】linux驱动总览

时间:2021-11-24 17:19:06

欢迎转载,转载时需保留作者信息,谢谢。

邮箱:tangzhongp@163.com

博客园地址:http://www.cnblogs.com/embedded-tzp

Csdn博客地址:http://blog.csdn.net/xiayulewa

 

1.1.  应用,设备,总线,驱动关系,应用到驱动

【linux驱动】linux驱动总览

为了简化问题,上图省略了app层与driver层中间的libc层。

linux驱动的开发步骤:设备号→设备(struct cdev,struct input_dev等)→驱动(struct file_operations)→应用层接口(创建/dev)

 

linux应用的open最终调用驱动struct file_operations的open,依次类推。

 

设备节点:

即/dev目录下面的设备,当驱动层申请设备号后,通过cat  /proc/devices 可以查询到申请设备的主次设备号。然后管理员可以手动去创建该设备,命令形式为:mknod -m 777 /dev/buttons c 249 0

以linux下的/dev/fb0设备节点为例:

 

tang@tang-vm ~ $ cat  /proc/devices

Character devices:

...

29 fb

...

 

可见其主设备号为29.

tang@tang-vm ~ $ ls /dev/fb0 -l

crw-rw---- 1 root video 29, 0  4月 14 00:01 /dev/fb0

 

设备节点/dev/fb0主设备号与cat  /proc/devices得到的一致。

 

1.1.1.   方案1,手动创建设备节点

 
 

       alloc_chrdev_region(&dev, 0, 1, "buttons"):动态设备号

       register_chrdev_region:静态设备号

       register_chrdev

 

 

 

 

 

 

 
  【linux驱动】linux驱动总览

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.1.2.   方案2,自动创建设备节点

 

       
   

alloc_chrdev_region(&dev, 0, 1, "buttons"):动态设备号

register_chrdev_region:静态设备号

cls = class_create(THIS_MODULE, "leds-atomic"); //

device_create(cls, NULL, dev, NULL, "myled");//dev/myled

 

 
 

在应用中使用 fd = open("/dev/myled", O_RDWR);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.1.2.1.    /dev设备节点自动创建原理

l  在sysfs下创建类

/sys

├── class

│   ├── input

│   │   ├── event0 -> ../../devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input0/event0

│   ├── leds → 由cls = class_create(THIS_MODULE, "leds"); //创建设备类

│   │   └── phy0-led -> ../../devices/pci0000:00/0000:00:1c.1/0000:03:00.0/leds/phy0-led  →由 device_create(cls, NULL, dev, NULL, "phy0-led"); //创建/sys/class/leds/phy0-led

 

l  udev自动加载

 

加载模块insmod *.ko的时候,用户空间中的udev会自动响应 device_create(…)函数,内核产生uevent, 在kset下产生uevent文件,其文件内容为action(add, remove等),  通过netlink socket被守护进程udevd捕获后,扫描/sys下的uevent文件,在/dev下自动创建对应的设备号。 见下面例子

 

l  e.g

    cls = class_create(THIS_MODULE, "leds-atomic"); //

device_create(cls, NULL, dev, NULL, "myled");//dev/myled

当insmod 该驱动后,

cat /sys/class/leds-atomic/myled/uevent(文件在内核中数据结构为struct attribute)

→  MAJOR=250

    MINOR=0

    DEVNAME=myled

因此,udevd根据上述uevent文件在创建设备节点 /dev/myled, major和minor分别为250和0。