Linux字符设备驱动--No.3
字符驱动(按键)初始化函数分析:
int charDrvInit(void)
{
devNum = MKDEV(reg_major, reg_minor);
printk(KERN_EMERG"devNum is %d\r\n", devNum);
if(OK == register_chrdev_region(devNum, subDevNum, DEVICE_NAME))//subdevnum:要申请的第一个次设备号
{
printk(KERN_EMERG"register_chrdev_region ok\r\n");
}
else
{
printk(KERN_EMERG"register_chrdev_region error\r\n");
return ERROR;
}
16
/**
* register_chrdev_region() - register a range of device numbers
* @from: the first in the desired range of device numbers; must include
* the major number.
* @count: the number of consecutive device numbers required
* @name: the name of the device or driver.
*
* Return value is zero on success, a negative error code on failure.
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name) //count = 1
{
struct char_device_struct *cd;
static struct char_device_struct {
struct char_device_struct *next;
unsigned int major;
unsigned int baseminor;
int minorct;
];
struct cdev *cdev; /* will die */
} *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
struct char_device_struct
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+, );/*先得到下一个设备号(其实也是一个设备号,只不过此时的次设备号为0)并存储于next中*/
18 if (next > to) /*溢出的情况*/ /*判断在from的基础上再追加count个设备(dev_t to = from+count)是否已经溢出到下一个主设备号*/
next = to;
/* 如果没有溢出(next小于to),那么整个for语句就只执行个一次__register_chrdev_region函数;
否则当设备号溢出时,会把当前溢出的设备号范围划分为几个小范围,分别调用__register_chrdev_region函数。 */
/*
* Register a single major with a specified minor range.
*
* If major == 0 this functions will dynamically allocate a major and return
* its number.
*
* If major > 0 this function will attempt to reserve the passed range of
* minors and will return zero on success.
*
* Returns a -ve errno on failure.
*/
static struct char_device_struct *
13 __register_chrdev_region(unsigned int major, unsigned int baseminor,
14 int minorct, const char *name)
{
struct char_device_struct *cd, **cp;
;
int i;
cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
if (cd == NULL)
return ERR_PTR(-ENOMEM);
mutex_lock(&chrdevs_lock);
/* temporary */
//此if语句目的在于如果主设备号为零,则自动分配主设备号(寻找设备号列表中的空的位置(从大到小))并返回
) {
; i > ; i--) {
if (chrdevs[i] == NULL)
break;
}
) {
ret = -EBUSY;
goto out;
}
major = i;
ret = major;
}
//新元素赋值
cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
strlcpy(cd->name, name, sizeof(cd->name));
i = major_to_index(major);
/* index in the above */
static inline int major_to_index(unsigned major)
{
return major % CHRDEV_MAJOR_HASH_SIZE;
}
//寻找新元素插入的位置
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
if ((*cp)->major > major ||
((*cp)->major == major &&
(((*cp)->baseminor >= baseminor) ||
((*cp)->baseminor + (*cp)->minorct > baseminor))))
break;
/* Check for overlapping minor ranges. */
if (*cp && (*cp)->major == major) {//如果当前元素存在并且主设备号和要添加的主设备号一致
int old_min = (*cp)->baseminor;//更新旧的最小值,值为当前元素的次设备号
;////更新旧的最大值,值为当前次设备号+要申请号的设备个数-1,-1是因为从0开始的次设备号
int new_min = baseminor;//新的最小值为要添加的次设备号
;
//新的最大值为要添加的次设备号+要申请号的设备个数-1,-1是因为次设备号从0开始
/* New driver overlaps from the left. */
//显然生成的新的值必须要大于旧的最大值或者小于旧的最小值
if (new_max >= old_min && new_max <= old_max) {
ret = -EBUSY;
goto out;
}
/* New driver overlaps from the right. */
if (new_min <= old_max && new_min >= old_min) {
ret = -EBUSY;
goto out;
}
}
cd->next = *cp;
*cp = cd;
mutex_unlock(&chrdevs_lock);
return cd;
out:
mutex_unlock(&chrdevs_lock);
kfree(cd);
return ERR_PTR(ret);
}
if (IS_ERR(cd))
goto fail;
}
;
fail:
to = n;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+, );
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
return PTR_ERR(cd);
}
gDev = kzalloc(sizeof(struct cdev), GFP_KERNEL);
gFile = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
gFile->open = butsOpen;
//注册设备函数到file_operations结构体gFile
//gDev->owner = THIS_MODULE;
gFile->owner = THIS_MODULE;
cdev_init(gDev, gFile);
//在cdev结构体中添加指针指向file_operations结构体gFile
cdev_add(gDev, devNum, );
//建立设备号与cdev结构体联系
printk(KERN_EMERG"button driver initial done...\r\n");
;
}
Linux字符设备驱动--No.3的更多相关文章
- 深入理解Linux字符设备驱动
文章从上层应用访问字符设备驱动开始,一步步地深入分析Linux字符设备的软件层次.组成框架和交互.如何编写驱动.设备文件的创建和mdev原理,对Linux字符设备驱动有全面的讲解.本文整合之前发表的& ...
- Linux字符设备驱动结构(一)--cdev结构体、设备号相关知识机械【转】
本文转载自:http://blog.csdn.net/zqixiao_09/article/details/50839042 一.字符设备基础知识 1.设备驱动分类 linux系统将设备分为3类:字符 ...
- Smart210学习记录----beep linux字符设备驱动
今天搞定了beep linux字符设备驱动,心里还是很开心的,哈哈...但在完成的过程中却遇到了一个非常棘手的问题,花费了我大量的时间,,,, 还是把问题描述一下吧,好像这个问题很普遍的,网上许多解决 ...
- Linux字符设备驱动实现
Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...
- Linux字符设备驱动基本结构
1.Linux字符设备驱动的基本结构 Linux系统下具有三种设备,分别是字符设备.块设备和网络设备,Linux下的字符设备是指只能一个字节一个字节读写的设备,不能随机读取设备内存中某一数据,读取数据 ...
- (57)Linux驱动开发之三Linux字符设备驱动
1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...
- Linux字符设备驱动框架
字符设备是Linux三大设备之一(另外两种是块设备,网络设备),字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备,常见的字符设备包括鼠标.键盘.显示器.串口等等,当我们执行ls -l ...
- Linux 字符设备驱动模型
一.使用字符设备驱动程序 1. 编译/安装驱动 在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码.因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块 2. 创建设备文件 通 ...
- linux字符设备驱动学习笔记(一):简单的字符设备驱动
最近在鼓捣lnux字符设备驱动,在网上搜集的各种关于linux设备驱动的代码和注释,要么是针对2.4的,要么是错误百出,根本就不能运行成功,真希望大家在发博客的时候能认真核对下代码的正确性,特别是要把 ...
- Linux字符设备驱动
一.字符设备基础 字符设备 二.字符设备驱动与用户空间访问该设备的程序三者之间的关系 三.字符设备模型 1.Linux内核中,使用 struct cdev 来描述一个字符设备 动态申请(构造)cdev ...
随机推荐
- wcf 访问控制
public class PasswordDigestChannelFactory<TPortTypeClient, TPlugin> where TPortTypeClient : Cl ...
- Mysql学习---基础操作学习2
基本数据类型 Mysql基本数据类型:二进制,数值[整数,小数].字符串[定长,变长]. 二进制数据.时间和枚举集合 bit[(M)] 二进制位(101001),m表示二进制位的长度(1-64),默认 ...
- 一款可以安利的MarkDown编辑器
Typeora一款可以安利的MarkDown编辑器 Typeora是什么? 一款使用MarkDown的本地编辑器集结了MarkDown的所有特点并展现了简洁.高效的特点,关键是免费. 特点: 支持 ...
- python UI自动化实战记录四:测试页面1-pageobject
该部分记录测试页面1-IndexPage,所有首页上的元素定位.操作.获取属性等方法都写在该类中. 1 首页类继承自BasePage 2 首页类第一部分写的是所有的定位器 3 首页类第二部分类的方法, ...
- BZOJ3033:太鼓达人(DFS,欧拉图)
Description 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_shy和ly ...
- BZOJ2141:排队(分块,树状数组)
Description 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们 ...
- tmux 后台运行程序
之前写过tmux分屏,其实这个只是方便写代码啥的,那都还不是最重要的.跑模型时,一般一跑就是一整天都是常事. 电脑关机,睡眠,ssh连接失效都会断了程序运行. solution:tmux后台运行程序! ...
- 记录一下xcode9 添加文件夹的顺序
右击->Add Files to YourProject->弹出文件对话框,点击Options->选择:Copy Items if needed和Create Groups 要选择O ...
- qsort()与sort的用法(收藏)
sort()函数是C++中的排序函数其头文件为:#include<algorithm>头文件: qsort()是C中的排序函数,其头文件为:#include<stdlib.h> ...
- 安装sqlserver2016出现的错误
今天安装sharepoint 2016,projectserver 2016,在安装sqlserver2016的时候突然报错了,提示需要安装oracle java se, Rule “Oracle J ...