还是老规矩先上代码

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驱动开发(三) 字符设备驱动框架相关推荐

  1. 奇小葩讲设备树(3/5)-- Linux设备树详解(三)u-boot设备树的传递

    前面两节介绍了设备的基本概念.编译.结构的组成,本章讨论的主要内容为 dtb如何通过Bootloader引导程序加载到内核 bootloader如何解析dbt bootloader支持哪些dtb的操作 ...

  2. 设备树学习(三、设备树dtb格式和结构)

    上一节我们学习了dts文件的格式,dts文件是方便我们书写和读写的格式.本节我们来学习一下经过Device Tree Compiler编译,Device Tree source file变成了Devi ...

  3. 为Exynos4412移植U-Boot-2017.11(三)——DM9000A驱动

    系列文章 为Exynos4412移植U-Boot-2017.11的步骤(一) 为Exynos4412移植U-Boot-2017.11(二)--SD卡.eMMC驱动 为Exynos4412移植U-Boo ...

  4. windows无法访问指定设备_恢复 你的电脑/设备需要修改 未连接或无法访问所需设备。...

    重装系统后重启电脑就出现了:你的电脑/设备需要修复,未连接或无法访问所需设备. 错误代码:0xc000000e 这个无法连接设备.有三种原因:一,系统驱动程序出错.二.接触不良.三.设备故障.按不同的 ...

  5. 字符设备驱动模板方式(linux驱动开发篇)

    简述 下面针对led灯,编写老版字符驱动设备.新字符设备驱动.设备树驱动. 老版本驱动设备 register_chrdev和unregister_chrdev 问题: 1需要我们事先确定好哪些主设备号 ...

  6. Linux platform 设备驱动实验-基于正点原子IMX6ULL开发板

    我们以前的设备驱动都非常的简单,都是对IO进行最简单的读写操作.像I2C. SPI.LCD 这些复杂外设的驱动就不能这么去写了,Linux 系统要考虑到驱动的可重用性,因此提出了驱动的分离与分层这样的 ...

  7. 君君学Linux设备驱动第一天之概述及开发环境搭建

    一.设备驱动的作用:     1 计算机系统里面的软件和硬件是互相成就的,没有软件的硬件是废铁,没有硬件作为依托的软件是空中楼阁.     2 当应用软件工程师不想了解硬件底层的具体操作的时候,就需要 ...

  8. 应用QQ2440(s3c2440)ARM开发板驱动MMA7455加速度计的linux设备驱动编写

    课题水下机器人需要测定水下机器人的位姿,为此应用了加速度计MMA7455,该传感器可以用SPI或I2C读取数字信号到MCU. 驱动MMA7455在atmega128上已经实现,但是由于mega128的 ...

  9. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(三十一)驱动进化之路:设备树的引入及简明教程

    文章目录 1.驱动进化之路:设备树的引入及简明教程 1.1 设备树的引入与作用 1.2 设备树的语法 1.2.1 Devicetree格式 1.2.1.1 DTS文件的格式 1.2.1.2 node的 ...

最新文章

  1. 输出程序运行的时间(精确到微秒)
  2. [Math][Algebra]--线性代数中的各种空间
  3. Chrome 0 day漏洞利用链
  4. apache+mod_wsgi+django的环境配置
  5. 到国外使用wifi悠着点防止天价帐单
  6. 多除了1次100的FM BAPI_CURRENCY_CONV_TO_INTERN_9
  7. 360浏览器 当前环境不支持支付宝控件_360 小程序来了,进攻 PC 端!
  8. python调用其他类中的方法_无法调用其他类中的方法
  9. MultipartFile多文件上传
  10. createdroptargets_拖拽神器React DnD你真的了解了吗?
  11. ASPUpLoad 文件上传
  12. SQL中的go、begin、end的用法
  13. Pareto最优解 Pareto分布
  14. WINDOWS备份与恢复
  15. 激光雕刻机装上AI,混合材料T恤上都能雕出花,自动变换力度保证不割破
  16. 好好说话之Use After Free
  17. 加拿大玩具巨头斯平玛斯特在华确权维权,爆丸专利获赔超千万,汪汪队品牌获刑事保护...
  18. 电源设计经验谈1-5
  19. 阿里云跨境游戏及电商网络加速方案(全球加速和CDN)
  20. 2021| 四月行业营销活动指导方案

热门文章

  1. Linux磁盘配额(一)
  2. Java自带的常用工具
  3. Redis笔记系列(特别总结篇)——常见配置redis.conf知识点总结
  4. 【巧妙算法系列】【Uva 11464】 - Even Parity 偶数矩阵
  5. 数论概论(Joseph H.Silverman) 定理39.2 连分数相邻收敛项之差定理
  6. golang time 时间 加减法
  7. 可视化监控指标展示工具 grafana 简介
  8. php web框架 symfony简介
  9. java jar包 和 war包 区别
  10. linux rpm命令 查询包安装与否、包详细信息、包安装位置、文件属于哪个包、包依赖