一、kmalloc()、kzalloc()和vmalloc()

这三个函数都可以分配连续的虚拟内存

除此之外,这三个函数的区别有:

1. kmalloc()和kzalloc()函数分配的物理内存也是连续的,而vmalloc()分配的物理内存不一定连续

2. kmalloc()和kzalloc()函数分配的大小需要小于128K,而vmalloc()分配的大小没有限制

3. kmalloc()和kzalloc()分配内存的过程可以是原子操作(使用GFP_ATOMIC),而vmalloc()分配内存时则可能产生阻塞。因此vmalloc()不能从中断上下文调用

4. 在分配DMA内存时(使用GFP_DMA)需要保证物理内存连续,需要使用kmalloc()和kzalloc()

5. kmalloc()和kzalloc()分配内存开销小,因此比vmalloc()要快。内核较多使用的也是kmalloc()和kzalloc()

6. kmalloc()和kzalloc()的差别类似于malloc()和calloc(),kmalloc()只分配,不清0;kzalloc()会进行清0

7. kmalloc()和kzalloc()使用kfree()释放,vmalloc()使用vfree()释放

二、device_create()的调用和设备节点的创建过程

device_create()
-> device_create_vargs
-> kzalloc struct device
-> device_register()
-> device_initialize()
-> device_add()
-> kobject_uevent(&dev->kobj, KOBJ_ADD);

device的注册过程,最终只是调用kobject_uevent来发送一个action,对于uevent分析,读者可以参考:二十三、uevnet机制和U盘自动挂载

那么是谁创建/dev下的设备节点呢?

通常是使用应用程序udev来创建,在嵌入式系统中我们使用busybox的mdev

我们可以在命令行中输入mdev命令查看它的描述信息

我们在制作文件系统过程中(TINY4412移植第五节)使用到了mdev -s。它的作用是在引导期间运行扫描/sys下设备的并根据扫描到的设备信息在/dev创建设备节点

三、container_of()解读

在Linux内核编程中,会经常见到一个宏函数container_of(ptr,type,member),函数原型如下:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

...

#define container_of(ptr, type, member) ({            \
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })

其实原理很简单,它的作用就是:已知结构体type的成员member的地址ptr,求解结构体type的起始地址

如上图,type的起始地址 = ptr - size(这里需要都转换为char *,因为它为单位字节)

而图中的size就是由((size_t) &((TYPE *)0)->MEMBER)求出来的

四、readb()和writeb()系列函数

 #define readb_relaxed(c) ({ u8  __r = __raw_readb(c); __r; })
#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
__raw_readw(c)); __r; })
#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
__raw_readl(c)); __r; }) #define writeb_relaxed(v,c) __raw_writeb(v,c)
#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) #define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); })
#define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); })
#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })

此系列函数用于从内存映射的I/O空间读写数据

readb()和readb_relaxed()从I/O空间读取8位数据(1字节)

readw()和readb_relaxew()从I/O空间读取16位数据(2字节)

readl()和readb_relaxel()从I/O空间读取32位数据(4字节)

writeb()和writeb_relaxed()从I/O空间写入8位数据(1字节)

writew()和writew_relaxed()从I/O空间写入16位数据(2字节)

writel()和writel_relaxed()从I/O空间写入32位数据(4字节)

其中没有relaxed()的系列函数都调用了__iowmb()和__iormb()函数,这两个函数是内存屏障指令,防止编译器优化执行过程。

五、ioctl()的幻数

ioctl()函数的幻数定义如下:

#define GLOBAL_MAGIC    'g'
#define CMD_RESET _IO(GLOBAL_MAGIC, 1)

如果正常定义CMD_RESET 0x1可能会导致不同的设备驱动拥有相同的命令号。如果设备1、设备2都支持0x1命令,就会造成命令码的污染。因此,Linux内核推荐采用幻数来生成命令

