0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式Linux内核字符设备的详细资料概述

Q4MP_gh_c472c21 来源:未知 作者:易水寒 2018-07-06 09:57 次阅读

就当我还在学校的时候,我就曾在一个装机群里听一位装机圣手说,驱动程序的安装没你想的那么简单,分类型的,分为字符设备驱动和块设备驱动。我当时就纳闷了,我说我装机的时候好像没看到啊,我就把光盘放过去然后就一直点下一步,然后重启就好了啊。后面我在群里被几位高手围攻,败下阵来,时过境迁,哥现在也算是道上混的兄弟了,再也没那么容易被蒙了。就算你DIY再牛,你也不要和我说装驱动要分类。否则我就和你讲内核,讲晕你再说。看谁更能吹,哈哈。我得意的笑。我发现学内核的一个好处,就是非常好装B。你只要把内核里面的名词背熟了,拿出来去吓唬吓唬人,挺管用的,不过撞到行家的话,你就要注意了。呵呵。

好了,学内核不是为了吓唬人的,是为了掌握其原理,学习其技巧与方法,知其然而知其所以然,另外内核代码是具有一定复杂度的,看了内核代码再看看我们自已写的,和玩具没啥两样,这就是学内核的好处!

如果你已经看过驱动模型应该有这种感受:你这玩意折腾来折腾去半天的,昨不干活呢?

字符设备是传说中的东西,玩过linux的人都知道这个东西,很多同志也可以照猫画虎的写出一个字符设备。但哥不,哥是有追求的人,知其然,必需得知其所以然。我决不会不负责任的把大家领进门后就不管了。我依然会不惜笔墨的把该说的全都说清楚。

我们先不用去抠概念,不要说,什么是字符设备啊,什么是块设备啊。这些都没意义,你最需要知道的是这个叫字符设备的东西究竟都干了些啥?他到底是怎么工作的?搞清楚后,什么是字符设备你就明白了。如果再学块设备,一对比,差异在哪?你就明白了。我学习一向都不喜欢抠概念。有的同志你叫字符设备他回答你说char设备,你说块设备他说block设备,你说底半部他说下半部。你说NXP他说恩智浦,还好哥是道上混的,多少知道一点。否则就被人家给唬住了。好了,闲话不多说了,总的来说要表达的就是一种学习态度:不用抠概念。

接下来我们欣赏一下字符设备。

看过驱动模型系列的朋友现在应该有一种意识了,我们暂且把它叫做“初始化意识”。就是说你用register_chrdev()注册的时候是很爽,但是那是因为前人把路铺好了,好,我们就来看看前人都做了些啥,再提醒一次一定要有“初始化意识”。

我们在“初始化意识”的指引下找到了一个文件:char_dev.c。打开这个文件一看。有这么一个初始化函数:

void __init chrdev_init(void)

{

cdev_map = kobj_map_init(base_probe, &chrdevs_lock);

bdi_init(&directly_mappable_cdev_bdi);

}

base_probe是一个很简单的函数:

static struct kobject *base_probe(dev_t dev, int *part, void *data)

{

if (request_module("char-major-%d-%d", MAJOR(dev), MINOR(dev)) > 0)

/* Make old-style 2.4 aliases work */

request_module("char-major-%d", MAJOR(dev));

return NULL;

}

request_module这个函数先大概知道意思就行了,他的意思是请求加载一个模块。

chrdevs_lock是一把大大的锁。没别的,就这两玩意。

关键在:

struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct mutex *lock)

{

struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);

struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);

int i;

if ((p == NULL) || (base == NULL)) {

kfree(p);

kfree(base);

return NULL;

}

base->dev = 1;

base->range = ~0;

base->get = base_probe;

for (i = 0; i < 255; i++)

p->probes[i] = base;

p->lock = lock;

return p;

}

最关键的一个角色就在这种神不知鬼不觉的情况下登场了,那就是struct kobj_map。

我们可以看到首先用kmalloc分配了一块内存并赋值给struct kobj_map *p了。

struct kobj_map {

struct probe {

struct probe *next;

dev_t dev;

unsigned long range;

struct module *owner;

kobj_probe_t *get;

int (*lock)(dev_t, void *);

void *data;

} *probes[255];

struct mutex *lock;

};

里面内嵌了一个长度为255的结构体数组和一把锁。

Linux内核里面如果是直接分配比较大块的内存,基本都是有hash思想在里面的,主要是为了效率。这个结构体中的成员等会大家就知道干嘛用的了。

接下来

struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);

内核作者你就卖弄吧。写成struct probe *base = kzalloc(sizeof(struct probe), GFP_KERNEL)这样多好?不管了,随便了,反正我只取其精华。

接下来:

if ((p == NULL) || (base == NULL)) {

kfree(p);

kfree(base);

return NULL;

}

