zoukankan      html  css  js  c++  java
  • 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()来返回这个错误代码。

  • 相关阅读:
    图的概念、存储、遍历、最短路径问题、最小生成树、拓扑排序、关键路径
    Nginx负载均衡
    Nginx反向代理
    Nginx配置虚拟主机
    Linux下Nginx安装
    freemarker使用
    ActiveMQ与spring整合
    ActiveMQ安装
    全局异常处理
    solr整合spring
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3233745.html
Copyright © 2011-2022 走看看