Linux驱动函数解读的更多相关文章

  1. linux驱动的入口函数module_init的加载和释放【转】

    本文转载自:http://blog.csdn.net/zhandoushi1982/article/details/4927579 就像你写C程序需要包含C库的头文件那样,Linux内核编程也需要包含 ...

  2. module_init宏解析 linux驱动的入口函数module_init的加载和释放

    linux驱动的入口函数module_init的加载和释放 http://blog.csdn.net/zhandoushi1982/article/details/4927579 void free_ ...

  3. 基于Linux 3.0.8 Samsung FIMC(S5PV210) 的摄像头驱动框架解读(一)

    作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 FIMC这个名字应该是从S5PC1x0開始出现的.在s5pv210里面的定义是摄像头接口.可是它相 ...

  4. Linux驱动实践:中断处理函数如何【发送信号】给应用层?

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  5. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...

  6. Linux代码的重用与强行卸载Linux驱动

    (一)Linux代码的重用 重用=静态重用(将要重用的代码放到其他的文件的头文件中声明)+动态重用(使用另外一个Linux驱动中的资源,例如函数.变量.宏等) 1.编译是由多个文件组成的Linux驱动 ...

  7. Linux 驱动学习笔记05--字符驱动实例,实现一个共享内存设备的驱动

    断断续续学驱动,好不容易有空,做了段字符驱动的例子.主要还是跟书上学习在此记录下来,以后说不定能回过头来温故知新. 首先上驱动源码 gmem.c: /************************* ...

  8. Linux驱动学习之常用的模块操作命令

    1.常用的模块操作命令 (1)lsmod(list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 (2)insmod(install module,安装模块),功能是向当前 ...

  9. Linux驱动学习之什么是驱动?

    一.什么是驱动? 1: 驱动一词的字面意思 2: 物理上的驱动 3: 硬件中的驱动 4: linux内核驱动.软件层面上的驱动广义上是指:这一段代码操作了硬件去动,所以这一段代码就叫硬件的驱动程序. ...

随机推荐

  1. CSS Pixel 和 Device pixels

    Web developers need CSS pixels, that is, the pixels that are used in CSS declarations such as " ...

  2. Hibernate 关系配置

    表之间关系 1. 一对多 一个部门有多个员工,一个员工只能属于某一个部门 一个班级有多个学生,一个学生只能属于一个班级 2. 多对多 一个老师教多个学生,一个学生可以被多个老师教 一个学生可以先择多门 ...

  3. HTTP的POST提交的四种常见消息主体格式

    HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据,本文 ...

  4. 配置 Ubuntu 服务器

    Python: apt install python3-pip sudo add-apt-repository ppa:fkrull/deadsnakes sudo apt-get update ap ...

  5. 等待 Redis 应答

    https://zhuanlan.zhihu.com/p/58608323 mq消息合并:由于mq请求发出到响应的时间,即往返时间, RTT(Round Time Trip),每次提交都要消耗RTT, ...

  6. 寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现。本文记录HAProxy服务热加载后某微服务50%概率失效的问题。设计3组对比实验,验证了陈旧配置的HAProxy在Reload时没有退出进而导致微服务丢失,并给出了解决方案. Keywords:HAProxy热加

    寻找丢失的微服务-HAProxy热加载问题的发现与分析 原创: 单既喜 一点大数据技术团队 4月8日 在一点资讯的容器计算平台中,我们通过HAProxy进行Marathon服务发现.本文记录HAPro ...

  7. iOS12 中的后台下载与上传

    严格意义上来说,iOS并不能像Android一样,真的在后台开启一个下载Service,一直下载.但是它可以进行在系统允许范围内的后台上传和下载. 当使用 NSURLSessionConfigurat ...

  8. zblog模板怎么安装?zblog主题安装教程

    有很多初次使用zblog的新手还会问我“zblog模板怎么安装?”,那么本文就专门给大家介绍下zblog主题安装教程. zblog现在分为zblogasp和zblogphp两个版本,两个版本的模板主题 ...

  9. 阶段5 3.微服务项目【学成在线】_day18 用户授权_19-微服务之间认证-Feign 拦截器

    4.2 Feign 拦截器 4.2.1 定义Feign拦截器 微服务之间使用feign进行远程调用,采用feign拦截器实现远程调用携带JWT. 在common工程添加依赖: <dependen ...

  10. Ubuntu 14.04 apache安装配置

    http://jingyan.baidu.com/article/6d704a130c8a0d28da51ca5f.html Ubuntu 14.04 apache安装配置 1.安装 ~# apt-g ...