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

摘要:
");ret=PTR_ERR;gotofailure_device_create;}return0;failure_device_create:class_destroy;failure_class_create:cdev_del;failure_cdev_add:unregister_chrdev_region;failure_register_chrdev:returnret;}staticvoid__exitdemo_exit{printk;/*逆序消除*///从内核中删除设备device_destroy;//从内核中删除设备类class_destroy;//删除一个cdev,完成字符设备的注销。

代码如下

#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;

structcdev cdev;

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

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

int demo_release(struct inode * inodep, struct file * filep)  //关闭设备
{
    printk("%s,%d
", __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
", __func__, __LINE__);

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

    printk("devno:%d
", devno);
    printk("demo_major:%d
", 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. "); returnret; } //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); gotofailure_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! "); ret = PTR_ERR("demo_class"); gotofailure_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! "); ret =PTR_ERR("demo_device"); gotofailure_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: returnret; } static void __exit demo_exit(void) { printk("%s,%d ", __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");
linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第1张linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第2张
KVERS = $(shell uname -r)

# Kernel modules
obj-m +=demo.o

# Specify flags forthe 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
View Code
linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第3张linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第4张
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>





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

{

    intfd;

    int val = 1;

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

    if (fd < 0)

    {

        printf("can't open!
");

        return -1;

    }

    else
    {

        printf("open success.
");

    }

 

 

    getchar();

 

 

    close(fd);



    return 0;

}
View Code

linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第5张

linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第6张

linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第7张

linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)第8张

主要使用到函数

class_create
device_create
device_destroy
class_destroy
小技巧:
类似
http://lxr.free-electrons.com/
http://lxr.oss.org.cn/
这样的网站提供了Linux内核源代码的交叉索引,
在其中输入Linux内核中的函数、数据结构或变量的名称就可以直接得到以超链接形式给出的定义和引用它的所有位置。
还有一些网站也提供了Linux内核中函数、变量和数据结构的搜索功能,
在google中搜索“linux identifier search”可得。

免责声明:文章转载自《linux驱动开发(四) 字符设备驱动框架(自动创建设备节点)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇django 视图函数返回queryset对象或日期对象至浏览器ajax接收的写法使用Linux的mail命令发送邮件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux源码编译安装和卸载

Linux下正常的编译安装/卸载 源码的安装一般由3个步骤组成: 配置(configure) 编译(make) 安装(make install)。 configure文件是一个可执行的脚本文件,它有很多选项,在待安装的源码目录下使用命令./configure –help可以输出详细的选项列表。 其中--prefix选项是配置安装目录,如果不配置该选项,...

嵌入式Linux USB WIFI驱动的移植

硬件平台:飞思卡尔MX258开发板 操作系统:Linux2.6.31 WIFI:RT2860 USB WIFI模组 交叉编译环境:gcc version 4.1.2 调试步骤: 第一步:测试USB HOST接口 在menuconfig中将USB HOST设置为内核模式: 重新编译内核后启动开发板,插入U盘并挂载: mount /dev/sda1 /tmp...

Linux软件开发常用的软件包(持续更新中)

下面是Linux开发常用的软件包: 软件包的名称 作用描述 安装方式 build-essential   sudo apt-get install build-essential policycoreutils audit2allow工具 sudo apt-get install policycoreutils vim   sudo ap...

Linux系统备份-----Respin

一,Respin方法(respin为remastersys的替代品,因为remastersys已经不再维护): 1.添加下载源: sudo add-apt-repository ppa:sergiomejia666/respin sudo add-apt-repository ppa:sergiomejia666/xresprobe 2.更新软件库...

linux系统下安装Jenkins

1、首先准备java环境,安装JDK 2、下载jenkins至Linux服务器 下载地址:https://pkg.jenkins.io/redhat-stable/ 按需选择:最新版 or 稳定版 这里选择最新版 ,使用yum方式下载安装 sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.j...

Linux Tips: 使用dd制作Ubuntu系统的安装盘

找到U盘的分区 sudo fdisk -l 卸载U盘 # 假设U盘的挂载是/dev/sdc1 sudo umount /dev/sdc1 格式化U盘 # 假设U盘是/dev/sdc,注意这里是“sdc”不带“1” sudo mkfs.vfat -I /dev/sdc 写入镜像 # 注意这里也是“sdc”不带“1” sudo dd if...