欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux深入解析IS_ERR函數(shù)的使用方式

 更新時間:2025年07月11日 09:47:34   作者:小嵌同學  
文章解釋了Linux內(nèi)核中IS_ERR函數(shù)的作用及原理,說明其通過檢測特定地址范圍的指針來識別錯誤碼,用于內(nèi)存分配和資源獲取等場景,并給出調(diào)試技巧與底層宏實現(xiàn)解析

一、為什么需要IS_ERR?

在Linux內(nèi)核開發(fā)中,內(nèi)核空間的函數(shù)(如內(nèi)存分配、設備驅(qū)動接口)無法像用戶空間那樣直接返回-ENOMEM-EINVAL等錯誤碼,因為它們的返回值類型通常是指針。為此,內(nèi)核采用了一種巧妙的方式:將錯誤碼編碼到指針值中,而IS_ERR()正是用來檢測這種特殊指針的關鍵工具。

二、IS_ERR的原理

錯誤碼的編碼規(guī)則

  • 內(nèi)核將錯誤碼(如-ENOMEM)轉(zhuǎn)換為指針的形式,具體實現(xiàn)依賴于體系結(jié)構(gòu)。
  • 例如在x86-64中,錯誤碼會被轉(zhuǎn)換為(void *)(-4095UL ~ -1UL)區(qū)間的虛擬地址(即最高有效位為1的地址)。
  • 當指針值在 0xFFFFF000~0xFFFFFFFFFFFFFFFF范圍時,IS_ERR()返回true。

核心函數(shù)解析

// 判斷指針是否為錯誤碼
bool IS_ERR(const void *ptr);

// 從錯誤指針中提取原始錯誤碼
long PTR_ERR(const void *ptr);

// 將錯誤碼轉(zhuǎn)換為指針
void *ERR_PTR(long error);

三、實際使用場景

示例:字符設備驅(qū)動中的內(nèi)存分配

static int mydev_open(struct inode *inode, struct file *filp) {
    struct my_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
    
    if (!dev)
        return -ENOMEM; // 用戶空間可以直接返回錯誤碼
    
    // 內(nèi)核函數(shù)返回指針的錯誤處理
    dev->regs = ioremap(DEVICE_BASE, SIZE);
    if (IS_ERR(dev->regs)) {
        int err = PTR_ERR(dev->regs);
        kfree(dev);
        return err; // 將錯誤傳遞到用戶空間
    }
    return 0;
}

四、常見錯誤及調(diào)試技巧

典型錯誤案例

void *ptr = vmalloc(1024);
if (IS_ERR(ptr)) {  // 錯誤!vmalloc失敗時返回NULL,而非錯誤指針
    printk("Allocation failed: %ld\n", PTR_ERR(ptr));
    return;
}

? 正確做法:對可能返回錯誤指針的函數(shù)(如devm_clk_get())使用IS_ERR,對返回NULL的函數(shù)(如kmalloc())直接判空。

調(diào)試技巧

  • 打印錯誤碼:printk("Error code: %ld\n", PTR_ERR(ptr));
  • 使用dump_stack()定位調(diào)用路徑

五、底層實現(xiàn)解析( include/linux/err.h)

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_ERR_H
#define _LINUX_ERR_H

#include <linux/compiler.h>
#include <linux/types.h>

#include <asm/errno.h>

/*
 * Kernel pointers have redundant information, so we can use a
 * scheme where we can return either an error code or a normal
 * pointer with the same return value.
 *
 * This should be a per-architecture thing, to allow different
 * error and pointer decisions.
 */
#define MAX_ERRNO	4095

#ifndef __ASSEMBLY__

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

static inline void * __must_check ERR_PTR(long error)
{
	return (void *) error;
}

static inline long __must_check PTR_ERR(__force const void *ptr)
{
	return (long) ptr;
}

static inline bool __must_check IS_ERR(__force const void *ptr)
{
	return IS_ERR_VALUE((unsigned long)ptr);
}

static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr)
{
	return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr);
}

/**
 * ERR_CAST - 顯式將帶有錯誤值的指針轉(zhuǎn)換為另一種指針類型
 * @ptr: 需要轉(zhuǎn)換的指針。
 *
 * 以一種明確的方式,將帶有錯誤值的指針顯式轉(zhuǎn)換為另一種指針類型。
 */
