module_param_named 內核啟動時模塊參數實現原理

基于上節內核啟動參數實現原理內容, 其中對early_param的實現流程做了分析, 已基本清晰. 但有不少的參數是在內核模塊中聲明的, 具體賦值流程也值得一探究竟.

nomodeset

裝過Linux系統的同學可能多少有看到過nomodeset這個參數, 解決一些顯卡點不亮Linux的問題.

那么這個nomodeset是怎么生效的呢?

在內核代碼中查找一下:

[mxd@5 linux-4.19-loongson]$ grep nomodeset -rnIw drivers/video/
drivers/video/console/vgacon.c:116:	pr_warning("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
drivers/video/console/vgacon.c:118:	pr_warning("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
drivers/video/console/vgacon.c:124:__setup("nomodeset", text_mode);
drivers/video/fbdev/aty/radeon_base.c:263:static bool nomodeset = 0;
drivers/video/fbdev/aty/radeon_base.c:1472:	if (nomodeset)
drivers/video/fbdev/aty/radeon_base.c:2624:		} else if (!strncmp(this_opt, "nomodeset", 9)) {
drivers/video/fbdev/aty/radeon_base.c:2625:			nomodeset = 1;
drivers/video/fbdev/aty/radeon_base.c:2671:module_param(nomodeset, bool, 0);
drivers/video/fbdev/aty/radeon_base.c:2672:MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode");

drivers/video/console/vgacon.c中有相關聲明:

static int __init text_mode(char *str)
{vgacon_text_mode_force = true;pr_warning("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");pr_warning("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");pr_warning("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");return 1;
}/* force text mode - used by kernel modesetting */
__setup("nomodeset", text_mode);

而關于__setup的定義, 在上節中已經看到過了:

#ifndef MODULE
#define __setup_param(str, unique_id, fn, early)            \static const char __setup_str_##unique_id[] __initconst     \__aligned(1) = str;                     \static struct obs_kernel_param __setup_##unique_id      \__used __section(.init.setup)               \__attribute__((aligned((sizeof(long)))))        \= { __setup_str_##unique_id, fn, early }
#else /* MODULE */
#define __setup_param(str, unique_id, fn)   /* nothing */
#endif#define __setup(str, fn)                        \__setup_param(str, fn, fn, 0)

上節中的early_param是只在內核中用, 這個可就不好判斷了呀.

看一下編譯內容:

[mxd@5 linux-4.19-loongson]$ grep vgacon.o -rn drivers/video/console/Makefile
9:obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
[mxd@5 linux-4.19-loongson]$ cat .config | grep CONFIG_VGA_CONSOLE
CONFIG_VGA_CONSOLE=y

所以, 這個參數還是給內核用的, 但與early_param不同, 他的并不滿足early_param的條件:

  1. 如果成員是early類型, 且成員中的變量名與傳入的參數名一致
  2. 如果參數名是console, 且成員中的變量名是earlycon時.

還記得有一個obsolete_checksetup嗎? 它是在參數未知的情況下注冊的:

static int __init unknown_bootoption(char *param, char *val,const char *unused, void *arg)
{repair_env_string(param, val, unused, NULL);/* Handle obsolete-style parameters */if (obsolete_checksetup(param))return 0;............
}asmlinkage __visible void __init start_kernel(void)
{char *command_line;char *after_dashes;............after_dashes = parse_args("Booting kernel",static_command_line, __start___param,__stop___param - __start___param,-1, -1, NULL, &unknown_bootoption);............
}static bool __init obsolete_checksetup(char *line)
{const struct obs_kernel_param *p;bool had_early_param = false;p = __setup_start;do {int n = strlen(p->str);if (parameqn(line, p->str, n)) {if (p->early) {/* Already done in parse_early_param?* (Needs exact match on param part).* Keep iterating, as we can have early* params and __setups of same names 8( */if (line[n] == '\0' || line[n] == '=')had_early_param = true;} else if (!p->setup_func) {pr_warn("Parameter %s is obsolete, ignored\n",p->str);return true;} else if (p->setup_func(line + n))return true;}p++;} while (p < __setup_end);return had_early_param;
}

所以nomodeset是在start_kernel時初始化并調用的. 仍然屬于內核參數.

radeon.modeset

nomodeset類似, radeon.modeset也是在搭配顯卡時安裝Linux黑屏的解決方案之一.

radeon的驅動中查找一下看看:

[mxd@5 linux-4.19-loongson]$ grep modeset -rnwI drivers/gpu/drm/radeon/ | grep -v include
drivers/gpu/drm/radeon/trinity_dpm.c:1983:	pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
drivers/gpu/drm/radeon/radeon_kms.c:144:		dev_err(&dev->pdev->dev, "Fatal error during modeset init\n");
drivers/gpu/drm/radeon/radeon_kms.c:150:	/* Call ACPI methods: require modeset init
drivers/gpu/drm/radeon/radeon_connectors.c:195:			/* mode_clock is clock in kHz for mode to be modeset on this connector */
drivers/gpu/drm/radeon/radeon_drv.c:204:MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
drivers/gpu/drm/radeon/radeon_drv.c:205:module_param_named(modeset, radeon_modeset, int, 0400);
drivers/gpu/drm/radeon/radeon_pm.c:281:				/* This can fail if a modeset is in progress */
drivers/gpu/drm/radeon/radeon_pm.c:1565:				 * a modeset to call this.
drivers/gpu/drm/radeon/radeon_display.c:175:	/* XXX match this to the depth of the crtc fmt block, move to modeset? */

可見在drivers/gpu/drm/radeon/radeon_drv.c中通過module_param_namedMODULE_PARM_DESC聲明和描述了這個參數.

看看代碼:

#define __MODULE_INFO(tag, name, info)                    \
static const char __UNIQUE_ID(name)[]                     \__used __attribute__((section(".modinfo"), unused, aligned(1)))     \= __stringify(tag) "=" info#define __MODULE_PARM_TYPE(name, _type)                   \__MODULE_INFO(parmtype, name##type, #name ":" _type)/* One for each parameter, describing how to use it.  Some files domultiple of these per line, so can't just use MODULE_INFO. */
#define MODULE_PARM_DESC(_parm, desc) \__MODULE_INFO(parm, _parm, #_parm ":" desc)#define module_param_cb(name, ops, arg, perm)                     \__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \/* Default value instead of permissions? */         \static const char __param_str_##name[] = prefix #name;      \static struct kernel_param __moduleparam_const __param_##name   \__used                              \__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \= { __param_str_##name, THIS_MODULE, ops,           \VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }#define module_param_named(name, value, type, perm)            \param_check_##type(name, &(value));                \module_param_cb(name, &param_ops_##type, &value, perm);        \__MODULE_PARM_TYPE(name, #type)

所以radeon.modeset的聲明實體就是:

param_check_int(modeset, &(radeon_modeset));
static const char __param_str_modeset[] = radeon.modeset;
static struct kernel_param __moduleparam_const __param_modeset__used __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) = {__param_str_modeset,radeon,&param_ops_int,VERIFY_OCTAL_PERMISSIONS(0400),-1,0,{&(radeon_modeset)}};
static const char __UNIQUE_ID(modesettype)[]__used __attribute__((section(".modinfo"), unused, aligned(1))) = "parmtype=modeset:int";

類似的, 也是將相關的參數存入指定的section中, 在加載modules時進行初始化及調用. 原理同early_param類似, 所以不再細說.

AI

學習的時候, 沒必要把代碼全都看得這么細, 除非對算法有研究. 在AI時代, 借助AI分析, 并掌握一個大項目的實現策略的優先級是更高的. 看看AI的說法:

MODULE_PARM_DESC有什么用?

MODULE_PARM_DESC 是 Linux 內核模塊編程中的一個宏,用于描述模塊參數的意義和用途。當你在內核模塊中定義了一個可以由用戶空間程序修改的參數時,使用 MODULE_PARM_DESC 宏可以幫助記錄這個參數的描述性信息。

當你在模塊中定義一個參數時,通常會使用 module_param 或 module_param_array 宏來聲明這個參數,并指定它的類型和權限。接著,你可以在同一地方使用 MODULE_PARM_DESC 宏來添加對該參數的描述。

例如:

#include <linux/module.h>
#include <linux/kernel.h>int myparam = 10;
module_param(myparam, int, 0644);
MODULE_PARM_DESC(myparam, "This is a description of the parameter myparam.");

在這個例子中,myparam 參數被聲明為整型,權限為 0644(讀寫權限對所有用戶開放),并且有一個描述,告訴用戶這個參數的含義。

當你使用 modinfo 命令查詢模塊信息時,MODULE_PARM_DESC 提供的描述會被顯示出來,幫助用戶理解參數的作用。這對于調試和配置模塊時非常有用,因為用戶可以更容易地理解每個參數的功能。

例如,如果你有一個名為 example.ko 的模塊,你可以使用以下命令來查看參數信息:

$ modinfo example.ko
filename:       /lib/modules/$(uname -r)/kernel/drivers/example.ko
license:        GPL
description:    Example kernel module
author:         Your Name
srcversion:     1234567890abcdef...
depends:
retpoline:      Y
name:           example
vermagic:       4.19.0-xyz SMP mod_unload
parm:           myparam:This is a description of the parameter myparam. (int)

在 parm: 行中,你會看到 myparam 參數的描述。這樣,當用戶使用 modprobe 加載模塊或使用 insmod 命令手動加載模塊并設置參數時,他們可以根據描述來正確地設置參數值。

module_param_named和模塊初始化代碼的調用順序是怎樣的

在Linux內核模塊中,module_param_named宏的使用和模塊初始化函數的調用順序是非常關鍵的,因為它們決定了模塊參數如何被內核識別和處理。以下是典型的調用順序和工作流程:

模塊參數聲明與注冊:
在模塊的源文件中,你需要使用module_param_named(或其他module_param_*宏)來聲明模塊參數。這些宏會在編譯時生成相應的代碼,注冊參數,并將其關聯到一個特定的回調函數,該函數用于處理模塊加載或卸載時的參數設置。
這些宏的執行是在編譯階段完成的,它們生成的代碼會被鏈接到模塊的.init.text和.data段中。
模塊初始化:
模塊初始化函數(如init_module或自定義命名的初始化函數)會在模塊加載到內核時由內核自動調用。在這之前,內核已經解析了模塊信息段(.modinfo),包括所有由module_param_*宏注冊的參數信息。
初始化函數可以訪問通過module_param_*宏注冊的所有參數。這意味著你可以在這個函數中使用這些參數來初始化模塊的狀態或者配置模塊的行為。
參數解析與應用:
當模塊加載時,內核會讀取傳遞給模塊的命令行參數,并嘗試匹配這些參數與模塊參數。如果找到了匹配,內核會調用相應的回調函數來設置參數值。
這一過程發生在模塊初始化函數被調用之前。因此,當你的模塊初始化代碼執行時,所有通過命令行傳遞的參數值已經被設置好了。
模塊清理:
類似地,當模塊被卸載時,模塊的清理函數(如cleanup_module)會被調用。此時,module_param_*宏所注冊的參數仍然可用,直到模塊完全從內核中移除。
總結來說,module_param_named宏的調用應該在模塊初始化函數的定義之前,這樣在模塊加載時,內核就能正確地解析和設置參數。而模塊初始化函數則會在參數設置完成后被調用,此時就可以使用這些參數來配置模塊了。

使用

借助modinfo命令:

[root@mxd ~]# modinfo /lib/modules/6.8.6-2/kernel/drivers/gpu/drm/radeon/radeon.ko.zst
......
name:           radeon
vermagic:       6.8.6-2 SMP preempt mod_unload modversions LOONGARCH 64BIT
parm:           no_wb:Disable AGP writeback for scratch registers (int)
parm:           modeset:Disable/Enable modesetting (int)
parm:           dynclks:Disable/Enable dynamic clocks (int)
parm:           r4xx_atom:Enable ATOMBIOS modesetting for R4xx (int)
parm:           vramlimit:Restrict VRAM for testing, in megabytes (int)
......

所以在內核啟動時, 可以通過radeon.modeset=0的方式禁用radeon驅動的modesetting.

龍芯的GPU也有相似的功能:

root@loongson-pc:/home/loongson# modinfo /lib/modules/4.19.0-19-loongson-3/kernel/drivers/gpu/drm/gsgpu/gpu/gsgpu.ko
filename:       /lib/modules/4.19.0-19-loongson-3/kernel/drivers/gpu/drm/gsgpu/gpu/gsgpu.ko
license:        GPL and additional rights
description:    GS GPU Driver
author:         Loongson graphics driver team
firmware:       loongson/lg100_cp.bin
alias:          pci:v00000014d00007A25sv*sd*bc*sc*i*
depends:        gpu-sched
intree:         Y
name:           gsgpu
vermagic:       4.19.0-19-loongson-3 SMP mod_unload modversions LOONGARCH 64BIT
parm:           LG100_support:LG100 support (1 = enabled (default), 0 = disabled (int)
parm:           vramlimit:Restrict VRAM for testing, in megabytes (int)
parm:           vis_vramlimit:Restrict visible VRAM for testing, in megabytes (int)
parm:           gartsize:Size of GART to setup in megabytes (32, 64, etc., -1=auto) (uint)
parm:           gttsize:Size of the GTT domain in megabytes (-1 = auto) (int)
parm:           moverate:Maximum buffer migration rate in MB/s. (32, 64, etc., -1=auto, 0=1=disabled) (int)
parm:           benchmark:Run benchmark (int)

所以當龍芯的板卡出問題時, 可以通過gsgpu.LG100_support=0來禁用gsgpu功能.

參考文獻

  1. 內核源碼
  2. 通義千問

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41541.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41541.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41541.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI繪畫Stable Diffusion 新手入門教程:萬字長文解析Lora模型的使用,快速上手Lora模型!

大家好&#xff0c;我是設計師阿威 今天給大家講解一下AI繪畫Stable Diffusion 中的一個重要模型—Lora模型&#xff0c;如果還有小伙伴沒有SD安裝包的&#xff0c;可以看我往期入門教程2024最新超強AI繪畫Stable Diffusion整合包安裝教程&#xff0c;零基礎入門必備&#xff…

React Hooks --- 分享自己開發中常用的自定義的Hooks (1)

為什么要使用自定義 Hooks 自定義 Hooks 是 React 中一種復用邏輯的機制&#xff0c;通過它們可以抽離組件中的邏輯&#xff0c;使代碼更加簡潔、易讀、易維護。它們可以在多個組件中復用相同的邏輯&#xff0c;減少重復代碼。 1、useThrottle 代碼 import React,{ useRef,…

三葉青圖像識別研究簡概

三葉青圖像識別研究總概 文章目錄 前言一、整體目錄介紹二、前期安排三、構建圖像分類數據集四、模型訓練準備五、遷移學習模型六、在測試集上評估模型精度七、可解釋性分析、顯著性分析八、圖像分類部署九、樹莓派部署十、相關補充總結 前言 本系列文章為近期所做項目研究而作…

工作助手VB開發筆記(2)

今天繼續講功能 2.功能 2.9開機自啟 設置程序隨windows系統啟動&#xff0c;其實就是就是將程序加載到注冊表 Public Sub StartRunRegHKLM()REM HKEY_LOCAL_MACHINE \ SOFTWARE \ WOW6432Node \ Microsoft \ Windows \ CurrentVersion \ RunDim strName As String Applicat…

教師商調函流程詳解

作為一名教師&#xff0c;您是否曾面臨過工作調動的困惑&#xff1f;當您決定邁向新的教育環境&#xff0c;是否清楚整個商調函流程的每一個細節&#xff1f;今天&#xff0c;就讓我們一起來探討這一過程&#xff0c;確保您能夠順利地完成工作調動。 首先需要確定新調入的學校已…

裁員風波中的項目經理,如何自洽?

最近都在擔心企業裁員&#xff0c;那么項目經理會不會也有被優化的風險呢&#xff1f; 答案是&#xff0c;一定會&#xff01; 今天從3個方面給大家闡述一下項目經理崗位的發展現狀以及未來的趨勢 01 項目經理被優化的可能性大嗎&#xff1f; 02 哪一類項目經理會被最先裁員…

CSDN導入本地md文件圖片不能正常回顯問題

標題 搭建圖像倉庫獲取圖片URL 路徑替換 因為服務器讀取不到本地圖片&#xff0c;故不能正常回顯&#xff0c;因此想要正常回顯圖片&#xff0c;我們首先要做的就是搭建一個可以存放圖片的服務器&#xff0c;像你可以選擇購買一個云服務器、FastDFS圖片服務器、Minio多云對象存…

信息收集-arping

信息收集-arping 簡介 arping 是一個用于發送 ARP 請求和接收 ARP 回復的工具。它通常用于檢查網絡中的 IP 地址是否被使用&#xff0c;或發現網絡中的重復 IP 地址。arping 工具類似于 ping 命令&#xff0c;但它使用的是 ARP 協議而不是 ICMP 協議。在 Kali Linux 中&#…

娛樂圈驚爆已婚男星劉端端深夜幽會

【娛樂圈驚爆&#xff01;已婚男星劉端端深夜幽會&#xff0c;竟是《慶余年》二皇子“戲外風云”】在這個信息爆炸的時代&#xff0c;娛樂圈的每一次風吹草動都能瞬間點燃公眾的熱情。今日&#xff0c;知名娛樂博主劉大錘的一則預告如同投入湖中的巨石&#xff0c;激起了層層漣…

紙電混合階段,如何在線上實現紙電會檔案的協同管理?

隨著國家政策的出臺和引導&#xff0c;電子會計檔案的管理越來越規范&#xff0c;電子會計檔案建設成為打通財務數字化最后一公里的重要一環。但是&#xff0c;當前很多企業的財務管理仍處于電子檔案和紙質檔案并行的階段&#xff0c;如何能將其建立合理清晰關聯&#xff0c;統…

《數字圖像處理-OpenCV/Python》第17章:圖像的特征描述

《數字圖像處理-OpenCV/Python》第17章&#xff1a;圖像的特征描述 本書京東 優惠購書鏈接 https://item.jd.com/14098452.html 本書CSDN 獨家連載專欄 https://blog.csdn.net/youcans/category_12418787.html 第17章&#xff1a;圖像的特征描述 特征檢測與匹配是計算機視覺的…

javascript v8編譯器的使用記錄

我的機器是MacOS Mx系列。 一、v8源碼下載構建 1.1 下載并更新depot_tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git export PATH/path/to/depot_tools:$PATH 失敗的話可能是網絡問題&#xff0c;可以試一下是否能ping通&#xff0c;連…

【代碼隨想錄_Day25】452. 用最少數量的箭引爆氣球 435. 無重疊區間 763. 劃分字母區間

Day25 OK&#xff0c;今日份的打卡&#xff01;第二十五天 以下是今日份的總結用最少數量的箭引爆氣球無重疊區間劃分字母區間 以下是今日份的總結 用最少數量的箭引爆氣球無重疊區間劃分字母區間 今天的題目難度不低&#xff0c;而且非常的有意思&#xff0c;盡量還是寫一些…

imx6ull/linux應用編程學習(11)CAN應用編程基礎

關于裸機的can通信&#xff0c;會在其他文章發&#xff0c;這里主要講講linux上的can通信。 與I2C,SPI等同步通訊方式不同&#xff0c;CAN通訊是異步通訊&#xff0c;也就是沒有時鐘信號線來保持信號接收同步&#xff0c;也就是所說的半雙工&#xff0c;無法同時發送與接收&…

python項目常見使用的傳參調試方法

簡介 你是否經常遇到下載的github開源知名項目&#xff0c;不知如何調試&#xff1f;只知道按說明的命令行運行&#xff1f;遇到異常或想改造也無從下手&#xff1f;這篇文檔章將指導你如何入手調試別人的大型開源項目。 常見項目使用說明及代碼如何調試 常見情況一 使用說…

16.【C語言】初識常見關鍵字 上

1.關鍵字由C語言自帶&#xff0c;不能自創 2.關鍵字不作變量名 3.關鍵字舉例&#xff1a; auto自動&#xff1a;每個局部變量都由auto修飾&#xff0c;含義&#xff1a;自動創建&#xff0c;自動銷毀 auto int a0;等價于int a0; exturn:申明外部符號 register:寄存器關鍵字…

數據治理的制勝法寶:篩斗數據技術在現代企業管理中的應用

數據治理的制勝法寶&#xff1a;篩斗數據技術在現代企業管理中的應用 在當今這個數據驅動的時代&#xff0c;企業管理的效率和競爭力越來越依賴于對數據的精準把握和高效利用。然而&#xff0c;隨著企業規模的擴大和業務復雜度的增加&#xff0c;數據治理成為了一個亟需解決的…

EasyExcel 單元格根據圖片數量動態設置寬度

在使用 EasyExcel 導出 Excel 時&#xff0c;如果某個單元格是圖片內容&#xff0c;且存在多張圖片&#xff0c;此時就需要單元格根據圖片數量動態設置寬度。 經過自己的研究和實驗&#xff0c;導出效果如下&#xff1a; 具體代碼如下&#xff1a; EasyExcel 版本 <depen…

Haxm安裝失敗的解決辦法

確認你的處理器是否是Intel的&#xff0c;如果是AMD那就無法安裝&#xff0c;如果是Intel的&#xff0c;再確認是否支持V1T 如果處理器是Intel的且支持VT&#xff0c;在開機時進入BIOS界面&#xff0c;不同的品牌進入BIOS的方法各不相同&#xff0c;通常是F2/F12/delete些&…

Python爬蟲零基礎實戰,簡潔實用!

1.爬蟲簡介 簡單來講&#xff0c;爬蟲就是一個探測機器&#xff0c;它的基本操作就是模擬人的行為去各個網站溜達&#xff0c;點點按鈕&#xff0c;查查數據&#xff0c;或者把看到的信息背回來。就像一只蟲子在一幢樓里不知疲倦地爬來爬去。 你可以簡單地想象&#xff1a;每個…