• linux 2.6 一个简单的字符驱动程序


    //#globalvar.c
    #include    //模块所需的大量符号和函数定义
    #include      //指定初始化和清楚函数
    #include        //文件系统相关的函数和头文件
    #include      //cdev结构的头文件
    #include     //在内核和用户空间中移动数据的函数
    MODULE_LICENSE("GPL");      //指定代码使用的许可证
    //文件操作函数的声明
    int globalvar_open(struct inode *, struct file *);
    int globalvar_release(struct inode *, struct file *);
    ssize_t globalvar_read(struct file *, char *, size_t, loff_t *);
    ssize_t globalvar_write(struct file *, const char *, size_t, loff_t *);

    int dev_major = 50;     //指定主设备号
    int dev_minor = 0;      //指定次设备号
    struct file_operations globalvar_fops=  //将文件操作与分配的设备号相连
    {
        owner: THIS_MODULE,                 //指向拥有该模块结构的指针
        open: globalvar_open,
        release: globalvar_release,
        read: globalvar_read,
        write: globalvar_write,
    };
     
    struct globalvar_dev                //用来表示我们定义设备的结构
    {
        int global_var;                 //这个变量代表要操作的设备
        struct cdev cdev;               //内核中表示字符设备的结构
    };
     
    struct globalvar_dev *my_dev;       //设备结构的指针
     
    static void __exit globalvar_exit(void)         //退出模块时的操作
    {
        dev_t devno=MKDEV(dev_major, dev_minor);    //dev_t是用来表示设备编号的结构
      
        cdev_del(&my_dev->cdev);                    //从系统中移除一个字符设备
        kfree(my_dev);                              //释放自定义的设备结构
        unregister_chrdev_region(devno, 1);         //注销已注册的驱动程序
      
        printk("globalvar unregister success/n");
    }
     
    static int __init globalvar_init(void)          //初始化模块的操作
    {
        int ret, err;
        dev_t devno=MKDEV(dev_major, dev_minor);
        //动态分配设备号,次设备号已经指定
        ret=alloc_chrdev_region(&devno, dev_minor, 1, "globalvar");
        //保存动态分配的主设备号
        dev_major=MAJOR(devno);
        //根据期望值分配设备号
        //ret=register_chrdev_region(devno, 1, "globalvar");
        if(ret<0)
        {
            printk("globalvar register failure/n");
            globalvar_exit();                      //如果注册设备号失败就退出系统
            return ret;
        }
        else
        {
            printk("globalvar register success/n");
        }
        //为设备在内核空间分配空间
        my_dev=kmalloc(sizeof(struct globalvar_dev), GFP_KERNEL);
        if(!my_dev)
        {
            ret=-ENOMEM;                           //如果分配失败返回错误信息
            printk("create device failed/n");
        }
        else                                       //如果分配成功就可以完成设备的初始化
        {
            my_dev->global_var=0;                        //设备变量初始化为0
            cdev_init(&my_dev->cdev, &globalvar_fops);   //初始化设备中的cdev结构
            my_dev->cdev.owner=THIS_MODULE;              //初始化cdev中的所有者字段
            //my_dev->cdev.ops=&globalvar_fops;
            err=cdev_add(&my_dev->cdev, devno, 1);       //向内核添加这个cdev结构的信息
            if(err<0)
                printk("add device failure/n");          //如果添加失败打印错误消息
        }
        return ret;
    }
    //打开设备文件系统调用对应的操作
    int globalvar_open(struct inode *inode, struct file *filp)
    {
        struct globalvar_dev *dev;
        //根据inode结构的cdev字段,获得整个设备结构的指针
        dev=container_of(inode->i_cdev, struct globalvar_dev, cdev);
        //将file结构中的private_data字段指向已分配的设备结构
        filp->private_data=dev;
        return 0;
    }
    //关闭设备文件系统调用对应的操作
    int globalvar_release(struct inode *inode, struct file *filp)
    {
        return 0;
    }
    //读设备文件系统调用对应的操作
    ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
    {
        //获取指向已分配数据的指针
        struct globalvar_dev *dev=filp->private_data;
        //将设备变量值复制到用户空间
        if(copy_to_user(buf, &dev->global_var, sizeof(int)))
        {
            return -EFAULT;
        }
        return sizeof(int);    //返回读取数据的大小
    }
    //写设备文件系统调用对应的操作
    ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off)
    {
        //获取指向已分配数据的指针
        struct globalvar_dev *dev=filp->private_data;
        //从用户空间复制数据到内核中的设备变量
        if(copy_from_user(&dev->global_var, buf, sizeof(int)))
        {
            return -EFAULT;
        }
        return sizeof(int);    //返回写数据的大小
    }
     
    module_init(globalvar_init);        //模块被装载时调用globalvar_init
    module_exit(globalvar_exit);        //模块被卸载时调用globalvar_exit
     

    ++++++++++++++++++++++++++++++++++++++++++++++++++++


    # Makefile

    ifneq ($(KERNELRELEASE), )
        obj-m := globalvar.o
    else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)
    all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    clean:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
    endif


    ++++++++++++++++++++++++++++++++++++++++++++++++++++


    //#test.c
    #include
    #include
    #include
    #include
     
    main()
    {
        int fd, num;
        fd=open("/dev/globalvar", O_RDWR, S_IRUSR|S_IWUSR);     //可读写方式打开设备文件
        if(fd!=-1)
        {
            read(fd, &num, sizeof(int));                        //读取设备变量
            printf("The globalvar is %d/n", num);
     
            printf("Please input the num written to globalvar/n");
            scanf("%d", &num);
            write(fd, &num, sizeof(int));                       //写设备变量
     
            read(fd, &num, sizeof(int));                        //再次读取刚才写的值
            printf("The globalvar is %d/n", num);
     
            close(fd);                                          //关闭设备文件
        }
        else
        {
            printf("Device open failure/n");
        }
    }



    ++++++++++++++++++++++++++++++++++++++++++++++++++++


    # gcc test.c
    # mknod /dev/globalvar c 251 0
    # rmmod globalvar.ko
    # insmod globalvar.ko
    # ./a.out

    <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
    阅读(362) | 评论(0) | 转发(1) |
    0

    上一篇:EI SCI

    下一篇:javascript 列表 多选 左右移动

    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    一些 好的链接
    图像滤波算法
    minigui中使用ttf字体库流程
    国庆长假归来
    vs2015 快捷键
    R11 u盘不能自动识别
    qt 自定义折线图
    qt QThread
    qt动态库编译和链接
    scons 库文件生成和链接
  • 原文地址:https://www.cnblogs.com/ztguang/p/12647221.html
Copyright © 2020-2023  润新知