IS_ERR宏定义在include/linux/err.h,如下所示:

#define MAX_ERRNO 4095

//判断x是不是在(0xfffff000,0xffffffff)之间,注意这里用unlikely()的用意

#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)

//由错误码求指针,-1 -> 0xFFFFFFFF

static inline void *ERR_PTR(long error)  

{  

return (void *) error;  

}  

//由指针求错误码,0xFFFFFFFF -> -1 ,依次类推

static inline long PTR_ERR(const void *ptr)  

{  

return (long) ptr;  

}  

//判断x是不是在(0xfffff000,0xffffffff)之间,x是不是一个有效的指针

static inline long IS_ERR(const void *ptr) 
{  

return IS_ERR_VALUE((unsigned long)ptr);  

}

首先要理解内核空间,所有的驱动程序都运行在内核空间,在这有限的空间中,其最后一个 page是专门为错误码保留的,即内核用最后一页捕捉错误。在写设备驱动程序的过程中,涉及到的指针,必然有以下三种情况:

  • 有效指针;
  • NULL,即空指针;
  • 错误指针,或者说无效指针。

而所谓的错误指针就是指其已经到达了最后一个page。对于32位的系统,内核空间最高地址为0xffffffff,那么最后一个page就是0xfffff000到 0xffffffff(假设4k一个page),这段地址是被保留的。

IS_ERR()就是用来判断指针是否有错,如果指针并不是指向最后一个page,那么没有问题;如果指针指向了最后一个page,那么说明实际上这不是一个有效的指针,这个指针里保存的实际上是一种错误代码。

通常很常用的方法就是先用IS_ERR()来判断是否是错误,然后如果是,那么就调用 PTR_ERR()来返回这个错误代码,返回错误码的时候一般加个负号,如-ENOSYS。

错误码的值在内存中的定义(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 */

linux内核中的IS_ERR()、PTR_ERR()、ERR_PTR()的更多相关文章

  1. Linux内核中的IS_ERR()实现

    1.前言 对于任何一个指针来说,必然有三种情况:一种是有效指针,一种是NULL,也就是空指针,一种是错误指针,也就是无效指针,在Linux内核中,所谓的错误指针就是指其已经到达了内核空间的最后一个pa ...

  2. Linux内核中流量控制

    linux内核中提供了流量控制的相关处理功能,相关代码在net/sched目录下:而应用层上的控制是通过iproute2软件包中的tc来实现, tc和sched的关系就好象iptables和netfi ...

  3. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  4. Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】

    转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...

  5. 【转】 Linux内核中读写文件数据的方法--不错

    原文网址:http://blog.csdn.net/tommy_wxie/article/details/8193954 Linux内核中读写文件数据的方法  有时候需要在Linuxkernel--大 ...

  6. 【转】在linux内核中读写文件 -- 不错

    原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成 ...

  7. Linux 内核中的 Device Mapper 机制

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

  8. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

  9. Linux内核中双向链表的经典实现

    概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...

随机推荐

  1. AJAX原生JavaScript写法

    GET方式 //创建XMLHttpRequest对象,为考虑兼容性问题,老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象 var ajax = windo ...

  2. Windows 编译 MQTT C++ Client

    MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可 ...

  3. Centos如何通过yum安装php7

      执行如下命令安装epel yum -y install epel-release   更换rpm源,请根据自己的centos版本选择相应的rpm源进行安装 Centos 5.X: rpm -Uvh ...

  4. DBMS_SQLTUNE使用方法

    SQL调优工具包DBMS_SQLTUNE的使用方法 oracle 提供了优化建议功能包DBMS_SQLTUNE,该包可以帮助我们分析SQL,并提供优化建议. 原有执行计划alter session s ...

  5. 我的第一个Python随笔

    自学Python也很长时间了,注册博客园写了第一篇随笔.之前想过很多次,但是始终不知道该怎么开始,内容如何,现在想想,随笔嘛,是自己的想法,也自己的实践,又是自己的锻炼.话不多说,开始今天的正式内容. ...

  6. 深入理解PHP传参原理(PHP5.2)

    首先说下今天想到的一个问题.在编写php扩展的时候,似乎参数(即传给zend_parse_parameters的变量)是不需要free的.举例: PHP_FUNCTION(test) { char* ...

  7. 数据库JDBC的基本内容

    JDBC 基本流程 首先向项目中导入jar包 创建如下代码 Class.forName("com.mysql.jdbc.Driver"); String url = "j ...

  8. MATLAB入门学习(七)

    开始,线性代数和微积分了,不怕.不怕. 背命令就行了... 线性代数 解线性方程组: Ax=b A是系数矩阵,x未知数,b是列向量 如果有唯一解,直接x=b\A 第二 B=null(A,'r')求Ax ...

  9. Spring Framework5.0 学习(4)—— 基本概念

    1.0  控制反转(IOC)/依赖注入(DI) 通过依赖注入(DI),对象的依赖关系将由负责协调系统关系中各个对象的第三方组件在创建对象是设定.对象无需自行创建或管理它们的依赖关系——依赖关系将被自动 ...

  10. BIND简易教程(3):DNSSec配置

    目录:BIND简易教程(1):安装及基本配置BIND简易教程(2):BIND视图配置BIND简易教程(3):DNSSec配置 (本篇) DNSSec,有个半英半中的名字叫DNS安全扩展.说的好听一点, ...