当前位置: 首页 > news >正文

设计本网站天津企业网站设计制作

设计本网站,天津企业网站设计制作,模板网站定制,化妆品网站静态模板一、静态申请字符类设备号 字符类设备函数在文件include/linux/fs.h中内核提供了三个函数来注册一组字符设备编号#xff0c;这三个函数分别是 register_chrdev_region()alloc_chrdev_region()register_chrdev()register_chrdev_region()是提前知道设备的主次设备…一、静态申请字符类设备号 字符类设备函数在文件include/linux/fs.h中内核提供了三个函数来注册一组字符设备编号这三个函数分别是 register_chrdev_region()alloc_chrdev_region()register_chrdev()register_chrdev_region()是提前知道设备的主次设备号再去申请设备号alloc_chrdev_region()是动态分配主次设备号register_chrdev() 是老版本的设备号注册方式只分配主设备号。从设备号在mknod的时候指定。  宏定义MKDEV的头文件include/linux/kdev.h 在kdev_t.h头文件中有一个系列设备号处理的宏命令用于处理各种设备号相关的数据。本期视频只介绍MKDEV后面使用了其他宏定义再介绍include/linux/cdev.h cdev类型是字符设备描述的结构其次的设备号必须用dev_t类型来描述高12位为主设备号低20位为此设备号  编写编译运行 将视频16_驱动模块传参数中的文件module_param.c改成为request_cdev_num.c静态生成设备号编写编译加载运行 使用命令cat /proc/devices查看已经被注册的主设备设备号9没有被注册insmod /mnt/udisk/request_cdev_num.ko numdev_major9 numdev_minor0使用命令cat /proc/devices查看设备号9被注册为scdevrmmod request_cdev_num numdev_major9 numdev_minor0 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h#define DEVICE_NAME scdev #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);static int hello_init(void) {int ret;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret register_chrdev_region(num_dev, DEVICE_MINOR_NUM, DEVICE_NAME);} else {printk(KERN_EMERG numdev_major %d is failed\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}printk(KERN_EMERG Hello World enter!\n);return 0; }static void hello_exit(void) {dev_t num_dev MKDEV(numdev_major, numdev_minor);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);printk(KERN_EMERG Hello World exit!\n); }module_init(hello_init); module_exit(hello_exit); register_chrdev_region 测试结果 [rootiTOP-4412]# insmod request_cdev_num.ko numdev_major9 numdev_minor0 [ 135.652085] numdev_major is 9! [ 135.653710] numdev_minor is 0! [ 135.656810] Hello World enter! [rootiTOP-4412]# cat /proc/devices Character devices:1 mem4 ttyS5 /dev/tty5 /dev/console5 /dev/ptmx9 scdev10 misc13 input21 sg29 fb81 video4linux89 i2c 108 ppp 116 alsa 128 ptm 136 pts 153 rc522_test 166 ttyACM 180 usb 188 ttyUSB 189 usb_device 204 ttySAC 216 rfcomm 243 ump 244 mali 249 mt3326-gps 250 roccat 251 BaseRemoteCtl 252 media 253 ttyGS 254 rtcBlock devices:1 ramdisk 259 blkext7 loop8 sd65 sd66 sd67 sd68 sd69 sd70 sd71 sd 128 sd 129 sd 130 sd 131 sd 132 sd 133 sd 134 sd 135 sd 179 mmc 254 device-mapper [rootiTOP-4412]# rmmod request_cdev_num numdev_major9 numdev_minor0 [ 152.245805] Hello World exit! [rootiTOP-4412]# cat /proc/devices Character devices:1 mem4 ttyS5 /dev/tty5 /dev/console5 /dev/ptmx10 misc13 input21 sg29 fb81 video4linux89 i2c 108 ppp 116 alsa 128 ptm 136 pts 153 rc522_test 166 ttyACM 180 usb 188 ttyUSB 189 usb_device 204 ttySAC 216 rfcomm 243 ump 244 mali 249 mt3326-gps 250 roccat 251 BaseRemoteCtl 252 media 253 ttyGS 254 rtcBlock devices:1 ramdisk 259 blkext7 loop8 sd65 sd66 sd67 sd68 sd69 sd70 sd71 sd 128 sd 129 sd 130 sd 131 sd 132 sd 133 sd 134 sd 135 sd 179 mmc 254 device-mapper [rootiTOP-4412] 测试结果   二、动态申请字符类设备号 字符设备函数在文件include/linux/fs.h中alloc_chrdev_region()是动态分配主次设备号宏定义MAJOR提取dev_t数据中的主设备号编写编译运行 将视频17中的文件request_cdev_num.c改写为request_ascdev_num.c动态生成字符设备号编写编译加载运行 使用命令cat /proc/device查看动态加载模块之后再查看设备号 修改后的代码 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h#define DEVICE_NAME scdev #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);static int hello_init(void) {int ret;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);} else {ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);numdev_major MAJOR(num_dev);printk(KERN_EMERG register req major number is %d\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}printk(KERN_EMERG Hello World enter!\n);return 0; }static void hello_exit(void) {dev_t num_dev MKDEV(numdev_major, numdev_minor);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);printk(KERN_EMERG Hello World exit!\n); }module_init(hello_init); module_exit(hello_exit); alloc_chrdev_region代码 测试运行后 [rootiTOP-4412]# insmod request_ascdev_num.ko [ 1335.710205] numdev_major is 0! [ 1335.711817] numdev_minor is 0! [ 1335.714861] register req major number is 248 [ 1335.727258] Hello World enter! [rootiTOP-4412]# cat /proc/ 1/ 670/ bus/ mfc/ 11907/ 714/ cgroups misc 12924/ 726/ cmdline modules 12925/ 731/ consoles mounts 12926/ 734/ cpu/ net/ 16/ 744/ cpuinfo pagetypeinfo 2/ 745/ crypto panic_info_dump 3/ 763/ devices partitions 339/ 767/ diskstats sched_debug 341/ 838/ driver/ scsi/ 343/ 866/ execdomains self/ 354/ 892/ fb softirqs 365/ 894/ filesystems stat 376/ 896/ fs/ sys/ 429/ 898/ interrupts sysrq-trigger 445/ 900/ iomem sysvipc/ 455/ 911/ ioports timer_list 456/ 918/ irq/ tty/ 5/ 919/ kallsyms uid_stat/ 508/ 9192/ key-users uptime 522/ 940/ kmsg version 528/ 943/ kpagecount vmallocinfo 6/ 956/ kpageflags vmstat 6437/ 994/ loadavg wakelocks 657/ asound/ locks zoneinfo 662/ buddyinfo meminfo [rootiTOP-4412]# cat /proc/devices Character devices:1 mem4 ttyS5 /dev/tty5 /dev/console5 /dev/ptmx10 misc13 input21 sg29 fb81 video4linux89 i2c 108 ppp 116 alsa 128 ptm 136 pts 153 rc522_test 166 ttyACM 180 usb 188 ttyUSB 189 usb_device 204 ttySAC 216 rfcomm 243 ump 244 mali 248 scdev 249 mt3326-gps 250 roccat 251 BaseRemoteCtl 252 media 253 ttyGS 254 rtc 测试   三、注册字符类设备 分配内存空间函数kmalloc 分配连续的虚拟地址用于小内存分配。在include/linux/slab.h文件中参数1申请的内存大小最大128K参数2GFP_KERNEL代表优先权内存不够可以延迟分配清空内存空间的数据函数memset 可以清空内存空间也就是全部写为0参数1内存地址参数20参数3内存长度字符设备初始化函数cdev_init 在头文件include/linux/cdev.h中参数1cdev字符设备文件结构体参数2file_operations结构体注册设备本质是向linux设备文件中添加数据这些数据需要初始化字符设备注册函数cdev_add 在头文件include/linux/cdev.h中参数1cdev字符设备文件结构体参数2设备号参数3设备范围大小向系统注册设备也就是向linux系统添加数据卸载设备函数cdev_del 参数1cdev结构体移除字符设备将18_动态申请字符类设备号中的文件request_ascdev_num.c改写为register_cdev.c编译测试 通过加载模块后的打印信息可以观察到驱动加载的过程以及注册设备的反馈信息 代码 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h /* define memroy sapce */ #include linux/slab.h#define DEVICE_NAME scdev #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);struct reg_dev {char *data;unsigned long size;struct cdev cdev; }; struct reg_dev *my_devices;struct file_operations my_fops {.owner THIS_MODULE, };static void reg_init_cdev(struct reg_dev *dev, int index) {int err;int devno MKDEV(numdev_major, numdev_minorindex);cdev_init(dev-cdev, my_fops);dev-cdev.owner THIS_MODULE;dev-cdev.ops my_fops;err cdev_add(dev-cdev, devno, 1);if(err) {printk(KERN_EMERG cdev_add %d is fail! %d\n, index, err);} else {printk(KERN_EMERG cdev_add %d is success!\n, index);} }static int hello_init(void) {int ret, i;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);} else {ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);numdev_major MAJOR(num_dev);printk(KERN_EMERG register req major number is %d\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}my_devices kmalloc(DEVICE_MINOR_NUM*sizeof(struct reg_dev), GFP_KERNEL);if(!my_devices) {ret -ENOMEM;printk(KERN_EMERG kamlloc fialed!\n);goto fail;}memset(my_devices, 0, DEVICE_MINOR_NUM*sizeof(struct reg_dev));for(i0;iDEVICE_MINOR_NUM;i) {my_devices[i].data kmalloc(REGDEV_SIZE, GFP_KERNEL);memset(my_devices[i].data, 0, REGDEV_SIZE); /* data address */reg_init_cdev(my_devices[i], i);}printk(KERN_EMERG Hello World enter!\n);return 0;fail:unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret; }static void hello_exit(void) {int i;dev_t num_dev MKDEV(numdev_major, numdev_minor);printk(KERN_EMERG Hello World exit!\n);for(i0;iDEVICE_MINOR_NUM;i) {cdev_del(my_devices[i].cdev);}unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM); }module_init(hello_init); module_exit(hello_exit); 代码 测试结果 [rootiTOP-4412]# insmod register_cdev.ko [ 1065.781646] numdev_major is 0! [ 1065.783265] numdev_minor is 0! [ 1065.786377] register req major number is 248 [ 1065.790637] cdev_add 0 is success! [ 1065.793943] cdev_add 1 is success! [ 1065.797392] Hello World enter! [rootiTOP-4412]# rmmod register_cdev [ 1082.904729] Hello World exit 测试结果   四、生成字符类设备节点 前面介绍设备中的模型bus,device,driver,都是有比较明显确定的定义。bus代表总线device代表实际的设备和接口driver代表驱动。 class是设备类它是一个抽象的概念没有对应的实体。它是提供给用户接口相似的一类设备的集合。常见的输入子系统input、usb、串口tty‘块设备block等。 函数class_create创建class类文件 参数1一般是THIS_MODULE参数2设备名称创建一个设备类用于设备节点文件的创建返回一个class结构体变量class结构体变量 class是设备驱动模型中通用的设备结构在头文件include/linux/device.h的280行老版本创建设备class函数class_device_create 头文件include/linux/device.h中参数1class结构体变量参数2父设备NULL参数3dev_t设备号参数4数据NULL参数5设备节点名称释放设备class函数class_destroy 参数1myclass创建设备节点函数device_create 头文件include/linux/device.h中参数1设备诶所属于的类参数2设备的浮设备NULL参数3设备号参数4设备数据NULL参数5设备名称摧毁设备节点函数device_destroy 参数1设备所属于的类参数2设备号释放内存函数kfree 参数1数据指针 编写编译运行测试 将19注册字符类设备中的register_cdev.c文件为create_cnode.c编译加载模块create_cnode.ko 使用命令ls /sys/class/可以查看到生成的class使用命令ls /dev可以查看到生成的两个设备节点加载模块的时候还可以使用命令生成设备节点命令列如 mknod dev/test0 c 249 0mknod dev/test1 c 249 1 运行代码 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h /* define memroy sapce */ #include linux/slab.h/* include device_create class file */ #include linux/device.h#define DEVICE_NAME chardevnode #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);static struct class *my_class;struct reg_dev {char *data;unsigned long size;struct cdev cdev; }; struct reg_dev *my_devices;struct file_operations my_fops {.owner THIS_MODULE, };static void reg_init_cdev(struct reg_dev *dev, int index) {int err;int devno MKDEV(numdev_major, numdev_minorindex);cdev_init(dev-cdev, my_fops);dev-cdev.owner THIS_MODULE;dev-cdev.ops my_fops;err cdev_add(dev-cdev, devno, 1);if(err) {printk(KERN_EMERG cdev_add %d is fail! %d\n, index, err);} else {printk(KERN_EMERG cdev_add %d is success!\n, (numdev_minorindex));} }static int hello_init(void) {int ret, i;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);} else {ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);numdev_major MAJOR(num_dev);printk(KERN_EMERG register req major number is %d\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}my_class class_create(THIS_MODULE, DEVICE_NAME);my_devices kmalloc(DEVICE_MINOR_NUM*sizeof(struct reg_dev), GFP_KERNEL);if(!my_devices) {ret -ENOMEM;printk(KERN_EMERG kmalloc fialed!\n);goto fail;}memset(my_devices, 0, DEVICE_MINOR_NUM*sizeof(struct reg_dev));for(i0;iDEVICE_MINOR_NUM;i) {my_devices[i].data kmalloc(REGDEV_SIZE, GFP_KERNEL);memset(my_devices[i].data, 0, REGDEV_SIZE); /* data address *//* register device to system */reg_init_cdev(my_devices[i], i);/* create device node */device_create(my_class, NULL, MKDEV(numdev_major, numdev_minori), NULL, DEVICE_NAME%d, i);}printk(KERN_EMERG Hello World enter!\n);return 0;fail:unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret; }static void hello_exit(void) {int i;dev_t num_dev MKDEV(numdev_major, numdev_minor);printk(KERN_EMERG Hello World exit!\n);for(i0;iDEVICE_MINOR_NUM;i) {cdev_del(my_devices[i].cdev);/* release memory*/device_destroy(my_class, MKDEV(numdev_major, numdev_minori));}/* release my class*/class_destroy(my_class);/* release kfre */kfree(my_devices);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM); }module_init(hello_init); module_exit(hello_exit); class_create 测试结果 [rootiTOP-4412]# insmod create_cnode.ko [12828.419006] numdev_major is 0! [12828.420699] numdev_minor is 0! [12828.423674] register req major number is 248 [12828.429116] cdev_add 0 is success! [12828.432882] cdev_add 1 is success! [12828.436403] Hello World enter![rootiTOP-4412]# cat /proc/devices Character devices:1 mem4 ttyS5 /dev/tty5 /dev/console5 /dev/ptmx10 misc13 input21 sg29 fb81 video4linux89 i2c 108 ppp 116 alsa 128 ptm 136 pts 153 rc522_test 166 ttyACM 180 usb 188 ttyUSB 189 usb_device 204 ttySAC 216 rfcomm 243 ump 244 mali 248 chardevnode 249 mt3326-gps 250 roccat 251 BaseRemoteCtl 252 media 253 ttyGS 254 rtc[rootiTOP-4412]# rmmod create_cnode [12439.491484] Hello World exit! 测试结果   五、字符驱动 file_operations中的函数比较多选取用的比较多的函数简单介绍后面的驱动教程中调用了对应的函数再详细介绍int (*open)(struct inode *, struct file *) 打开函数int (*release)(struct inode *, struct file *) 释放close函数long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long) io控制函数ssize_t (*read)(struct file *, char __user *, size_t, loff_t *) 读函数ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *) 写函数loff_t (*llseek)(struct file *, loff_t, int) 定位函数如果需要不同的设备节点有不同的功能只需要在注册设备的时候添加不同的file_operations结构体即可编写编译运行测试将驱动视频教程20中的create_cnode.c改为“char_driver.c”修改编译文件Makefile将驱动视频教程09中invoke_hello.c改为invoke_char_driver.c编译应用命令如下 arm-none-linux-gnueabi-gcc -o invoke_char_driver invoke_char_driver.c -static 编写代码 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h /* define memroy sapce */ #include linux/slab.h/* include device_create class file */ #include linux/device.h#define DEVICE_NAME chardevnode #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);static struct class *my_class;struct reg_dev {char *data;unsigned long size;struct cdev cdev; }; struct reg_dev *my_devices;/* open */ static int chardevnode_open(struct inode *inode, struct file *file) {printk(KERN_EMERG chardevnode open is success!\n);return 0; }/* close */ static int chardevnode_release(struct inode *indoe, struct file *file) {printk(KERN_EMERG chardevnode release is success!\n);return 0; }/* io control */ static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {printk(KERN_EMERG chardevnode release is success!cmd is %d,arg is %d\n, cmd, arg);return 0; }/* read */ static ssize_t chardevnode_read(struct file *file, char __user *buf, size_t size, loff_t *f_ops) {return 0; }/* write */ static ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t size, loff_t *ops) {return 0; }/* lseek */ static loff_t chardevnode_llseek(struct file *file, loff_t offset, int whence) {return 0; }struct file_operations my_fops {.owner THIS_MODULE,.open chardevnode_open,.release chardevnode_release,.unlocked_ioctl chardevnode_ioctl,.read chardevnode_read,.write chardevnode_write,.llseek chardevnode_llseek, };static void reg_init_cdev(struct reg_dev *dev, int index) {int err;int devno MKDEV(numdev_major, numdev_minorindex);cdev_init(dev-cdev, my_fops);dev-cdev.owner THIS_MODULE;dev-cdev.ops my_fops;err cdev_add(dev-cdev, devno, 1);if(err) {printk(KERN_EMERG cdev_add %d is fail! %d\n, index, err);} else {printk(KERN_EMERG cdev_add %d is success!\n, (numdev_minorindex));} }static int hello_init(void) {int ret, i;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);} else {ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);numdev_major MAJOR(num_dev);printk(KERN_EMERG register req major number is %d\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}my_class class_create(THIS_MODULE, DEVICE_NAME);my_devices kmalloc(DEVICE_MINOR_NUM*sizeof(struct reg_dev), GFP_KERNEL);if(!my_devices) {ret -ENOMEM;printk(KERN_EMERG kmalloc fialed!\n);goto fail;}memset(my_devices, 0, DEVICE_MINOR_NUM*sizeof(struct reg_dev));for(i0;iDEVICE_MINOR_NUM;i) {my_devices[i].data kmalloc(REGDEV_SIZE, GFP_KERNEL);memset(my_devices[i].data, 0, REGDEV_SIZE); /* data address *//* register device to system */reg_init_cdev(my_devices[i], i);/* create device node */device_create(my_class, NULL, MKDEV(numdev_major, numdev_minori), NULL, DEVICE_NAME%d, i);}printk(KERN_EMERG Hello World enter!\n);return 0;fail:unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret; }static void hello_exit(void) {int i;dev_t num_dev MKDEV(numdev_major, numdev_minor);printk(KERN_EMERG Hello World exit!\n);for(i0;iDEVICE_MINOR_NUM;i) {cdev_del(my_devices[i].cdev);/* release memory*/device_destroy(my_class, MKDEV(numdev_major, numdev_minori));}/* release my class*/class_destroy(my_class);/* release kfre */kfree(my_devices);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM); }module_init(hello_init); module_exit(hello_exit); 代码 测试结果 [rootiTOP-4412]# insmod char_driver.ko [ 2135.474056] numdev_major is 0! [ 2135.475744] numdev_minor is 0! [ 2135.478724] register req major number is 248 [ 2135.484220] cdev_add 0 is success! [ 2135.487909] cdev_add 1 is success! [ 2135.500246] Hello World enter! [rootiTOP-4412]# ./invok_char [ 2174.171640] chardevnode open is success! [ 2174.174452] chardevnode release is success!cmd is 1,arg is 6 [ 2174.179828] chardevnode open is success! [ 2174.183737] chardevnode release is success!cmd is 1,arg is 6 [ 2174.189346] chardevnode release is success! [ 2174.193511] chardevnode release is success! APP open /dev/chardevnode0 success APP open /dev/chardevnode0 success [rootiTOP-4412]# rmmod char_driver [ 2199.758801] Hello World exit! 测试结果   六、字符类GPIOSLED驱动编写 将21_字符驱动中的文件“char_driver.c”改为“char_driver_leds.c”,添加gpio的初始化和操作函数卸载模块的时候释放GPIO将宏定义部分添加到头文件中简单修改Makefile文件将“21_字符驱动”中的文件incoke_char_driver.c改为文件invoke_char_gpios.c并使用main参数传参数操作gpio应用编译命令 arm-none-linux-gnueabi-gcc -o invoke_char_gpios invoke_char_gpios.c -static操作命令 类似./invoke_char_gpios 0 1参数1为命令参数2为GPIO字符驱动程序 #include linux/init.h #include linux/module.h/* define module_param module_param_array header file */ #include linux/moduleparam.h /* define perms head file*/ #include linux/stat.h /* char device register head file */ #include linux/fs.h /* MKDEV change device ID type */ #include linux/kdev_t.h /* define char device struct */ #include linux/cdev.h /* define memroy sapce */ #include linux/slab.h/* include device_create class file */ #include linux/device.h#include linux/gpio.h #include plat/gpio-cfg.h #include mach/gpio.h #include mach/gpio-exynos4.h#define DEVICE_NAME chardevnode #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000MODULE_LICENSE(Dual BSD/GPL); MODULE_AUTHOR(TOPEET);int numdev_major DEV_MAJOR; int numdev_minor DEV_MINOR;/* input major device ID */ module_param(numdev_major, int, S_IRUSR); /* input minor device ID */ module_param(numdev_minor, int, S_IRUSR);static struct class *my_class;struct reg_dev {char *data;unsigned long size;struct cdev cdev; }; struct reg_dev *my_devices;/* open */ static int chardevnode_open(struct inode *inode, struct file *file) {printk(KERN_EMERG chardevnode open is success!\n);return 0; }/* close */ static int chardevnode_release(struct inode *indoe, struct file *file) {printk(KERN_EMERG chardevnode release is success!\n);return 0; }/* io control */ static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {printk(KERN_EMERG chardevnode release is success!cmd is %d,arg is %d\n, cmd, arg);if(cmd 1 || arg 1) {printk(KERN_EMERG cmd and arg is 0 or 1);return 0;}switch(arg) {case 0:gpio_set_value(EXYNOS4_GPL2(0), cmd);break;case 1:gpio_set_value(EXYNOS4_GPK1(1), cmd);break;default:printk(KERN_EMERG cmd and arg is 0 or 1);break;}return 0; }/* read */ static ssize_t chardevnode_read(struct file *file, char __user *buf, size_t size, loff_t *f_ops) {return 0; }/* write */ static ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t size, loff_t *ops) {return 0; }/* lseek */ static loff_t chardevnode_llseek(struct file *file, loff_t offset, int whence) {return 0; }struct file_operations my_fops {.owner THIS_MODULE,.open chardevnode_open,.release chardevnode_release,.unlocked_ioctl chardevnode_ioctl,.read chardevnode_read,.write chardevnode_write,.llseek chardevnode_llseek, };/* GPL2_0 */ static int led1_init(void) {int ret;printk(KERN_EMERG Gpio led 1 init\n);ret gpio_request(EXYNOS4_GPL2(0), LEDS);if(ret 0) {printk(KERN_EMERG gpio_request EXYNOS4_GPL2(0) failed\n);return ret;}s3c_gpio_cfgpin(EXYNOS4_GPL2(0), S3C_GPIO_OUTPUT);gpio_set_value(EXYNOS4_GPL2(0), 0);return 0; }/* GPK1_1 */ static int led2_init(void) {int ret;printk(KERN_EMERG GPIO led 2 init\n);ret gpio_request(EXYNOS4_GPK1(1), LEDS2);if(ret 0) {printk(KERN_EMERG gpio_request EXYNOS4_GPK1(1) fialed\n);return ret;}s3c_gpio_cfgpin(EXYNOS4_GPK1(1), S3C_GPIO_OUTPUT);gpio_set_value(EXYNOS4_GPK1(1), 0);return 0; }static void reg_init_cdev(struct reg_dev *dev, int index) {int err;int devno MKDEV(numdev_major, numdev_minorindex);cdev_init(dev-cdev, my_fops);dev-cdev.owner THIS_MODULE;dev-cdev.ops my_fops;err cdev_add(dev-cdev, devno, 1);if(err) {printk(KERN_EMERG cdev_add %d is fail! %d\n, index, err);} else {printk(KERN_EMERG cdev_add %d is success!\n, (numdev_minorindex));} }static int hello_init(void) {int ret, i;dev_t num_dev;printk(KERN_EMERG numdev_major is %d!\n, numdev_major);printk(KERN_EMERG numdev_minor is %d!\n, numdev_minor);if(numdev_major) {num_dev MKDEV(numdev_major, numdev_minor);ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);} else {ret alloc_chrdev_region(num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME);numdev_major MAJOR(num_dev);printk(KERN_EMERG register req major number is %d\n, numdev_major);}if(ret 0) {printk(KERN_EMERG register_chrdev_region req %d is failed\n, numdev_major);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret;}my_class class_create(THIS_MODULE, DEVICE_NAME); my_devices kmalloc(DEVICE_MINOR_NUM*sizeof(struct reg_dev), GFP_KERNEL);if(!my_devices) {ret -ENOMEM;printk(KERN_EMERG kmalloc fialed!\n);goto fail;}memset(my_devices, 0, DEVICE_MINOR_NUM*sizeof(struct reg_dev));for(i0;iDEVICE_MINOR_NUM;i) {my_devices[i].data kmalloc(REGDEV_SIZE, GFP_KERNEL); memset(my_devices[i].data, 0, REGDEV_SIZE); /* data address *//* register device to system */reg_init_cdev(my_devices[i], i);/* create device node */device_create(my_class, NULL, MKDEV(numdev_major, numdev_minori), NULL, DEVICE_NAME%d, i);}led1_init();led2_init();printk(KERN_EMERG Hello World enter!\n);return 0;fail:unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM);return ret; }static void hello_exit(void) {int i;dev_t num_dev MKDEV(numdev_major, numdev_minor);printk(KERN_EMERG Hello World exit!\n);for(i0;iDEVICE_MINOR_NUM;i) {cdev_del(my_devices[i].cdev);/* release memory*/device_destroy(my_class, MKDEV(numdev_major, numdev_minori));}/* release my class*/class_destroy(my_class);/* release kfre */kfree(my_devices);unregister_chrdev_region(num_dev, DEVICE_MINOR_NUM); }module_init(hello_init); module_exit(hello_exit); char_driver_leds.c 然后是应用程序 #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include stdlib.hint main(int argc, char *argv[]) {int fd0, fd1;char *hello_node0 /dev/chardevnode0;char *hello_node1 /dev/chardevnode1;if(argc 2) {printf(please input cmd and arg\n);}/* O_RDWR只读打开, O_NDELAY非阻塞方式 */fd0 open(hello_node0, O_RDWR|O_NDELAY);if(fd0 0) {printf(APP open %s failed\n, hello_node0);exit(EXIT_FAILURE);} else {printf(APP open %s success\n, hello_node0);ioctl(fd0, atoi(argv[1]), atoi(argv[2]));}/* O_RDWR只读打开, O_NDELAY非阻塞方式 */ /*fd1 open(hello_node0, O_RDWR|O_NDELAY);if(fd1 0) {printf(APP open %s failed\n, hello_node0);exit(EXIT_FAILURE);} else {printf(APP open %s success\n, hello_node0);ioctl(fd1, 1, 6);} */close(fd0);close(fd1); } invoke_char_driver.c 然后是makefile TARGET_NAME char_driver_leds APP_NAME invoke_char_gpios obj-m $(TARGET_NAME).oKDIR : /home/topeet/chen/kernel-3.0/iTop4412_Kernel_3.0PWD ? $(shell pwd)all:appmake -C $(KDIR) M$(PWD) modulesapp:$(APP_NAME)arm-none-linux-gnueabi-gcc $(APP_NAME).c -o $(APP_NAME) -staticclean:rm -rf *.o *.ko *.mod.c *.symvers *.order *.cmd .$(TARGET_NAME)* $(APP_NAME) Makefile 测试结果 [rootiTOP-4412]# insmod char_driver_leds.ko [ 420.107938] numdev_major is 0! [ 420.109549] numdev_minor is 0! [ 420.112677] register req major number is 248 [ 420.125765] cdev_add 0 is success! [ 420.137424] cdev_add 1 is success! [ 420.148881] Gpio led 1 init [ 420.150342] gpio_request EXYNOS4_GPL2(0) failed [ 420.154743] GPIO led 2 init [ 420.165167] Hello World enter! [rootiTOP-4412]# ./invoke_char_gpios 1 0 please input cmd [ 431.050669] chardevnode open is success! [ 431.054691] chardevnode release is success!cmd is 1,arg is 0 [ 431.060238] chardevnode release is success! and arg APP open /dev/chardevnode0 success [rootiTOP-4412]# ./invoke_char_gpios 1 1 please input cmd [ 435.289936] chardevnode open is success! [ 435.294047] chardevnode release is success!cmd is 1,arg is 1 [ 435.299498] chardevnode release is success! and arg APP open /dev/chardevnode0 success [rootiTOP-4412]# ./invoke_char_gpios 0 0 please input cmd [ 440.595232] chardevnode open is success! [ 440.599237] chardevnode release is success!cmd is 0,arg is 0 and arg APP open /dev/chardevnode0 success [ 440.609648] chardevnode release is success! [rootiTOP-4412]# ./invoke_char_gpios 0 1 please input cmd [ 443.313565] chardevnode open is success! [ 443.317679] chardevnode release is success!cmd is 0,arg is 1 [ 443.323129] chardevnode release is success! and arg APP open /dev/chardevnode0 success[rootiTOP-4412]# rmmod char_driver_leds [ 468.722834] Hello World exit! 测试结果   不知道为什么要设两个驱动设备按我的写法应该这两个驱动设备没什么区别。转载于:https://www.cnblogs.com/ch122633/p/9459904.html
http://www.pierceye.com/news/878258/

