• 嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法


    之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 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;
    }
  • 相关阅读:
    推荐一款优秀的web自动化测工具
    基于kylinTOP工具的HTTP2压力测试
    SIP压力测试——奇林软件kylinPET
    软件WEB自动化测试工具之智能元素定位
    软件自动化测试工具之智能元素定位
    软件自动化测试工具之元素智能定位
    压力测试工具有哪些
    optimizing Wi-Fi solution for International School
    All in One我有一个梦想,所有的应用程序都可以跑在tablet上面
    C#.Net全栈工程师之路-学习路径
  • 原文地址:https://www.cnblogs.com/ynxf/p/6063520.html
Copyright © 2020-2023  润新知