IS_EER分析
下面我们就来具体分析一下这段代码,看看内核中的巧妙设计思路。
要想明白IS_ERR(),首先理解要内核空间。所有的驱动程序都是运行在内核空间,内核空间虽然很大,但总是有限的,而在这有限的空间中,其最后一个page是专门保留的,也就是说一般人不可能用到内核空间最后一个page的指针。换句话说,你在写设备驱动程序的过程中,涉及到的任何一个指针,必然有三种情况:
有效指针;
NULL,空指针;
错误指针,或者说无效指针。
而所谓的错误指针就是指其已经到达了最后一个page,即内核用最后一页捕捉错误。比如对于32bit的系统来说,内核空间最高地址0xffffffff,那么最后一个page就是指的0xfffff000~0xffffffff(假设4k一个page),这段地址是被保留的。内核空间为什么留出最后一个page?我们知道一个page可能是4k,也可能是更多,比如8k,但至少它也是4k,所以留出一个page出来就可以让我们把内核空间的指针来记录错误了。内核返回的指针一般是指向页面的边界(4k边界),即ptr & 0xfff == 0。如果你发现你的一个指针指向这个范围中的某个地址,那么你的代码肯定出错了。IS_ERR()就是判断指针是否有错,如果指针并不是指向最后一个page,那么没有问题;如果指针指向了最后一个page,那么说明实际上这不是一个有效的指针,这个指针里保存的实际上是一种错误代码。而通常很常用的方法就是先用IS_ERR()来判断是否是错误,然后如果是,那么就调用PTR_ERR()来返回这个错误代码。因此,判断一个指针是不是有效的,可用如下的方式:
#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
(unsigned long)-1000L 应该为 (unsigned long)-0x1000L!(因为 -0x1000 才是 0xFFFFF000),这应该是内核的一个bug吧!在2.6.30.4的内核中是这样定义的:
#define MAX_ERRNO 4095
#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
即判断是不是在(0xfffff000,0xffffffff)之间,因此,可以用IS_ERR()来判断内核函数的返回值是不是一个有效的指针。注意这里用unlikely()的用意!
至于PTR_ERR(), ERR_PTR(),只是强制转换以下而已。现在应该知道为什么我们写返回错误码的时候也加个负号如 -ENOSYS这样子了。而PTR_ERR()只是返回错误代码,也就是提供一个信息给调用者,如果你只需要知道是否出错,而不在乎因为什么而出错,那你当然不用调用PTR_ERR()了。
而我们的错误码的值在内存中定义都是这样的(asm-generic/errno-base.h):
......
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
........
如果指针指向了最后一个page,那么说明实际上这不是一个有效的指针。这个指针里保存的实际上是一种错误代码。而通常很常用的方法就是先用IS_ERR()来判断是否是错误,然后如果是,那么就调用PTR_ERR()来返回这个错误代码。
IS_EER分析的更多相关文章
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 火焰图分析openresty性能瓶颈
注:本文操作基于CentOS 系统 准备工作 用wget从https://sourceware.org/systemtap/ftp/releases/下载最新版的systemtap.tar.gz压缩包 ...
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- 应用工具 .NET Portability Analyzer 分析迁移dotnet core
大多数开发人员更喜欢一次性编写好业务逻辑代码,以后再重用这些代码.与构建不同的应用以面向多个平台相比,这种方法更加容易.如果您创建与 .NET Core 兼容的.NET 标准库,那么现在比以往任何时候 ...
- UWP中新加的数据绑定方式x:Bind分析总结
UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...
- 查看w3wp进程占用的内存及.NET内存泄露,死锁分析
一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...
- ZIP压缩算法详细分析及解压实例解释
最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
随机推荐
- ssh无密码登陆(转)
[0]写在前面 由于ssh 实现的是免密码登陆,大致步骤是: 0.1) client通过ssh登陆到server: 0.2) server检查家目录下的.ssh文件, 并发送公钥文件 authoriz ...
- JQuery之初探
软考过后又进入了紧张的B/S学习阶段,因为自己的进度比較慢,所以更要加进学习.如今就来总结下JQuery的一些基础知识: JQuery定义 jQuery是一套跨浏览器的JavaScript库,简化HT ...
- 蜘蛛牌 (DFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1584 全部状态都判断一遍 代码: #include <stdio.h> #include ...
- HDU1253 胜利大逃亡 BFS
胜利大逃亡 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submiss ...
- DataTable转化为List
public List<T> ConvertToList<T>(DataTable dt) where T : new() { // 定义集 ...
- bigdata_hive_Issue of Vectorization on Parquet table
When Vectorization is turned on in Hive:set hive.vectorized.execution.enabled=true;If the involved t ...
- C#关于图片的相关处理
public class ImageHelper { /// <summary> /// 图片转换成字节流 /// </summary> /// <param name= ...
- Effective C++之‘宁以pass-by-reference-to-const替换pass-by-value’
Effective C++之'宁以pass-by-reference-to-const替换pass-by-value' 缺省情况下C++以by value 方式(一个继承自C的方式)传递对象至函数.除 ...
- java:高速排序算法与冒泡排序算法
Java:高速排序算法与冒泡算法 首先看下,冒泡排序算法与高速排序算法的效率: 例如以下的是main方法: /** * * @Description: * @author:cuiyaon ...
- 【转】传递给Appium服务器以开启相应安卓Automation会话的Capabilities的几点说明
原文地址:http://blog.csdn.net/zhubaitian/article/details/39431307 Desired Capabilities是由客户端发送给Appium服务器端 ...