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

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

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

一、為什么需要IS_ERR?

在Linux內(nèi)核開(kāi)發(fā)中,內(nèi)核空間的函數(shù)(如內(nèi)存分配、設(shè)備驅(qū)動(dòng)接口)無(wú)法像用戶空間那樣直接返回-ENOMEM-EINVAL等錯(cuò)誤碼,因?yàn)樗鼈兊姆祷刂殿愋屯ǔJ侵羔?。為此,?nèi)核采用了一種巧妙的方式:將錯(cuò)誤碼編碼到指針值中,而IS_ERR()正是用來(lái)檢測(cè)這種特殊指針的關(guān)鍵工具。

二、IS_ERR的原理

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

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

核心函數(shù)解析

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

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

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

三、實(shí)際使用場(chǎng)景

示例:字符設(shè)備驅(qū)動(dòng)中的內(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; // 用戶空間可以直接返回錯(cuò)誤碼
    
    // 內(nèi)核函數(shù)返回指針的錯(cuò)誤處理
    dev->regs = ioremap(DEVICE_BASE, SIZE);
    if (IS_ERR(dev->regs)) {
        int err = PTR_ERR(dev->regs);
        kfree(dev);
        return err; // 將錯(cuò)誤傳遞到用戶空間
    }
    return 0;
}

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

典型錯(cuò)誤案例

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

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

調(diào)試技巧

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

五、底層實(shí)現(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 - 顯式將帶有錯(cuò)誤值的指針轉(zhuǎn)換為另一種指針類型
 * @ptr: 需要轉(zhuǎn)換的指針。
 *
 * 以一種明確的方式,將帶有錯(cuò)誤值的指針顯式轉(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范圍時(shí),IS_ERR()返回true。

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

六、總結(jié)

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

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Linux之nfs與autofs的使用方式

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

最新評(píng)論

玉屏| 张北县| 内丘县| 英吉沙县| 朝阳区| 阿拉善左旗| 临潭县| 临江市| 大宁县| 安泽县| 山东| 桐乡市| 友谊县| 平遥县| 佛教| 宁波市| 岱山县| 叶城县| 乌兰县| 荣成市| 句容市| 柯坪县| 浮梁县| 宽城| 遂溪县| 黔江区| 松原市| 隆昌县| 兴和县| 津市市| 武安市| 宜黄县| 隆林| 高安市| 聂拉木县| 安徽省| 那坡县| 舒城县| 丹棱县| 新竹市| 神池县|