字符设备驱动第四课----自动生成设备
来源:互联网 发布:上传淘宝图片尺寸 编辑:程序博客网 时间:2024/04/29 13:12
【概述】
前面的时候我们要在应用程序中使用我们自己写的内核模块要做以下步骤:
1.insmod
2.mknod /dev/demo1 c 250 0
3.在运用程序中调用open(“/dev/demo1”,O_RDWR)打开我们自己创建的设备
现在问题来了,难道每次使用设备都要让用户(写运用程序的人)自己去创建设备吗?这显然不好,所以本节课就要解决“在驱动中自动创建设备”这个问题。
【涉及到的内核接口函数】
1.创建一个类
其实质是个目录,将同一类设备(共用同一个驱动程序的设备)归纳到其目录下,目录下是具体的设备。
/** 功能: 创建一个目录* 输入参数: owner:THIS_MODULE* name:目录名* 返回值: 成功:返回对象指针 失败:错误码*/struct class *class_create(owner, name)
2.创建一个设备:
跟手动敲mknod命令效果一样
<driver/base/core.h>/** 功能:创建一个设备* 输入参数:struct class *:所属对象,上一步创建的对象* struct device *parent:父设备* dev_t:将要创建的设备* void *drvdata:驱动传入的一些数据* const char *fmt:路径* 返回值:成功:返回所创建的设备 失败:返回错误码*/struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
3.销毁一个设备:
跟手动敲rmnod命令效果一样
<drivers/base/core.c>/** 功能: 销毁指定设备* 输入参数:struct class:所属类的指针* dev_t:设备号* 返回值: none*/void device_destroy(struct class *class, dev_t devt)
4.销毁一个类:
<drivers/base/driver.h>/** 功能: 销毁一个类* 输入参数:struct class *:类指针* 返回值:none*/void class_destroy(struct class *cls);
【工程实例】
#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/errno.h>#include <asm/current.h>#include <linux/sched.h>#include <linux/device.h>static struct class *cls = NULL;static int major = 0;static int minor = 0;const int count = 6;#define DEVNAME "demo"static struct cdev *demop = NULL;//打开设备static int demo_open(struct inode *inode, struct file *filp){ //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); return 0;}//关闭设备static int demo_release(struct inode *inode, struct file *filp){ //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); return 0;}//读设备//ssize_t read(int fd, void *buf, size_t count)static ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *offset){ struct inode *inode = filp->f_path.dentry->d_inode; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); return 0;}//写设备static ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset){ struct inode *inode = filp->f_path.dentry->d_inode; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); return 0;}static struct file_operations fops = { .owner = THIS_MODULE, .open = demo_open, .release= demo_release, .read = demo_read, .write = demo_write,};static int __init demo_init(void){ dev_t devnum; int ret, i; struct device *devp = NULL; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //1. alloc cdev obj demop = cdev_alloc(); if(NULL == demop){ return -ENOMEM; } //2. init cdev obj cdev_init(demop, &fops); ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME); if(ret){ goto ERR_STEP; } major = MAJOR(devnum); //3. register cdev obj ret = cdev_add(demop, devnum, count); if(ret){ goto ERR_STEP1; } cls = class_create(THIS_MODULE, DEVNAME); if(IS_ERR(cls)){ ret = PTR_ERR(cls); goto ERR_STEP1; } for(i = minor; i < (count+minor); i++){ devp = device_create(cls, NULL, MKDEV(major, i), NULL, "%s%d", DEVNAME, i); if(IS_ERR(devp)){ ret = PTR_ERR(devp); goto ERR_STEP2; } } //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - ok.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return 0;ERR_STEP2: for(--i; i >= minor; i--){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls);ERR_STEP1: unregister_chrdev_region(devnum, count);ERR_STEP: cdev_del(demop); //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - fail.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return ret;}static void __exit demo_exit(void){ int i; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - leave.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); for(i=minor; i < (count+minor); i++){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls); unregister_chrdev_region(MKDEV(major, minor), count); cdev_del(demop);}module_init(demo_init);module_exit(demo_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Farsight");MODULE_DESCRIPTION("Demo for kernel module");
0 0
- 字符设备驱动第四课----自动生成设备
- 字符设备驱动第十一课----设备树
- 字符设备驱动高级篇3——自动创建字符设备驱动的设备文件
- 高级字符设备驱动-自动创建设备文件笔记
- 简单字符设备驱动和自动创建设备文件
- 简单字符设备驱动和自动创建设备文件
- linux驱动开发--字符设备:自动创建设备节点
- linux字符设备驱动中自动创建设备节点
- Linux字符设备驱动自动创建设备节点
- linux字符设备驱动中自动创建设备节点【转】
- linux驱动开发--字符设备:自动创建设备节点
- linux字符设备驱动之设备节点的自动创建
- linux驱动开发之字符设备--自动创建设备节点
- linux字符设备驱动:自动创建设备及其节点
- Linux创建字符设备 自动生成设备节点
- Linux创建字符设备 自动生成设备节点
- Linux创建字符设备 自动生成设备节点
- 字符设备驱动--- 设备操作
- Oracle12c安装后忘记用户名和密码可通过如下方法解决:
- 1. TCP的三次握手和四次挥手
- 修改mysql表的字段为自增长
- [BZOJ3223]文艺平衡树 splay
- 基于Apache Mahout的电影推荐系统
- 字符设备驱动第四课----自动生成设备
- Keras一些基本概念
- 51nod 1405 树的距离之和【树型dp】
- 第十三周:C语言:学生成绩
- 1046. Plane Spotting
- javaSE api
- 第三章 高质量的代码 打印1到最大的n位数
- 快速幂取模算法
- php jpgraph的中文乱码问题及解决方法