linux驱动开发字符设备,linux驱动开发(三) 字符设备驱动框架
还是老规矩先上代码
demo.c
#include #include#include#include#include
int demo_major = 250;int demo_minor = 0;int demo_count = 1;structcdev cdev;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)//静态申请
{
ret= register_chrdev_region(devno, 1, "demo");
}else//动态分配
{
ret= alloc_chrdev_region(&devno, 0, 1, "demo");
}if(ret)
{
printk("Failed to register_chrdev_region.\n");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_count);
unregister_chrdev_region(devno, demo_count);returnret;
}return 0;
}static void __exit demo_exit(void)
{
printk("%s,%d\n", __func__, __LINE__);//删除一个 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");
Makefile
VERS = $(shell uname -r)
# Kernel modules
obj-m +=demo.o
# Specify flagsforthe module compilation.
#EXTRA_CFLAGS=-g -O0
build: kernel_modules
kernel_modules:
make-C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
make-C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
make测试一下
使用dmesg指令来查看
使用 cat /proc/devices看到demo的信息
下面截图来自https://blog.csdn.net/u012142460/article/details/78932165
现在主要介绍demo.c中使用到函数和宏,结构体等
使用cdev结构体描述一个字符设备
1 structcdev2 {3 struct kobject kobj; /*内嵌的 kobject 对象*/
4 struct module *owner; /*所属模块*/
5 struct file_operations *ops; /*文件操作结构体*/
6 structlist_head list;7 dev_t dev; /*设备号*/
8 unsigned intcount;9 };
cdev结构体
cdev 结构体的 dev_t 成员定义了设备号,为 32 位,其中 12 位主设备号,20 位次设备号。
比较用到三个宏
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
用下列宏可以从 dev_t 获得主设备号和次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
使用下列宏则可以通过主设备号和次设备号生成 dev_t:
MKDEV(int major, int minor)
void cdev_init(struct cdev *, const struct file_operations *);//初始化cdev的成员,并建立cdev和file_operations之间关联起来struct cdev *cdev_alloc(void);//动态申请(构造)cdev内存(设备对象)void cdev_put(struct cdev *p);//释放cdev内存int cdev_add(struct cdev *, dev_t, unsigned);//注册cdev设备对象(添加到系统字符设备列表中)void cdev_del(struct cdev *);//将cdev对象从系统中移除(注销 )
/切割线//
我们增加一个测试
#include #include#include#include
int main(int argc, const char *argv[])
{intfd;int val = 1;
fd= open("/dev/xyz", O_RDWR);if (fd < 0)
{
printf("can't open!\n");return -1;
}else{
printf("open success.\n");
}
getchar();
close(fd);return 0;
}
root@lin-virtual-machine:/home/lin/demo# gcc -o demodrvtest demodrvtest.c
root@lin-virtual-machine:/home/lin/demo# ls
demo~ demodrvtest demo.mod.c Makefile~ Untitled Document~
demo.c demodrvtest.c demo.mod.o modules.order
demo.c~ demo.ko demo.o Module.symvers
root@lin-virtual-machine:/home/lin/demo# pwd/home/lin/demo
root@lin-virtual-machine:/home/lin/demo# ./demodrvtest
can't open!
root@lin-virtual-machine:/home/lin/demo# mknod /dev/xyz c 250 0root@lin-virtual-machine:/home/lin/demo# ./demodrvtest
open success.
这边使用手动来创建
手动创建设备 mknod命令
命令的格式是:mknod 设备名 设备类型(字符:c,块:b) 主设备号 从设备号
linux驱动开发字符设备,linux驱动开发(三) 字符设备驱动框架相关推荐
- 奇小葩讲设备树(3/5)-- Linux设备树详解(三)u-boot设备树的传递
前面两节介绍了设备的基本概念.编译.结构的组成,本章讨论的主要内容为 dtb如何通过Bootloader引导程序加载到内核 bootloader如何解析dbt bootloader支持哪些dtb的操作 ...
- 设备树学习(三、设备树dtb格式和结构)
上一节我们学习了dts文件的格式,dts文件是方便我们书写和读写的格式.本节我们来学习一下经过Device Tree Compiler编译,Device Tree source file变成了Devi ...
- 为Exynos4412移植U-Boot-2017.11(三)——DM9000A驱动
系列文章 为Exynos4412移植U-Boot-2017.11的步骤(一) 为Exynos4412移植U-Boot-2017.11(二)--SD卡.eMMC驱动 为Exynos4412移植U-Boo ...
- windows无法访问指定设备_恢复 你的电脑/设备需要修改 未连接或无法访问所需设备。...
重装系统后重启电脑就出现了:你的电脑/设备需要修复,未连接或无法访问所需设备. 错误代码:0xc000000e 这个无法连接设备.有三种原因:一,系统驱动程序出错.二.接触不良.三.设备故障.按不同的 ...
- 字符设备驱动模板方式(linux驱动开发篇)
简述 下面针对led灯,编写老版字符驱动设备.新字符设备驱动.设备树驱动. 老版本驱动设备 register_chrdev和unregister_chrdev 问题: 1需要我们事先确定好哪些主设备号 ...
- Linux platform 设备驱动实验-基于正点原子IMX6ULL开发板
我们以前的设备驱动都非常的简单,都是对IO进行最简单的读写操作.像I2C. SPI.LCD 这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的 ...
- 君君学Linux设备驱动第一天之概述及开发环境搭建
一.设备驱动的作用: 1 计算机系统里面的软件和硬件是互相成就的,没有软件的硬件是废铁,没有硬件作为依托的软件是空中楼阁. 2 当应用软件工程师不想了解硬件底层的具体操作的时候,就需要 ...
- 应用QQ2440(s3c2440)ARM开发板驱动MMA7455加速度计的linux设备驱动编写
课题水下机器人需要测定水下机器人的位姿,为此应用了加速度计MMA7455,该传感器可以用SPI或I2C读取数字信号到MCU. 驱动MMA7455在atmega128上已经实现,但是由于mega128的 ...
- 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程
文章目录 1.驱动进化之路:设备树的引入及简明教程 1.1 设备树的引入与作用 1.2 设备树的语法 1.2.1 Devicetree格式 1.2.1.1 DTS文件的格式 1.2.1.2 node的 ...
最新文章
- 多组两两比较用什么检验方法_用SPSS进行不同变量多组间两两比较卡方检验.pdf...
- ranorex自动化测试框架开发--控件操作
- MySQL分库分表环境下全局ID生成方案
- Json 不同语言的使用
- Java软件研发工程师转行之深度学习(Deep Learning)进阶:手写数字识别+人脸识别+图像中物体分类+视频分类+图像与文字特征+猫狗分类
- solr elasticsearch比较
- SpringBoot 如何进行对象复制,老鸟们都这么玩的!
- 瑞银报告:Waymo在2030年占据全球60%无人出租车市场
- 数据集如何影响作物病害识别的有效性
- Atitit 架构师的分类 架构师都有哪些种类? 1. 应用架构师 应用架构师是行业中数量最多的架构师,主要负责公司产品的技术架构。产品架构师需要对业务有足够的理解,根据产品需求设计架构,在运营团
- 复化科特斯公式matlab_基于牛顿—科特斯积分的误差分析
- flutter图片识别_想在 flutter 中提取图片颜色?试试 color_thief_flutter
- excel文档查询服务器,excel服务器数据库查询语句
- 自媒体都在用的5个素材网站,视频、音效、图片全部免费下载~
- 《越狱》中的项目管理——两个版本的对比
- win10 EFI文件夹删除了,引导进不去了,该怎么办?
- excel2016打开空白解决方法
- VC驿站黑客编程(关机,重新启动,注销)
- 程序员必修内功,收集了上千本各类编程书籍【免费获取】
- 如何在Outlook中将所有邮件显示为纯文本