内核 中每个字符 设备 都对应一个 cdev 结构的变量,下面是它的定义:
linux -2.6.22/include/linux/cdev.h
struct cdev {
struct kobject kobj;          // 每个 cdev 都是一个 kobject
struct module *owner;       // 指向实现驱动的模块
const struct file_operations *ops;   // 操纵这个字符设备文件的方法
struct list_head list;       // 与 cdev 对应的字符设备文件的 inode->i_devices 的链表头
dev_t dev;                   // 起始设备编号
unsigned int count;       // 设备范围号大小
};
一个 cdev 一般它有两种定义初始化方式:静态的和动态的。
静态 内存 定义初始化:
struct cdev my_cdev;
cdev_init(&my_cdev, &fops);
my_cdev.owner = THIS_MODULE;
动态内存定义初始化:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &fops;
my_cdev->owner = THIS_MODULE;

两种使用方式的 功能 是一样的,只是使用的内存区不一样,一般视实际的数据结构需求而定。
下面贴出了两个函数的代码,以具体看一下它们之间的差异。
struct cdev *cdev_alloc(void)
{
struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
if (p) {
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj, &ktype_cdev_dynamic);
}
return p;
}
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev); 注1;
   INIT_LIST_HEAD(&cdev->list);
kobject_init(&cdev->kobj, &ktype_cdev_default);
cdev->ops = fops;
}
由此可见,两个函数完成都功能基本一致,只是 cdev_init() 还多赋了一个 cdev->ops 的值。
初始化 cdev 后,需要把它添加到 系统 中去。为此可以调用 cdev_add() 函数。传入 cdev 结构的指针,起始设备编号,以及设备编号范围。
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
p->dev = dev;
p->count = count;
return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
关于 kobj_map() 函数就不展开了,我只是大致讲一下它的原理。内核中所有都字符设备都会记录在一个 kobj_map 结构的 cdev_map 变量中。这个结构的变量中包含一个散列表用来快速存取所有的对象。kobj_map() 函数就是用来把字符设备编号和 cdev 结构变量一起保存到 cdev_map 这个散列表里。当后续要打开一个字符设备文件时,通过调用 kobj_lookup() 函数,根据设备编号就可以找到 cdev 结构变量,从而取出其中的 ops 字段。
当一个字符设备驱动不再需要的时候(比如模块卸载),就可以用 cdev_del() 函数来释放 cdev 占用的内存。
void cdev_del(struct cdev *p)
{
cdev_unmap(p->dev, p->count);
kobject_put(&p->kobj);
}
其中 cdev_unmap() 调用 kobj_unmap() 来释放 cdev_map 散列表中的对象。kobject_put() 释放 cdev 结构本身。

注1:
Memset  用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘\0’;
例:char a[100];memset(a, '\0', sizeof(a));
memcpy  用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度。
例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。
Strcpy   就只能拷贝字符串了,它遇到'\0'就结束拷贝。
例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。

memset主要应用是初始化某个内存空间。
memcpy 是用于copy源空间的数据到目的空间中。

strcpy用于字符串copy,遇到‘\0’,将结束。

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/101356/showart_2050054.html

Linux 内核中的 cdev_alloc和cdev_add相关推荐

  1. linux内核的外部接口函数,linux内核中GPIO的使用(二)--标准接口函数

    在linux内核中,有一些基本模块可以使用标准的接口函数来操作,比如GPIO.interrupt.clock,所谓的标准接口函数是指一些与硬件平台无关的.linux下做驱动通用的函数, 常用的有: g ...

  2. Linux内核中锁机制之完成量、互斥量

    在上一篇博文中笔者分析了关于信号量.读写信号量的使用及源码实现,接下来本篇博文将讨论有关完成量和互斥量的使用和一些经典问题. 八.完成量 下面讨论完成量的内容,首先需明确完成量表示为一个执行单元需要等 ...

  3. 简单谈一点linux内核中套接字的bind机制--数据结构以及端口确定

    众所周知,创建一个套接字可以bind到一个特定的ip地址和端口,实际上套接字这一概念代表了TCP/IP协议栈的应用层标识,协议栈中的应用层就是通过一个ip地址和一个端口号标识的,当然这仅仅是对于TCP ...

  4. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  5. 如何放出Linux内核中的链表大招

    前言 上回,我们说到Linux内核中max()宏的终极奥义,Linux内核链表也不甘示弱,那么接下来,让我们看看Linux内核中的链表大招. 如何放出Linux内核中的链表大招 前言 一.链表简介 ( ...

  6. Linux内核中max()宏的奥妙何在?(一)

    Linux内核中max()宏的奥妙何在?(一) 1.max()宏那点事 在Linux内核中,有这样四个比较大小的函数,如下: max(x,y) //两个数求最大值 min(x,y) //两个数求最小值 ...

  7. Linux内核中max()宏的奥妙何在?(二)——大神Linus对这个宏怎么看?

    最新max()宏 上回,我们在<Linux内核中max()宏的奥妙何在?(一)>一文中说到,在3.18.34版Linux内核源码中的max()宏,采用了GCC的扩展特性,可以避免一些错误. ...

  8. Linux中文件描述符1,linux内核中的文件描述符(一)--基础知识简介

    原标题:linux内核中的文件描述符(一)--基础知识简介 Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blo ...

  9. Linux 内核中的 GCC 特性(zz)

    from:http://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux ...

最新文章

  1. 正则表达式的常用方法和属性
  2. blast | diamond 输出结果选择和解析 | 比对
  3. 几个SQL命令的使用
  4. cpp 怎么连接mysql_C++连接mysql数据库的两种方法
  5. 在linux系统上运行新加的内核模块(驱动模块) 需要安装的东西
  6. 图像处理:Hough变换原理分析
  7. mnesia数据库学习笔记四
  8. Oracle入门(十四.18)之使用动态SQL
  9. 最新版的SSM框架spring5.0搭建教程(附源码)
  10. cocos2d-x多分辨率自适配及因此导致的CCListView的bug修复
  11. DFS(深度优先遍历)走迷宫算法
  12. Android内核开发:理解和掌握repo工具
  13. Java IO 系统(一)
  14. 算法:(七)模拟算法
  15. ThinkPad P53,T490,T590 Win7显卡驱动
  16. switch更新主机服务器维护,switch更新链接不到服务器
  17. Java并发指南12:深度解读 java 线程池设计思想及源码实现
  18. java 实现图片的裁剪
  19. netlink使用方法
  20. 自述从被坑70000到开工作室月入100000+:我做自动项目这一年辛酸史!

热门文章

  1. android开发期间使用真机调试但系统无法识别出真机
  2. 饲料企业精细化生产管理方案
  3. 最好的船_“船”说中的美丽陶瓷
  4. C语言训练题-铺草坪简易版
  5. 每列大于0的个数_题目1342——把一个数字减少到0的步骤数
  6. linux 同步 多终端,Linux系统如何实现不同终端间的同步
  7. springboot 拦截器_Spring Boot入门系列(十)如何使用拦截器,一学就会!
  8. Java黑皮书课后题第4章:*4.8(给出ASCII码对应的字符)编写程序,得到一个ASCII码的输入(0~27之间的一个整数),然后显示该字符
  9. php5.4与php5.2,升级php 5.2.14 到5.4.11版本报错问题
  10. java利用求余水仙花数_java求水仙花数