还是老规矩先上代码

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. 多组两两比较用什么检验方法_用SPSS进行不同变量多组间两两比较卡方检验.pdf...
  2. ranorex自动化测试框架开发--控件操作
  3. MySQL分库分表环境下全局ID生成方案
  4. Json 不同语言的使用
  5. Java软件研发工程师转行之深度学习(Deep Learning)进阶:手写数字识别+人脸识别+图像中物体分类+视频分类+图像与文字特征+猫狗分类
  6. solr elasticsearch比较
  7. SpringBoot 如何进行对象复制,老鸟们都这么玩的!
  8. 瑞银报告:Waymo在2030年占据全球60%无人出租车市场
  9. 数据集如何影响作物病害识别的有效性
  10. Atitit 架构师的分类 架构师都有哪些种类? 1. 应用架构师 应用架构师是行业中数量最多的架构师,主要负责公司产品的技术架构。产品架构师需要对业务有足够的理解,根据产品需求设计架构,在运营团
  11. 复化科特斯公式matlab_基于牛顿—科特斯积分的误差分析
  12. flutter图片识别_想在 flutter 中提取图片颜色?试试 color_thief_flutter
  13. excel文档查询服务器,excel服务器数据库查询语句
  14. 自媒体都在用的5个素材网站,视频、音效、图片全部免费下载~
  15. 《越狱》中的项目管理——两个版本的对比
  16. win10 EFI文件夹删除了,引导进不去了,该怎么办?
  17. excel2016打开空白解决方法
  18. VC驿站黑客编程(关机,重新启动,注销)
  19. 程序员必修内功,收集了上千本各类编程书籍【免费获取】
  20. 如何在Outlook中将所有邮件显示为纯文本

热门文章

  1. 在单元测试时指定HttpContext的各种Path
  2. Qt5开发及实例学习之标准颜色对话框类QColorDialog:选择某种颜色
  3. 云无边界,阿里云混合云数据同步发布
  4. JDK容器学习之ArrayList:底层存储和动态扩容
  5. 2017先知创新大会:有ZHI而来
  6. linux下helloworld的简单编译过程
  7. 2006上半年程序员级试题答案
  8. VI常用使用命令 为初次接触VI 的兄弟们献微利
  9. linux iptables 命令简介
  10. linux 反弹shell(一)文件描述符与重定向