linux sparse
转自:sparse 介绍,linux 内核代码必要的基础知识_浮躁之人的博客-CSDN博客
sparse介绍
Sparse 诞生于 2004 年, 是由linux之父开发的, 目的就是提供一个静态检查代码的工具, 从而减少linux内核的隐患.
其实在Sparse之前, 已经有了一个不错的代码静态检查工具("SWAT"), 只不过这个工具不是免费软件, 使用上有一些限制.
所以 linus 还是自己开发了一个静态检查工具.
具体可以参考这篇文章(2004年的文章了): Finding kernel problems automatically
Sparse相关的资料非常少, 关于它的使用方法我也是网上查找+自己实验得出来的.
内核代码中还有一个简略的关于 Sparse的说明文件: Documentation/sparse.txt
Sparse通过 gcc 的扩展属性 __attribute__ 以及自己定义的 __context__ 来对代码进行静态检查.
这些属性如下(尽量整理的,可能还有些不全的地方):
#define __bitwise __attribute__((bitwise))
确保变量是相同的位方式(比如 bit-endian, little-endiandeng)
#define __user __attribute__((noderef, address_space(1)))
指针地址必须在用户地址空间
#define __kernel __attribute__((noderef, address_space(0)))
指针地址必须在内核地址空间
#define __iomem __attribute__((noderef, address_space(2)))
指针地址必须在设备地址空间
#define __safe __attribute__((safe))
变量可以为空
#define __force __attribute__((force))
变量可以进行强制转换
#define __nocast __attribute__((nocast))
参数类型与实际参数类型必须一致
#define __acquires(x) __attribute__((context(x, 0, 1)))
参数x 在执行前引用计数必须是0,执行后,引用计数必须为1
#define __releases(x) __attribute__((context(x, 1, 0)))
与 __acquires(x) 相反
#define __acquire(x) __context__(x, 1)
参数x 的引用计数 + 1
#define __release(x) __context__(x, -1)
与 __acquire(x) 相反
#define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
参数c 不为0时,引用计数 + 1, 并返回1
其中 __acquires(x) 和 __releases(x), __acquire(x) 和 __release(x) 必须配对使用, 否则 Sparse 会给出警告
注: 在Fedora系统中通过 rpm 安装的 sparse 存在一个小bug.
即使用时会报出 error: unable to open ’stddef.h’ 的错误, 最好从自己源码编译安装 sparse.
参考: http://wangcong.org/blog/archives/504
Sparse 使用方法
__bitwise 的使用
主要作用就是确保内核使用的整数是在同样的位方式下.
在内核代码根目录下 grep -r '__bitwise', 会发现内核代码中很多地方都使用了这个宏.
对于使用了这个宏的变量, Sparse 会检查这个变量是否一直在同一种位方式(big-endian, little-endian或其他)下被使用,
如果此变量在多个位方式下被使用了, Sparse 会给出警告.
内核代码中的例子:
/*
内核版本:v2.6.32.61 file:include/sound/core.h 51行
*/
typedef int __bitwise snd_device_type_t;
__user 的使用
如果使用了 __user 宏的指针不在用户地址空间初始化, 或者指向内核地址空间, 设备地址空间等等, Sparse会给出警告.
内核代码中的例子:
/*
内核版本:v2.6.32.61 file:arch/score/kernel/signal.c 45行
*/
static
int setup_sigcontext(structpt_regs *regs, struct sigcontext __user *sc)
__kernel 的使用
如果使用了 __kernel 宏的指针不在内核地址空间初始化, 或者指向用户地址空间, 设备地址空间等等, Sparse会给出警告.
内核代码中的例子:
/* 内核版本:v2.6.32.61 file:arch/s390/lib/uaccess_pt.c 180行
*/ memcpy(to, ( void __kernel __force *) from , n);
__iomem 的使用
如果使用了 __iomem 宏的指针不在设备地址空间初始化, 或者指向用户地址空间, 内核地址空间等等, Sparse会给出警告.
内核代码中的例子:
*/
/* 内核版本:v2.6.32.61 file:arch/microblaze/include/asm/io.h 22行 */
static inline unsigned char __raw_readb(const volatile void __iomem *addr)
__safe 的使用
使用了 __safe修饰的变量在使用前没有判断它是否为空(null), Sparse会给出警告.
我参考的内核版本(v2.6.32.61) 中的所有内核代码都没有使用 __safe, 估计可能是由于随着gcc版本的更新,
gcc已经会对这种情况给出警告, 所以没有必要用Sparse去检查了.
__force 的使用
使用了__force修饰的变量可以进行强制类型转换, 没有使用 __force修饰的变量进行强制类型转换时, Sparse会给出警告.
内核代码中的例子:
/* 内核版本:v2.6.32.61 file:arch/s390/lib/uaccess_pt.c 180行 */
memcpy(to, (void __kernel __force *) from, n);
__nocast 的使用
使用了__nocast修饰的参数的类型必须和实际传入的参数类型一致才行,否则Sparse会给出警告.
内核代码中的例子:
/* 内核版本:v2.6.32.61 file:fs/xfs/support/ktrace.c 55行 */
ktrace_alloc(int nentries, unsigned int __nocast sleep)
__acquires __releases __acquire __release的使用
这4个宏都是和锁有关的, __acquires 和 __releases 必须成对使用, __acquire 和 __release 必须成对使用, 否则Sparse会给出警告.
__cond_lock 的使用
这个宏有点特别, 因为没有 __cond_unlock 之类的宏和它对应.
之所以有这个宏的原因可以参见: http://yarchive.net/comp/linux/sparse.html 最后一段.
这个宏的来源清楚了, 但是为什么这个宏里面还要调用一次 __acquire(x)? 我也不是很清楚, 在网上找了好久也没找到, 谁能指教的话非常感谢!!!
Sparse 在编译内核中的使用
用 Sparse 对内核进行静态分析非常简单.
# 检查所有内核代码
make C=1 检查所有重新编译的代码
make C=2 检查所有代码, 不管是不是被重新编译
补充
Sparse除了能够用在内核代码的静态分析上, 其实也可以用在一般的C语言程序中.
比如下面的小例子:
/******************************************************************************
* @file : sparse_test.c
* @author : wangyubin
* @date : Fri Feb 28 16:33:34 2014
*
* @brief : 测试 sparse 的各个检查点
* history : init
******************************************************************************/
#include <stdio.h>
#define __acquire(x) __context__(x,1)
#define __release(x) __context__(x,-1)
int main(int argc, char *argv[])
{
int lock = 1;
__acquire(lock);
/* TODO something */
__release(lock); /* 注释掉这一句 sparse 就会报错 */
return 0;
}
linux sparse相关推荐
- linux sparse 内核代码静态检查
Sparse简介 Sparse诞生于2004年,是由Linux之父开发的,目的就是提供一个静态检查代码的工具,从而减少Linux内核的隐患.起始,在Sparse之前已经有了一个不错的代码静态检查工具( ...
- 内核工具 – Sparse 简介
Sparse是内核代码静态分析工具, 能够帮助我们找出代码中的隐患. 主要内容: Sparse 介绍 Sparse 使用方法 Sparse 在编译内核中的使用 补充 1. Sparse 介绍 Spar ...
- Kubernetes云原生开源分布式存储介绍
Kubernetes存储介绍 为何引入PV.PVC以及StorageClass? 熟悉Kubernetes的都对PV.PVC以及StorageClass不陌生,我们经常用到,因此这里不再详细介绍PV. ...
- linux python2.7 scipy_scipy.sparse.linalg.sp为Linux系统上的大型稀疏矩阵解决了令人惊讶的行为...
我正在计算一个线性系统Ax = b的解决方案,其中A具有一个大的(通常200,000行和相关的密集矩阵的列)稀疏矩阵和ba稀疏矩阵,大约100列. 当我在Windows系统上运行代码(Python2. ...
- linux内核那些事之Sparse vmemmap
<inux内核那些事之物理内存模型之SPARCE(3)>中指出在传统的sparse 内存模型中,每个mem_section都有一个属于自己的section_mem_map,如下图所示: 而 ...
- linux内核那些事之物理内存模型之SPARSE(3)
在内核FLAT和DISCONTIGMEM管理模型中,其实一直都存在两个问题 管理物理内存的数据结构本身占用内存较多,不使用于较大内存情况 无法解决空洞问题,不管是FLAT还是SPARCE模型都无法解决 ...
- Linux 静态代码检查工具:sparse 的安装和使用
sparse 是用于 C 语言的语法分析器,用以对 C 代码进行静态检查,它不但可以检查 ANSI C 而且还能检查具有 gcc 扩展的 C .在 Linux 中,不但可以检查用户端代码,还可以检查内 ...
- linux内核那些事之Sparse内存模型初始化
由于现在运行的设备中大都采用sparse内存模型,而<understanding the linux virtual memory manager>书中主要以2.4和2.6内核源码基础上进 ...
- 【开发工具】【sparse】Linux下代码检测工具(sparse)的使用
获取更多相关的嵌入式开发工具,可收藏系列博文,持续更新中: [开发工具]嵌入式常用开发工具汇总帖 Linux内核源码里其实包含了相应的代码检测工具[sparse],位置在: Documentation ...
最新文章
- HashMap 为什么会导致 CPU 100%?文章看不懂?
- PAT甲级1129 Recommendation System:[C++题解]统计前k个商品
- Tableau实战系列浏览 Tableau 环境(七) -重组工作区
- Android中设置RecyclerView的每一个item的单项点击事件
- BDOC generated after customer product id is changed in CRM - CUST_MAT_INF
- COSCon’20开源教育论坛介绍
- 我一定要找到它FreeEIM
- python ctypes 详解_python与C语言调用模块 ctypes的详解
- VB获取系统目录的简单方法
- 【OCP|052】OCP题库更新,052最新考题及答案整理-第10题
- linux lsof命令语法
- android fragment 底部菜单栏,安卓开发-底部导航栏切换Fragment进行显示
- 【植被指数学习笔记】
- 大揭秘(1):网店背后的隐秘产业链【连载】
- 我的世界服务器无限血,我的世界生物血量无限指令 | 手游网游页游攻略大全
- 大学数学建模大赛是用计算机,全国大学生数学建模大赛
- Android 2.3 Gingerbreader 正式发布,向游戏开发者献媚
- java 日期计算星座_Java日期时间API系列25-----Jdk8中java.time包中的新的日期时间API类,使用MonthDay计算十二星座。...
- rsync 的 “file has vanished” 问题
- VOLTE网络架构、接口与功能实体