最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

一、為什么需要IS_ERR?

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

二、IS_ERR的原理

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

  • 內(nèi)核將錯誤碼(如-ENOMEM)轉(zhuǎn)換為指針的形式,具體實現(xiàn)依賴于體系結(jié)構(gòu)。
  • 例如在x86-64中,錯誤碼會被轉(zhuǎn)換為(void *)(-4095UL ~ -1UL)區(qū)間的虛擬地址(即最高有效位為1的地址)。
  • 當(dāng)指針值在 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);

三、實際使用場景

示例:字符設(shè)備驅(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 限定符并進(jìn)行類型轉(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 */

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

函數(shù)/宏功能描述使用場景
PTR_ERR_OR_ZERO檢查指針是否為錯誤指針,如果是則返回錯誤碼,否則返回 0簡化錯誤處理邏輯,直接獲取錯誤碼或成功標(biāo)志。
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)試的重要基礎(chǔ)。它不僅能幫助開發(fā)者準(zhǔn)確定位資源分配錯誤,更是理解內(nèi)核錯誤處理機制的關(guān)鍵入口。

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

相關(guān)文章

  • 紅帽RHEL8和7的區(qū)別對比分享(Centos8與7參照redhat)

    紅帽RHEL8和7的區(qū)別對比分享(Centos8與7參照redhat)

    這篇文章主要介紹了紅帽RHEL8和7有什么區(qū)別(Centos8與7參照redhat),包括紅帽RHEL8和RHEL7功能區(qū)別對比和RHEL8額外新功能新特性,對紅帽RHEL8和7相關(guān)知識感興趣的朋友跟隨小編一起看看吧
    2023-01-01
  • Ubuntu20.04修改ip地址的方法示例

    Ubuntu20.04修改ip地址的方法示例

    這篇文章主要介紹了Ubuntu20.04修改ip地址的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • LINUX服務(wù)器安裝SVN服務(wù)實現(xiàn)方式

    LINUX服務(wù)器安裝SVN服務(wù)實現(xiàn)方式

    本文介紹了如何使用yum安裝Subversion,創(chuàng)建版本庫,配置SVN服務(wù),并解決常見問題,詳細(xì)步驟包括安裝Subversion,查看安裝版本和位置,創(chuàng)建存放版本庫的目錄及svn版本庫,配置權(quán)限控制,啟動svn版本庫,以及處理端口訪問權(quán)限等
    2024-09-09
  • 解決Debian系統(tǒng)自動更新軟件包的問題的方法

    解決Debian系統(tǒng)自動更新軟件包的問題的方法

    這篇文章主要介紹了解決Debian系統(tǒng)自動更新軟件包的問題的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Linux中行、列顯示與轉(zhuǎn)換實現(xiàn)方式

    Linux中行、列顯示與轉(zhuǎn)換實現(xiàn)方式

    本文介紹了在Linux中如何將多項數(shù)據(jù)或內(nèi)容打印輸出為一行,用空格或其他分隔符分開,以及如何將輸出按列顯示,同時,還介紹了如何使用xargs、sed和awk等命令將行列輸出進(jìn)行轉(zhuǎn)換
    2025-11-11
  • Linux VPS備份教程 數(shù)據(jù)庫/網(wǎng)站文件自動定時備份

    Linux VPS備份教程 數(shù)據(jù)庫/網(wǎng)站文件自動定時備份

    這篇文章老左分享目前大家比較常用的自動定時備份方案,數(shù)據(jù)庫發(fā)送到我們的郵箱、文件發(fā)送同步到我們另外空間FTP中
    2012-09-09
  • Linux 文件系統(tǒng)的操作實現(xiàn)

    Linux 文件系統(tǒng)的操作實現(xiàn)

    這篇文章主要介紹了Linux 文件系統(tǒng)的操作實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • linux安裝mysql數(shù)據(jù)庫以及配置Java項目的圖文詳解

    linux安裝mysql數(shù)據(jù)庫以及配置Java項目的圖文詳解

    在本篇文章里小編給大家整理的是關(guān)于linux安裝mysql配置Java的相關(guān)知識點內(nèi)容,有需要的朋友們可以跟著學(xué)習(xí)下。
    2019-11-11
  • Linux磁盤分區(qū)實戰(zhàn)案例(必看篇)

    Linux磁盤分區(qū)實戰(zhàn)案例(必看篇)

    下面小編就為大家?guī)硪黄狶inux磁盤分區(qū)實戰(zhàn)案例(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • Linux之nfs與autofs的使用方式

    Linux之nfs與autofs的使用方式

    這篇文章主要介紹了Linux之nfs與autofs的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-08-08

最新評論

巴南区| 通渭县| 周口市| 钦州市| 潮州市| 长海县| 汉沽区| 万宁市| 安国市| 广丰县| 马公市| 永定县| 黑水县| 修文县| 中西区| 丽水市| 伊宁市| 巴林左旗| 调兵山市| 庐江县| 密山市| 漯河市| 于都县| 黄冈市| 东宁县| 专栏| 兴文县| 来凤县| 磐安县| 乳山市| 江都市| 汉阴县| 婺源县| 武强县| 营山县| 绥中县| 荆州市| 玉龙| 彭州市| 中宁县| 芜湖市|