linux驱动开发(三) 字符设备驱动框架(自动创建设备节点)

代码如下

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>  

int demo_major = 250;
int demo_minor = 0;
int demo_count = 1;

struct cdev cdev;

static struct class *demo_class;
static struct device *demo_device;

int  demo_open(struct inode *inodep, struct file * filep) // 打开设备
{
    printk("%s,%d\n", __func__, __LINE__);
    return 0;
}

int demo_release(struct inode * inodep, struct file * filep)  // 关闭设备
{
    printk("%s,%d\n", __func__, __LINE__);
    return 0;
}

struct file_operations  fops =
{
    .owner = THIS_MODULE,
    .open = demo_open,
    .release = demo_release,
};

static int __init demo_init(void)
{
    int ret = 0;
    dev_t  devno;

    printk("%s,%d\n", __func__, __LINE__);

    //使用下列宏则可以通过主设备号和次设备号生成 dev_t
    devno = MKDEV(demo_major, demo_minor);

    printk("devno:%d\n", devno);
    printk("demo_major:%d\n", demo_major);

    /**在调用 cdev_add()函数向系统注册字符设备之前,
      *应首先调用 register_chrdev_region()或alloc_chrdev_region()函数向系统申请设备号
      **/
    if (demo_major)
    {     //使用cat /proc/devices | grep demo 来查询
        ret = register_chrdev_region(devno, 1, "demo");
    }
    else
    {
        ret = alloc_chrdev_region(&devno, demo_minor, 1, "demo");
    }

    if(ret)
    {
        printk("Failed to register_chrdev_region.\n");
        return ret;
    } 

    //cdev_init()函数用于初始化 cdev 的成员,并建立 cdev 和 file_operations 之间的连接
    cdev_init(&cdev, &fops);
    cdev.owner = THIS_MODULE;

    //系统添加一个 cdev,完成字符设备的注册。
    ret = cdev_add(&cdev, devno, demo_count);
    if(ret)
    {
        printk(KERN_NOTICE " Failed to cdev_add [Error] %d adding demo%d", ret, demo_minor);

        goto failure_cdev_add;

    }

    /*自动创建设备节点文件*/

    //1.注册设备类  /sys/class/demo的文件夹   //使用 ls /sys/class/demo
    demo_class = class_create(THIS_MODULE, "demo");
    if( IS_ERR(demo_class))
    {
        printk("class_create failed!\n");
        ret = PTR_ERR("demo_class");
        goto failure_class_create;
    }

    //2.注册设备  /sys/class/demo/demo0      /dev/demo0
    demo_device = device_create(demo_class, NULL, MKDEV(demo_major, demo_minor), NULL, "demo%d", demo_minor);
    if(IS_ERR(demo_device)){
        printk("device_create failed!\n");
        ret = PTR_ERR("demo_device");
        goto failure_device_create;
    }
    return 0;

failure_device_create:
    class_destroy(demo_class);
failure_class_create:
    cdev_del(&cdev);
failure_cdev_add:
    unregister_chrdev_region(devno, demo_count);
failure_register_chrdev:
    return ret;
}

static void __exit demo_exit(void)
{
    printk("%s,%d\n", __func__, __LINE__);

    /*逆序消除*/
    //从内核中删除设备
    device_destroy(demo_class,MKDEV(demo_major, demo_minor));
    //从内核中删除设备类
    class_destroy(demo_class);
    //删除一个 cdev,完成字符设备的注销。
    cdev_del(&cdev);
    //在调用cdev_del()函数从系统注销字符设备之后,unregister_chrdev_region()应该被调用以释放原先申请的设备号
    unregister_chrdev_region( MKDEV(demo_major, demo_minor), demo_count );
}

module_init(demo_init);
module_exit(demo_exit);

MODULE_AUTHOR(" libra13179 ");
MODULE_LICENSE("GPL v2");

KVERS = $(shell uname -r)

# Kernel modules
obj-m += demo.o

# Specify flags for the module compilation.
#EXTRA_CFLAGS=-g -O0

build: kernel_modules

kernel_modules:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
#    @echo $(KVERS)

clean:
    make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <stdio.h>

int main(int argc, const char *argv[])

{

    int fd;

    int val = 1;

    fd = open("/dev/demo0", O_RDWR);

    if (fd < 0)

    {

        printf("can‘t open!\n");

        return -1;

    }

    else

    {

        printf("open success.\n");

    }

    getchar();

    close(fd);

    return 0;

}

原文地址:https://www.cnblogs.com/libra13179/p/9370045.html

时间: 2024-09-29 12:25:40

