字符驱动设备(3)

led-drv.c:

 1 #include <linux/module.h>
 2 #include <linux/kernel.h>
 3 #include <linux/fs.h>
 4 #include <linux/init.h>
 5 #include <linux/delay.h>
 6 #include <asm/uaccess.h>
 7 #include <asm/irq.h>
 8 #include <asm/io.h>
 9 #include <asm/arch/regs-gpio.h>
10 #include <asm/hardware.h>
11 
12 static int led_drv_open(struct inode *inode, struct file *file)
13 {
14     printk("led_open\n");
15 
16     return 0;
17 }
18 
19 static ssize_t led_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
20 {
21     printk("led_write\n");
22 
23     return 0;
24 }
25 
26 static struct file_operations led_fops = {
27         .owner = THIS_MODULE,
28         .open = led_drv_open,
29         .write = led_drv_write,
30 };
31 
32 /*入口函数*/
33 static int __init led_drv_init(void)
34 {
35     register_chrdev(111, "led_drv",&led_fops);
36 
37     return 0;
38 }
39 
40 /*出口函数*/
41 static int __exit led_drv_exit(void)
42 {
43      unregister_chrdev(111, "led_drv");
44 
45      return 0;
46 }
47 
48 module_init(led_drv_init);
49 module_exit(led_drv_exit);
50 
51 MODULE_LICENSE("GPL");
52 MODULE_AUTHOR("ZHANGPENG");

led_drv_test.c:

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <stdio.h>
 5 
 6 int main(int argc,char **argv)
 7 {
 8     int fd;
 9     int val = 1;
10     
11     fd = open("/dev/led",O_RDWR);
12     if(fd<0)
13     {
14         printf("can't open!\n");
15     }
16     
17     write(fd,&val,4);
18 
19     return 0;
20 }

Makefile:

 1 KERN_DIR = /home/zhangpeng/workspace/kernel/linux-2.6.22.6
 2 
 3 all:
 4     make -C $(KERN_DIR) M=`pwd` modules 
 5 
 6 clean:
 7     make -C $(KERN_DIR) M=`pwd` modules clean
 8     rm -rf modules.order
 9 
10 obj-m    += led_drv.o

编译测试过程:

1.make

2.insmod led_drv.ko  //加载模块

3.arm-linux-gcc -o led_drv_test led_drv_test.c  //编译测试程序

 1 #include <sys/types.h>
 2 #include <sys/stat.h>
 3 #include <fcntl.h>
 4 #include <stdio.h>
 5 
 6 int main(int argc,char **argv)
 7 {
 8     int fd;
 9     int val = 1;
10      
11      fd = open("/dev/xxx",O_RDWR);//注意了,如果这里的"/dev/xxx"和led_drv.c里面的设备名一致,直接运行:./led_drv_test即可。或者手动创建节点也可以,例如:mknod /dev/xxx c 111 0
12      if(fd<0)
13      {
14          printf("can't open!\n");
15      }
16      
17      write(fd,&val,4);
18  
19      return 0;
20  }

关于主设备号问题:

主设备号可以手动设置,也可以设置为系统自动分配。

 1 int major;
 2 
 3 /*入口函数*/
 4 static int __init led_drv_init(void)
 5 {
 6     major = register_chrdev(0, "led_drv",&led_fops);//默认为0会自动分配
 7 
 8     return 0;
 9 }
10 
11 /*出口函数*/
12 static int __exit led_drv_exit(void)
13 {
14      unregister_chrdev(major, "led_drv");
15 
16      return 0;
17 }

 但是,这里也只是仅仅解决了主设备号生成方式的问题,与APP程序如何能打开对应的设备驱动呢?除了上述的手动创建测试程序的节点:mknod /dev/xxx c 111 0 之外,还有没有其他的改进方式呢?

 1 static struct class *led_drv_class;
 2 static struct class_device *led_drv_class_dev;
 3 
 4 /*入口函数*/
 5 static int __init led_drv_init(void)
 6 {
 7     major = register_chrdev(0, "led_drv",&led_fops);
 8 
 9     led_drv_class = class_create(THIS_MODULE, "led_drv");
10     led_drv_class_dev = class_device_create(led_drv_class, NULL, MKDEV(major, 0), NULL, "led_drv"); 
11 
12     return 0;
13 }
14 
15 /*出口函数*/
16 static int __exit led_drv_exit(void)
17 {
18      unregister_chrdev(major, "led_drv");
19 
20      class_device_unregister(led_drv_class_dev);
21      class_destroy(led_drv_class);
22 
23      return 0;
24 }

这样以来,就完成解决了驱动程序和测试程序/APP程序打开设备 open("/dev/led_drv",O_RDWR) 设备名不一致的问题了。

posted @ 2020-05-19 21:53  坦率  阅读(168)  评论(0编辑  收藏  举报