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********* ...
随机推荐
- Qt布局管理: 停靠窗口QDockWidget类(纯代码实现)
转载:好儿郎~志在四方 详细描述: QDockWidget类提供了一个窗体部件,其可以停靠在QMainWindow,或其本身作为一个在桌面上的顶级窗口(也就是父窗体). QDockWidget类提供了 ...
- Python3 读、写Excel文件
首先,简单介绍一下EXECL中工作簿和工作表的区别: 工作簿的英文是BOOK(WORKBOOK),工作表的英文是SHEET(WORKSHEET). 一个工作簿就是一个独立的文件 一个工作簿里面可以有1 ...
- BOS物流项目心得
定区管理 (和分区有何区别) : 区域管理针对自然行政区, 行政区域比较大,不可能让取派员去负责整个行政区域, 需要进行分区,将行政区域细分 ,成为很多小区域(分区), 需要为分区知道取派人员 , 在 ...
- (转)java基础-反射
原文地址:https://blog.csdn.net/sinat_38259539/article/details/71799078 反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的C ...
- 父级元素position:absolute,子节点也是absolute
当父级属性position是absolute,子节点也是absolute的时候,子节点是相对父级absolute的,举个例子 <div class="headManage"& ...
- Java热部署相关
今天发现早年在大象笔记中写的一篇笔记,之前放在ijavaboy上的,现在它已经访问不了了.前几天又有同事在讨论这个问题.这里拿来分享一下. 在web应用开发或者游戏服务器开发的过程中,我们时时刻刻都在 ...
- 分段覆盖率TPR
黑产监控中,需要尽可能做到尽可能少的误伤和尽可能准确地探测,可以选择“在FPR较低时的TPR加权平均值”作为平均指标. 根据混淆矩阵计算TPR(覆盖率)和FPR(打扰率): 覆盖率:TPR = TP ...
- linux驱动开发—基于Device tree机制的驱动编写
前言Device Tree是一种用来描述硬件的数据结构,类似板级描述语言,起源于OpenFirmware(OF).在目前广泛使用的Linux kernel 2.6.x版本中,对于不同平台.不同硬件,往 ...
- TFTP(Trivial File Transfer Protocol,简单文件传输协议)
网络特性 通常使用UDP 69端口(据说可改成TCP) 与FTP区别 轻量级,适用于传输小文件,当然功能也少些,比如没有列出目录功能,不进行认证
- Javascript的闭包及其使用技巧实例
Javascript的闭包及其使用技巧实例 一.闭包的基本概念 闭包(Closure)是一个引用了自由变量的函数,记录了该函数在定义时的scope chain.又称词法闭包(Lexical Closu ...