之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 struct file_operations 结构体对应。
而本节课讲的是如何在设备号相同的情况下,让不同的次设备号对应不同的 struct file_operations 结构体。
在本次的驱动程序中,打开/dev/hello0 、 /dev/hello1 调用的是hello_open函数。打开/dev/hello2 调用的是 hello2_open 函数。打开其他次设备号的文件,则是打开失败。
驱动程序代码:
/************************************************************************* > File Name: hello.c > Author: > Mail: > Created Time: 2016年11月14日 星期一 20时28分50秒 ************************************************************************/ #include <linux/sched.h> #include <linux/signal.h> #include <linux/spinlock.h> #include <linux/errno.h> #include <linux/random.h> #include <linux/poll.h> #include <linux/init.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/wait.h> #include <linux/mutex.h> #include <linux/io.h> #include <linux/cdev.h> #include <linux/fs.h> /* 确定主设备号 唯一 */ static int major; /* 第二种设备的函数 */ static int hello2_open( struct inode *inode, struct file *file ) { printk("hello_open2 "); return 0; } /* 第一种设备的函数 */ static int hello_open( struct inode *inode, struct file *file ) { printk("hello_open "); return 0; } /* 第一种设备的结构体 */ static struct file_operations hello_ops = { .owner = THIS_MODULE, .open = hello_open, }; /* 第二种设备的结构体 */ static struct file_operations hello2_ops = { .owner = THIS_MODULE, .open = hello2_open, }; static struct cdev hello_cdev; static struct cdev hello2_cdev; static struct class *cls; static int hello_init(void) { dev_t devid; if(major) //如果已经有了设备号则不再申请,如果没有则自动申请一个 { devid = MKDEV(major, 0); //次设备号从0开始计算 register_chrdev_region(devid,2,"hello"); //有两个设备文件与之对应 } else { alloc_chrdev_region(&devid, 0, 2,"hello"); //次设备号从0开始计算,有两个设备文件与之对应 major = MAJOR(devid); } cdev_init( &hello_cdev, &hello_ops ); cdev_add( &hello_cdev, devid, 2); //有两个设备文件与之对应 即次设备号为0~1的设备文件调用 hello_ops 中的函数 /* 因为上面的已经有了主设备号,这里肯定也是有主设备号,所以不用判断是否要去申请了 */ devid = MKDEV(major, 2); //次设备号从0开始计算 register_chrdev_region(devid,1,"hello2"); //有一个设备文件与之对应 cdev_init( &hello2_cdev, &hello2_ops ); cdev_add( &hello2_cdev, devid, 1 ); //有一个设备文件与之对应 即次设备号为2的设备文件调用 hello2_ops 中的函数 cls = class_create(THIS_MODULE,"hello"); class_device_create(cls,NULL,MKDEV(major,0),NULL,"hello0"); class_device_create(cls,NULL,MKDEV(major,1),NULL,"hello1"); class_device_create(cls,NULL,MKDEV(major,2),NULL,"hello2");
class_device_create(cls,NULL,MKDEV(major,3,NULL,"hello3"); return 0; } static void hello_exit(void) { class_device_destroy(cls,MKDEV(major,0)); class_device_destroy(cls,MKDEV(major,1)); class_device_destroy(cls,MKDEV(major,2));
class_device_destroy(cls,MKDEV(major,3)); class_destroy(cls); cdev_del(&hello_cdev); unregister_chrdev_region(MKDEV(major,0),1); cdev_del(&hello2_cdev); unregister_chrdev_region(MKDEV(major,2),1); } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
测试程序代码:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> int main( int argc, char **argv ) { int fd; if(argc != 2) return 0; fd = open(argv[1],O_RDWR); if(fd<0) printf("open failed "); else printf( "can open " ); return 0; }