linux驱动开发(三) 字符设备驱动框架
还是老规矩先上代码
demo.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h> int demo_major = ;
int demo_minor = ;
int demo_count = ; struct cdev cdev; int demo_open(struct inode *inodep, struct file * filep) // 打开设备
{
printk("%s,%d\n", __func__, __LINE__);
return ;
} int demo_release(struct inode * inodep, struct file * filep) // 关闭设备
{
printk("%s,%d\n", __func__, __LINE__);
return ;
} struct file_operations fops =
{
.owner = THIS_MODULE,
.open = demo_open,
.release = demo_release,
}; static int __init demo_init(void)
{
int ret = ;
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, , "demo");
}
else //动态分配
{
ret = alloc_chrdev_region(&devno, , , "demo");
} if(ret)
{
printk("Failed to register_chrdev_region.\n");
return ret;
} //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);
return ret;
} return ;
} 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 flags for the 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中使用到函数和宏,结构体等
<linux/cdev.h>
使用cdev结构体描述一个字符设备
struct cdev
{
struct kobject kobj; /* 内嵌的 kobject 对象 */
struct module *owner; /*所属模块*/
struct file_operations *ops; /*文件操作结构体*/
struct list_head list;
dev_t dev; /*设备号*/
unsigned int count;
};
cdev结构体
cdev 结构体的 dev_t 成员定义了设备号,为 32 位,其中 12 位主设备号,20 位次设备号。
比较用到三个宏
<linux/kdev_t.h>
#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)
<linux/cdev.h>
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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h> int main(int argc, const char *argv[])
{
int fd;
int val = ;
fd = open("/dev/xyz", O_RDWR);
if (fd < )
{
printf("can't open!\n");
return -;
}
else
{
printf("open success.\n");
} getchar(); close(fd); return ;
}
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
root@lin-virtual-machine:/home/lin/demo# ./demodrvtest
open success.
这边使用手动来创建
手动创建设备 mknod命令
命令的格式是:mknod 设备名 设备类型(字符:c,块:b) 主设备号 从设备号
linux驱动开发(三) 字符设备驱动框架的更多相关文章
- Linux驱动开发2——字符设备驱动
1.申请设备号 #include <linux/fs.h> int register_chrdev_region(dev_t first, unsigned int count, char ...
- Linux驱动开发之字符设备驱动模型之file_operations
90%的驱动模型都是按照下图开发的 下面来说下设备描述结构是什么东西 打开Linux-2.6.32.2的Source Insight 工程,搜索cdev 比如一个应用程序需要调用read和write这 ...
- LCD驱动分析(一)字符设备驱动框架分析
参考:S3C2440 LCD驱动(FrameBuffer)实例开发<一> S3C2440 LCD驱动(FrameBuffer)实例开发<二> LCD驱动也是字符设备驱动,也 ...
- 初入android驱动开发之字符设备(一)
大学毕业,初入公司,招进去的是android驱动开发工程师的岗位,那时候刚进去,首先学到的就是如何搭建kernel.android的编译环境,然后就是了解如何刷设备以及一些最基本的工具.如adb.fa ...
- Linux应用程序访问字符设备驱动详细过程【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51346532 下面先通过一个编写好的内核驱动模块来体验以下字符设备驱动 可以暂时 ...
- Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程
/*********************************************************************************** * * 字符设备驱动基本操作及 ...
- 驱动开发--【字符设备、块设备简介】【sky原创】
驱动开发 字符设备,块设备,网络设备 字符设备 以字节流的方式访问, 不能随机访问 有例外,显卡.EEPROM可以随机访问 EEPROM可以擦写1亿次,是一种字符设备,可以随机访问 读写是 ...
- 初入android驱动开发之字符设备(四-中断)
上一篇讲到android驱动开发中,应用是怎样去操作底层硬件的整个流程,实现了按键控制led的亮灭.当然,这是一个非常easy的实例,只是略微演变一下,就能够得到广泛的应用. 如开发扫描头,应用透过监 ...
- 【Linux 驱动】简单字符设备驱动架构(LED驱动)
本文基于icool210开发板,内核版本:linux2.6.35: 驱动代码: (1)头文件:led.h #ifndef __LED_H__ #define __LED_H__ #define LED ...
- Linux驱动开发之字符设备模板
/***************************** ** 驱动程序模板* 版本:V1* 使用方法(末行模式下):* :%s/xxx/"你的驱动名称"/g********* ...
随机推荐
- 树莓派Raspberry Pi zero w无线联网实测
第一次学习树莓派,使用的是Raspberry Pi zero w的型号. 刚开始,就只有一块板子!!!这要怎么开发啊 经过网上查阅资料,发现可以通过WiFi连接PC端实现开发测试 准备材料:一根USB ...
- Console.WriteLine的小用法
我在一开始使用Console.WriteLine的时候,经常采用的是拼接字符串的形式来构建输出. 但是Console.WriteLine具有扩展的方法来对内容进行输出,类似于我们常用的String.F ...
- 弹性势能,position,min用法,获取元素的宽
弹性势能: 网页div移动的mousemove的次数,跟div移动的距离没有关系,跟鼠标移动的快慢有关,浏览器自身有个计数事件,几毫秒 _this.seed*=0.95 //摩擦系数的写法 posit ...
- Oracle 存储过程起步
存储过程的注释不能写在第一行 select后面要有into create or replace procedure DelEmp(v_empno in emp.empno%type) AS No_re ...
- 00006 - Linux中使用export命令设置环境变量
功能说明:设置或显示环境变量. #################################################################################### ...
- 网络基础和python
·五层协议 物理层,数据链路层,网络层,传输层,应用层 ·用户上网流程 1.本机获取 2.打开浏览器,,输入网址. 3.dns协议(基于udp协议) 4.HTTP部分的内容 5 TCP协议 6 IP协 ...
- Android WebView清空缓存
Android原生和H5混合开发,要求用户退出登录后清空H5所有的缓存: 1.清空Cookie CookieSyncManager.createInstance(context.getApplicat ...
- 零基础学习python_字符串(14-15课)
今天回顾下我之前学习python的第一个对象——字符串,这个对象真蛋疼,因为方法是最多的,也是最常见的类型,没有之一... 内容有点多,我就搜了下网上的资料,转载下这个看起来还不错的网址吧:http: ...
- Python中__new__的作用
__new__ 的作用 依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径.还 ...
- JSP 调用java 常量 枚举
JAVA:public enum ReimStatus { UNCONFIRMED ("118001"), //未确认 DISPATCH_VERIFY("118002&q ...