相关文章:

  • 网站建设中 翻译六安市 网站集约化建设
  • 全国卫生机构建设管理系统网站公司网站维护费用计哪个科目
  • 学做川菜最好的网站商标综合查询
  • 网站开发培训 价格哪些网站可以找到兼职做报表的
  • 网站建设功能分为几种北京自考网址
  • 购买网站域名怎么做会计分录广告机免费投放
  • 网上做网站赚钱深圳市无限空间工业设计有限公司
  • 商贸网站建设怎么查看wordpress版本
  • 电子商务网站建设哪本教材比较适合中等专业学校用网站建设yankt
  • 局域网网站建设需要什么条件企业建网站的目的
  • 高校专业建设网站桂林漓江竹筏
  • 自已做个网站怎么做网站网络的可用性
  • 深圳网站设计建设永州做网站
  • 怎么制作网站应用wordpress 淘宝客赚钱
  • 网站在政务新媒体建设方案打开手机网站速度慢
  • 网站备案表服务类网站模板
  • 个人网站维护费用淮安注册公司
  • 网站提交做海鱼的网站
  • 建设网站业务竞争大唯一做魅惑的网站
  • 建设学校网站的意义更换wordpress图标
  • 环保局网站如何做备案证明在线代理服务器网页版
  • 十佳网站武昌做网站哪家好
  • wordpress调用同分类最新文章seo营销网站的设计标准
  • 免费下载网站有哪些连云港网络公司排名
  • 如何迅速建企业网站毕设做网站需要什么技术准备
  • 可以做音基题的音乐网站公司网页设计怎么弄
  • 益阳营销型网站建设乌鲁木做兼职的网站
  • 如何建单位网站怎么让别人找你做网站
  • 青海建设厅职称网站建设小程序怎么挂失
  • 建设在线购物网站51zwd一起做网站广州