linux驱动开发(三) 字符设备驱动框架(自动创建设备节点)的相关文章

【Linux驱动】自动创建设备节点

开始学习驱动的时候,是将驱动程序编译成模块然后用mknod命令手动建立设备节点以提供给应用程序调用.这对于刚开始调试驱动程序的时候常用的一种方法.但是,当有种需要必须在系统启动的时候就将驱动程序就绪,来供应用层程序调用.这时就不能再手动的建立设备节点了,而必须自动的创建设备节点(不需要人为的操作). ★注册类 注册类的目的是为了使mdev可以在/dev/目录下建立设备节点. 首先要定义一个类,利用struct class结构体.这个结构体定义在头文件include/linux/device.h中

linux字符设备-自动创建设备号和设备节点

Linux字符设备-自动创建设备号和设备节点 先写一个自动分配字符设备号和设备节点的例子及APP 手动安装步骤: Insmod my_char_dev.ko 不需要再安装设备节点 然后是测试app ./my_char_dev_app 1 1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/io.h> 4 #include <linux/fs.h> 5 #include

国嵌内核驱动进阶班-7-5(自动创建设备文件)

linux 2.6.13 开始,devfs不存在,udev取代devfs. udev(mdev)存在应用层,可以实现设备文件的自动创建和删除. 过程: 驱动代码调用class_create创建一个class,再为每个设备调用class_create创建对应的设备. ※ 自动创建设备文件需要udev的支持 struct class *myclass =  class_create(THIS_MODULE, "mydriver"); device_create(myclass,NULL,

如何自动创建设备节点

创建设备文件的方法: 第一种是使用mknod手工创建:mknod filename type major minor 第二种是自动创建设备节点:利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(嵌入式系统用mdev),由busybox配置. udev介绍 udev 运行在用户模式,而非内核中.udev 的初始化脚本在系统启动时创建设备节点,并且当插入新设备--加入驱动模块--在sysfs上注册新的数据后,udev会创新新的设备节点. udev 是一个工作在用户空间的工具,

class_create(),device_create自动创建设备文件结点

class_create(),device_create自动创建设备文件结点 从linux 内核2.6的某个版本之后,devfs不复存在,udev成为devfs的替代.相比devfs,udev有很多优势,在此就不罗嗦了,提醒一 点,udev是应用层的东东,不要试图在内核的配置选项里找到它;加入对udev的支持很简单,以作者所写的一个字符设备驱动为例,在驱动初始化的代码里调用class_create为该设备创建一个class,再为每个设备调用 class_device_create创建对应的设备.

自动创建设备节点class_create 和device_create

刚开始学习驱动的时候,每次都需要mknod /dev/timer c 500 0 这样手动去创建一个设备节点:实际上Linux内核提供一组函数,可以用来在驱动模块加载的时候自动在/dev目录下创建相应的设备节点,并在下载的时候删该节点. device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)和device_destroy(struct cla

platform型设备在/dev目录下自动创建设备节点的分析【转】

转自:http://blog.csdn.net/rockrockwu/article/details/7357648 系统启动过程中platform设备.驱动注册完毕,为什么在/dev目录下就自动创建好设备节点了? 在/dev目录自动创建设备节点可以通过class_create(),然后再device_create().但是在跟踪 内核platform注册过程中可以发现,其实这里面并未调用上诉两个函数,那么platform注册后 如何在/dev目录下创建设备文件节点? [cpp] view pl

驱动开发--【字符设备、块设备简介】【sky原创】

驱动开发   字符设备,块设备,网络设备 字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问 EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是直接访问硬件的 flash 擦写次数有限,一百万次,容易有坏块 块设备 能随机访问 以”块“为单位进行访问 块大小一般为512字节 块的大小由硬件决定 是内核进行数据传输的基本单位 硬盘结构: 格式化分区是以柱面为单位的,即硬盘的柱面 如果有10个盘面,就有十个柱面 对于嵌入式设备 如果是flash的话,结

初入android驱动开发之字符设备(五-定时器)

这个字符设备系列,主要借助较容易上手的字符设备实例,去讲解linux的一些机制,以及驱动中比较常用到的中断.定时器.信号量等一些知识,由于本人自身的知识有限,对于arm的架构体系不太了解,这里,一般这里只讲,如何去用,对于一些原理性的东西不会深究,以后的文章会慢慢的加深. 想想我们当初玩51单片机的时候,那时候按键防抖是一个硬件.软件都需要处理的地方.软件一般就是加延时检测判断.当然,这里我们也可以用到定时器的这个机制,做按键驱动,这里主要还是以按键为例,但不是讲的按键防抖. 1. 定时器的一些