如果对这个有疑问的同志可以仔细研究一下kfree函数。这个是没有问题的。我再说一个思想,有疑问就看源码,不要去翻书,或者google百度的。Linux内核里面的函数全都是自给自足的,你所有的疑问都可以通过翻阅内核源码本身得到解决。当然啦,如果不是说不要去看书,我的意思是能不看就尽量不看。

接下来:

base->dev = 1;

base->range = ~0; //取反,比你写一堆0xff...好多了,并且可移植性更好

base->get = base_probe;//把函数指针指向传进来的那个回调函数。

接下来:

for (i = 0; i < 255; i++)

p->probes[i] = base;

用base初始化整个kobj_map.probe[255]。

p->lock = lock;

return p;

最后把锁也传过来,并返回指针。

接下来:

bdi_init(&directly_mappable_cdev_bdi);

这个玩意先不用管了,这个对我们理解字符设备目前没有任何帮助,并且只能添乱。

好了。今天就到这吧。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4975

    文章

    18235

    浏览量

    287822
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39831
  • Linux
    +关注

    关注

    87

    文章

    10974

    浏览量

    206669

原文标题:学嵌入式Linux内核还有这个好处?

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    嵌入式Linux学习步骤

    Linux内核移植Linux2.6内核到 ARM9开发板  6、 嵌入式 Linux 下串口通信
    发表于 05-04 15:01

    新手必看--嵌入式Linux学习步骤,教你怎么入门

    ,World程序 使用 make命令编译程序 编写带有一个循环的程序 调试一个有问题的程序4、嵌入式系统开发基础嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和
    发表于 06-30 11:23

    分享 嵌入式测试详细资料 嵌入式教学资料

    实时、闭环、非侵入测试的自动化测试平台,适用于嵌入式系统在设计、仿真、开发、调试、测试、集成验证和维护等各阶段配置项级别和系统级别的动态测试与验证。有嵌入式视频教学,电子版教科书,详细资料
    发表于 02-06 09:50

    嵌入式Linux学习步骤

    Linux内核移植Linux2.6内核到 ARM9开发板6、嵌入式 Linux 下串口通信串行I
    发表于 03-24 10:41

    新手必看--嵌入式Linux学习步骤

    ,World程序 使用 make命令编译程序 编写带有一个循环的程序 调试一个有问题的程序4、嵌入式系统开发基础嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和
    发表于 03-25 14:53

    嵌入式linux学习步骤

    使用 make命令编译程序 编写带有一个循环的程序调试一个有问题的程序4、嵌入式系统开发基础嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务下载Bootloader和内核
    发表于 09-12 14:23

    嵌入式linux学习步骤

    内核 嵌入式Linux应用软件开发流程熟悉嵌入式系统概念以及开发流程 建立嵌入式系统开发环境制作cross_gcc工具链 编译并下载U-b
    发表于 10-25 10:12

    嵌入式Linux学习步骤

    系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和内核 嵌入式Linux应用软件开发流程熟悉嵌入式系统概念以及
    发表于 07-03 00:56

    嵌入式 linux字符设备驱动的设计与应用,看完你就懂了

    本文通过实现对 PXA255开发板外围字符设备(电机、数码管、串口和 mini键盘)的操作和控制,详细讨论了嵌入式 linux
    发表于 04-26 06:35

    嵌入式linux学习步骤

    ,World程序 使用 make命令编译程序 编写带有一个循环的程序 调试一个有问题的程序4、嵌入式系统开发基础嵌入式系统概述 交叉编译 配置TFTP服务 配置NFS服务 下载Bootloader和
    发表于 09-08 11:51

    嵌入式Linux字符设备驱动的设计与应用

    描述了基于嵌入式Linux字符设备驱动程序的设计方法和实现过程。以电机、数码管、串口和mini键盘的驱动设计为例,详细阐述了
    发表于 02-23 15:45 24次下载

    嵌入式Linux字符设备驱动的设计与应用

    描述了基于嵌入式Linux字符设备驱动程序的设计方法和实现过程。以电机、数码管、串口和mini键盘的驱动设计为例,详细阐述了
    发表于 07-14 17:31 31次下载

    嵌入式linux开发详细资料

    本文主要介绍了嵌入式linux开发详细资料
    发表于 06-05 08:00 3次下载

    构建嵌入式开发平台简明指导编译内核镜像的详细资料概述

    本文档的主要内容详细介绍的是构建嵌入式开发平台简明指导编译内核镜像的详细资料概述
    发表于 06-19 08:00 10次下载

    如何吧SQLite移植到嵌入式Linux系统的详细资料说明

    本文档的主要内容详细介绍的是如何吧SQLite移植到嵌入式Linux系统的详细资料说明。
    发表于 01-18 08:00 8次下载
    如何吧SQLite移植到<b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>系统的<b class='flag-5'>详细资料</b>说明