linux内核中的IS_ERR()、PTR_ERR()、ERR_PTR()
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()的更多相关文章
- Linux内核中的IS_ERR()实现
1.前言 对于任何一个指针来说,必然有三种情况:一种是有效指针,一种是NULL,也就是空指针,一种是错误指针,也就是无效指针,在Linux内核中,所谓的错误指针就是指其已经到达了内核空间的最后一个pa ...
- Linux内核中流量控制
linux内核中提供了流量控制的相关处理功能,相关代码在net/sched目录下:而应用层上的控制是通过iproute2软件包中的tc来实现, tc和sched的关系就好象iptables和netfi ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析
一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...
- Linux内核中的GPIO系统之(3):pin controller driver代码分析--devm_kzalloc使用【转】
转自:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html 一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道 ...
- 【转】 Linux内核中读写文件数据的方法--不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8193954 Linux内核中读写文件数据的方法 有时候需要在Linuxkernel--大 ...
- 【转】在linux内核中读写文件 -- 不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成 ...
- Linux 内核中的 Device Mapper 机制
本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
- Linux内核中双向链表的经典实现
概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...
随机推荐
- SQL Server ->>监控和管理Tempdb
Tempdb作为一个公共数据库,存储着一些临时的数据.有些是用户自己创建的,有些是SQL Server自己创建的.Tempdb空间被使用的一些常见场景有 用户自定义:临时表和表变量.游标. SQL S ...
- 爬虫入门之Scrapy框架基础框架结构及腾讯爬取(十)
Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据. 如果安装了 IPyth ...
- 关于单一网络适配器拓扑TMG
单网络适配器拓扑的功能 在单网络适配器拓扑中可以实现有限的 Forefront TMG 功能,其中包括: 针对 HTTP.HTTPS 和 CERN 代理 FTP 的正向 (CERN) 代理(仅限下载) ...
- markdown中设置、调整图片尺寸
使用百分比描述尺寸 <img src="https://img2018.cnblogs.com/blog/1122471/201902/1122471-2019022218575673 ...
- FireFox浏览器Flash&视频下载工具推荐
介绍 两款扩展组件:Flash and Video Download & Flash Video Downloader 一起使用,各有优缺点. Flash and Video Download ...
- MySQL闪回-binlog2sql
功能 提取SQL 生成回滚SQL 限制: mysql server必须开启,离线模式下不能解析binlog. binlog格式必须是row模式. flashback模式只支持DML,DDL将不 ...
- 记录两篇关于linux设置ssh登录 和NAT网络模式下访问
https://blog.csdn.net/java_dotar_01/article/details/76942563 https://blog.csdn.net/jiuduan2009/artic ...
- TCP建立连接和释放连接过程
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议.TCP建立连接需要三次握手,释放连接需要四次握手. 1.TCP整 ...
- php-------面向对象详解
php面向对象详解 面向对象 对象概念是面向对象技术的核心.在显示世界里我们所面对的事情都是对象,如计算机.电视机.自行车等.在面向对象的程序设计中,对象是一个由信息及对信息进行处理的描述所组成的整体 ...
- HDU 1166 【线段树 || 树状数组,单点修改 维护区间和】
题目链接 HDU 1166 大概题意: 第一行一个整数T,表示有T组数据.每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工 ...