• linux字符型设备驱动 一.注册设备并创建设备文件


    1.字符设备

    字符设备、字符设备驱动与用户空间访问该设备的程序三者之间的关系

      Linux内核中:

    a -- 使用cdev结构体来描述字符设备;

    b -- 通过其成员dev_t来定义设备号(分为主、次设备号)以确定字符设备的唯一性;

    c -- 通过其成员file_operations来定义字符设备驱动提供给VFS的接口函数,如常见的open()、read()、write()等;

         在Linux字符设备驱动中:

    a -- 模块加载函数通过 register_chrdev_region( ) 或 alloc_chrdev_region( )来静态或者动态获取设备号;

    b -- 通过 cdev_init( ) 建立cdev与 file_operations之间的连接,通过 cdev_add( ) 向系统添加一个cdev以完成注册;

    c -- 模块卸载函数通过cdev_del( )来注销cdev,通过 unregister_chrdev_region( )来释放设备号;


         用户空间访问该设备的程序:

    a -- 通过Linux系统调用,如open( )、read( )、write( ),来“调用”file_operations来定义字符设备驱动提供给VFS的接口函数;

    2.例子

    hello.c

    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    static int major = 99; //主设备号(用于区分设备类)
    static int minor = 0;  //次设备号(用于区分哪个设备)
    
    static dev_t devno;
    static struct cdev cdev1;
    struct class *hello_class;
    
    static int hello_open(struct inode *inodep, struct file *filep)
    {
        printk(KERN_ALERT "hello are opened 
    ");
        return 0;
    }
    
    static struct file_operations hello_ops = {
        .open = hello_open,
    };
    
    static int hello_init(void)
    {
        int ret;
        printk(KERN_ALERT "hello_init
    ");
        //第一步:将主设备号、次设备号转化成dev_t类型
        devno = MKDEV(major, minor);
        ret = register_chrdev_region(devno, 1, "hello");
        if (ret < 0)
        {
            printk(KERN_ERR "my register_chrdev_region fail 
    ");
            return ret;
        }
        printk(KERN_INFO "register_chrdev_region success
    ");
        //第二步:注册字符设备驱动
        cdev_init(&cdev1, &hello_ops);
        ret = cdev_add(&cdev1, devno, 1);
        if (ret < 0)
        {
            printk(KERN_ERR "Uable to add dev
    ");
            return ret;
        }
        printk(KERN_INFO "cdev_add success
    ");
        //第三步:2.6内核之后要向sys文件系统中添加设备
        hello_class = class_create(THIS_MODULE, "hello");
        device_create(hello_class, NULL, devno, NULL, "hello");
        printk(KERN_INFO "device created success
    ");
        return 0;
    }
    static void hello_exit(void)
    {
        cdev_del(&cdev1);
        unregister_chrdev_region(devno, 1);
        printk(KERN_ALERT "hell_exit
    ");
    }
    MODULE_LICENSE("GPL");
    module_init(hello_init);
    module_exit(hello_exit);

    test.c

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    main()
    {
        int fd;
    
        fd = open("/dev/hello",O_RDWR);
        if(fd<0)
        {
            perror("open fail 
    ");
            return ;
        }else
        {
            printf("open /dev/hello success! 
    ");
        }
    
        close(fd);
    }

    makefile

    #General Purpose Makefile for cross compile Linux Kernel module
    ifneq ($(KERNELRELEASE),)
    obj-m := hello.o  #+=是连接字符串
    else
    
    ARCH := arm    
    CROSS_COMPILE := arm-linux-gnueabihf-
    KERN_DIR := /home/zqh/lichee/linux-zero-4.14.y  #选择内核路径
    PWD :=$(shell pwd)   #当前路径
    
    all:
            $(info "1st")
            make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) modules    
    clean:                                   
            rm -f *.ko *.o *.symvers *.mod.c *.mod.o *.order .*.o.ko.cmd .*.ko.cmd .*.mod.o.cmd .*.o.cmd
            
    endif
     
  • 相关阅读:
    SharePoint 2010 Managed Metadata Columns and Metadata Navigation Settings
    SharePoint 知识整理1
    印度HCL揭秘云计算五大盈利模式
    云计算盈利模式都有什么?
    IaaS
    Salesforce
    走近云计算:解密IaaS PaaS SaaS的关系
    sasdas
    解析salesforce
    Salesforce成功的秘密
  • 原文地址:https://www.cnblogs.com/ZQQH/p/8573093.html
Copyright © 2020-2023  润新知