static inline void * __must_check ERR_CAST(__force const void *ptr)
{
	// 去除 const 限定符并進行類型轉(zhuǎn)換
	return (void *) ptr;
}

static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
{
	if (IS_ERR(ptr))
		return PTR_ERR(ptr);
	else
		return 0;
}

#endif

#endif /* _LINUX_ERR_H */

當指針值在0xFFFFF000~0xFFFFFFFFFFFFFFFF范圍時,IS_ERR()返回true。

函數(shù)/宏功能描述使用場景
PTR_ERR_OR_ZERO檢查指針是否為錯誤指針,如果是則返回錯誤碼,否則返回 0簡化錯誤處理邏輯,直接獲取錯誤碼或成功標志。
ERR_CAST將帶限定符的指針轉(zhuǎn)換為普通指針,保留錯誤信息需要將錯誤指針傳遞給期望不同類型的函數(shù)時使用。
IS_ERR_OR_NULL檢查指針是否為 NULL 或錯誤指針同時判斷指針是否為空或包含錯誤信息,適用于返回值可能為 NULL 或錯誤指針的情況。

六、總結(jié)

場景正確用法錯誤用法
內(nèi)存分配失敗if (!ptr)IS_ERR(ptr)
資源獲取類函數(shù)if (IS_ERR(ptr))直接判空
錯誤傳遞return PTR_ERR(ptr);返回未經(jīng)轉(zhuǎn)換的指針

掌握IS_ERR系列函數(shù)的使用,是Linux內(nèi)核調(diào)試的重要基礎。它不僅能幫助開發(fā)者準確定位資源分配錯誤,更是理解內(nèi)核錯誤處理機制的關鍵入口。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Apache配置虛擬目錄和多主機頭的方法

    Apache配置虛擬目錄和多主機頭的方法

    這篇文章主要介紹了apache中配置虛擬目錄,以及多主機頭配置,有需要的朋友,可以參考下
    2016-11-11
  • 一步步教你如何編寫Shell腳本

    一步步教你如何編寫Shell腳本

    這篇文章主要介紹了關于如何編寫Shell腳本的相關資料,文中介紹的非常詳細,對大家具有一定的參考價值,需要的朋友下面跟著小編來一起學習學習吧。
    2017-04-04
  • Ubuntu下安裝CUDA10.0以及問題

    Ubuntu下安裝CUDA10.0以及問題

    這篇文章主要介紹了Ubuntu下安裝CUDA10.0以及問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • Ubuntu常用指令及用法詳解

    Ubuntu常用指令及用法詳解

    本文重點給大家介紹Ubuntu常用指令及用法,感興趣的朋友跟隨腳本之家小編一起學習吧
    2018-06-06
  • 解決linux系統(tǒng)中運行node進程卻無法殺死進程的問題

    解決linux系統(tǒng)中運行node進程卻無法殺死進程的問題

    這篇文章主要介紹了linux系統(tǒng)中運行node進程無法殺死進程的問題,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • 詳解在LINUX上部署帶有JAR包的JAVA項目

    詳解在LINUX上部署帶有JAR包的JAVA項目

    這篇文章主要介紹了詳解在LINUX上部署帶有JAR包的JAVA項目,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • 關于Read-only file system問題的解決

    關于Read-only file system問題的解決

    這篇文章主要介紹了關于Read-only file system問題的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Apache服務的主要目錄和配置文件詳解

    Apache服務的主要目錄和配置文件詳解

    這篇文章主要介紹了Apache服務的主要目錄和配置文件詳解,需要的朋友可以參考下
    2017-05-05
  • linux操作系統(tǒng)內(nèi)核升級過程

    linux操作系統(tǒng)內(nèi)核升級過程

    這篇文章主要介紹了linux操作系統(tǒng)內(nèi)核升級過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • CentOS 7.2安裝Zabbix 3.2教程詳解

    CentOS 7.2安裝Zabbix 3.2教程詳解

    這篇文章主要介紹了CentOS 7.2安裝Zabbix 3.2教程詳解的相關資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-11-11

最新評論