__setup 在内核中的作用

Linux kernel 分析之四:setup辅助程序 我们发现,在起点与终点之间,还有几个中转站。最近的一站叫作MBR。BIOS,带你到MBR后,说:“对不起,只能送你到这里了。”     那其它几个中转站是什么呢?我们知道,在x86上,保护模式有两种,32位页式寻址的保护模式和32位段式寻址的保护模式。显然,32位页式寻址的保护模式要求系统中已经构造好页表。从16位实地址模式直接到32位页式寻址的保护模式是很有难度的,因为你要在16位实地址模式下 阅读详情

本文来自:

http://blog.chinaunix.net/uid-13798723-id-2871394.html


介绍的很详细,我也正好用了一次__setup(),蛮好用的:),今天回头看main.c,又搜索了一下,分享给大家:

 __setup(

//做了一次完整的盗贼,我毫无修改的抄袭了一次,但有时间会做量身裁减的//
关于__setup 在内核中的作用 

问题::
比如在printk.c有这样一句 
__setup("console=",console_setup); 
还有,在main.c中 
__setup("root=",root_dev_setup); 
人家的精彩回答:

你的这个问题,我从google上查找到了一些资料,再结合内核源代码,就在这里把这个问题说的清楚一点. 
首先,这里有一个简短的回答, 
http://mail.nl.linux.org/kernelnewbies/2003-03/msg00043.html 

从这上面的意思是这里会从main.c 中的checksetup函数中运行,这个函数是这样的 

static int __init checksetup(char *line) 
{ 
struct kernel_param *p; 

p = &__setup_start; 
do { 
int n = strlen(p->str); 
if (!strncmp(line,p->str,n)) { 
if (p->setup_func(line+n)) 
return 1; 
} 
p++; 
} while (p < &__setup_end); 
return 0; 
} 



这里的意思是从__setup_start开始处到__setup_end处中查找一个数据结构,这个数据结构中有str与setup_func这两个数据成员变量. 
只要与这里面的str与输入的参数字符串相匹配,就会调用个这个字符串后面所指的内容, 
对于你这里所说的 __setup("console=",console_setup); 就是你在启动linux内核的时候如果有这么一个参数输入console=ttyS1,那内核就会 
把默认的tty定位为ttyS1,这个在consol_setup函数的字符串处理中完成,因为它最后是确定prefered_console的参数. 


那把这在这里实现这个的内容是这样的, 

__setup() 是一个宏定义,在include/linux/init.h这个文件中. 
struct kernel_param { 
const char *str; 
int (*setup_func)(char *); 
}; 

extern struct kernel_param __setup_start, __setup_end; 

#define __setup(str, fn) \ 
static char __setup_str_##fn[] __initdata = str; \ 
static struct kernel_param __setup_##fn __attribute__((unused)) __initsetup = { __setup_str_##fn, fn } 

在这个情景中作了替换是这样的 

static char __setup_str_console_setup[] = "console="; 
static struct kernel_param __setup_console_setup = { __setup_str_console_setup, console_setup} 



这样你还可能不是很清楚,那你就要参考arch/i386/vmlinuz.lds这个关于ld 链接器的脚本文件有这样的一段 

__setup_start = .; 
.setup.init : { *(.setup.init) } 
__setup_end = .; 


这里的意思就是__setup_start是一个节的开始,而__setup_end是一个节的结束,这个节的名称是.setup,init, 
这个你可以用readelf -a这个来看一下你的vmlinux-2.4.20-8(后面的数字与你的内核版本有关)这个文件, 
可以看到有一个叫.setup.init的节,__setup_start就是指这个节的开始,那这个节中有什么内容呢,其实就是一个 
数据结构,一个就是str,一个就是setup_func,与我前面的说法相一致,那具体是什么呢,就是一个在.init.data节中存储的 
字符串-----__initdata是一个宏,就是(__attribute__ ((__section__ (".data.init")))), 所以你可以.data.init在vmlinux-2.4.20-8中的 
在文件中的偏移量与加载的的虚拟地址偏移量相减就可以得到, 
举个例子,所有的这些都是用readelf 与od 命令得到的 
我现在用的内核版本,它的.setup.init的节在0x26dd60的文件偏移处. 
[10] .data.init PROGBITS c0368040 268040 005d18 00 WA 0 0 32 
[11] .setup.init PROGBITS c036dd60 26dd60 0001b0 00 WA 0 0 4 

再查找console_setup在vmlinux-2.4.20-8所被映射为内存地址, 
840: c0355d40 343 FUNC LOCAL DEFAULT 9 console_setup 

这就可以知道了它所在的位置,就是0xc0355d40,这就是它的虚拟映射地址 

再用下面一条命令 
od --address-radix=x -t x4 vmlinux-2.4.20-8 |grep -A 20 26dd60 |head -20 | grep c0355d40 
可以得到 
26de40 c036943b c0355d10 c0369447 c0355d40 

很明显,这个函数的处理字符串在内存中的地址是0xc0369447,与前面得到的.data.init节在内存映射中的位置 
0xc0368040相减就是 0x1407,与.data.init在文件中的偏移量0x268040相加就得到0x269447 
这样用 
od --address-radix=x -a vmlinux-2.4.20-8 |grep -A 2 269440 

就可以得到下面的内容, 
269440 b l i n k = nul c o n s o l e = nul 
269450 r e s e r v e = nul nul nul nul nul nul nul nul 
269460 ` dc4 6 @ ` dc4 6 @ c p u f r e q = 

"console="这个值果真就在这里. 

(注:前面od 的选项 --address-radix= 表示的是显示文件偏移量的格式,默认下是o就是八进制, -t 表示显示文件二进制的形式
默认是o6 就是八进制的6位长,而-a表示显示的是字符串格式.) 


这是一点感受,与大家分享,希望大家提出宝贵意见. 
//////////////////////补充///////////////////////////

参见include/linux/init.h和vmlinux.lds 

1) 
所有标识为__init的函数在链接的时候都放在.init.text这个区段内, 
在这个区段中,函数的摆放顺序是和链接的顺序有关的,是不确定的。 

2) 
所有的__init函数在区段.initcall.init中还保存了一份函数指针, 
在初始化时内核会通过这些函数指针调用这些__init函数指针, 
并在整个初始化完成后,释放整个init区段(包括.init.text,.initcall.init等), 

注意,这些函数在内核初始化过程中的调用顺序只和这里的函数指针的顺序有关, 
和1)中所述的这些函数本身在.init.text区段中的顺序无关。 

在2.4内核中,这些函数指针的顺序也是和链接的顺序有关的,是不确定的。 

在2.6内核中,initcall.init区段又分成7个子区段,分别是 
.initcall1.init 
.initcall2.init 
.initcall3.init 
.initcall4.init 
.initcall5.init 
.initcall6.init 
.initcall7.init 

当需要把函数fn放到.initcall1.init区段时,只要声明 
core_initcall(fn); 
即可。 

其他的各个区段的定义方法分别是: 
core_initcall(fn) --->.initcall1.init 
postcore_initcall(fn) --->.initcall2.init 
arch_initcall(fn) --->.initcall3.init 
subsys_initcall(fn) --->.initcall4.init 
fs_initcall(fn) --->.initcall5.init 
device_initcall(fn) --->.initcall6.init 
late_initcall(fn) --->.initcall7.init 

而与2.4兼容的initcall(fn)则等价于device_initcall(fn)。 

各个子区段之间的顺序是确定的,即先调用.initcall1.init中的函数指针 
再调用.initcall2.init中的函数指针,等等。 
而在每个子区段中的函数指针的顺序是和链接顺序相关的,是不确定的。 

在内核中,不同的init函数被放在不同的子区段中,因此也就决定了它们的调用顺序。 
这样也就解决了一些init函数之间必须保证一定的调用顺序的问题。 

3) 
这些顺序和make dep没有关系。 

(转自http://blog.youkuaiyun.com/jifengszf/archive/2009/04/22/4100193.aspx)

内核组件用__setup宏来注册关键字及相关联的处理函数,__setup宏在include/linux/init.h中定义,其原型如下:
__setup(string, function_handler)
其 中:string是关键字,function_handler是关联处理函数。__setup只是告诉内核在启动时输入串中含有string时,内核要去 执行function_handler。String必须以“=”符结束以使parse_args更方便解析。紧随“=”后的任何文本都会作为输入传给 function_handler。
下面的例子来自于net/core/dev.c,其中netdev_boot_setup作为处理程序被注册给“netdev=”关键字:
__setup("netdev=", netdev_boot_setup);
不 同的关键字可以注册相同的处理函数,例如在net/ethernet/eth.c中为“ether =”关键字注册了同样的处理函数 netdev_boot_setup。当代码作为模块被编译时,__setup宏被忽视,你可以在include/linux/init.h中看到 __setup宏是怎样变化的,不管后续包含它的文件是否是模块,include/linux/init.h都是独立的。
start_kernel两次调用parse_args解析启动配置字符串的原因是启动选项事实上分为两类,且每次调用值能够兼顾到其中一类:

缺省选项:
绝大多数选项归于此类,这些选项由__setup宏定义并在第二次调用parse_args时处理。
先期(处理)选项:
在 内核启动阶段,有些选项要在其它选项之前被处理,内核提供了early_param宏以代替__setup宏申明此类选项。这些选项由 parse_early_params函数解析。early_param宏和__setup宏仅有的不同就是前者设置了一个特殊标志让内核能够区分两种不 同的状况。这个标志是我们将在“.init.setup内存区”小节中看到的obs_kernel_param结构的一部分。
启动时选项在内核 2.6中的处理方式已经改变,但并非所有的内核代码都因此而更新。在最近一次改变之前,还仅用__setup宏。因此,遗留下来将被更新的代码现在使用 __obsolete_setup宏。但用户用__obsolete_setup宏定义的选项给内核时,内核打印一条警告消息说明它已是废弃状态,并提供 一个文件指针和随后被公告的源代码行信息。
图7-1概述了几个宏之间的关系:它们都包裹了普通的__setup_param函数。


XGBoost的简单安装及入门使用 XGBoost安装及简单入门 XGBoost支持多种操作系统,如Windows, Linux, MacOS等,并支持多种语言版本,如Python, R, Scale, Java等。XGBoost的安装方式一般有两种,一种是直接通过pip安装(适合用于Python),另外一种是通过源码编译安装 1、通过pip安装 通过pip安装Python包既简单又方便,只需执行如下的命令: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple xgboost 使用 阅读详情

相关推荐

博科的SAN交换机基本操作

2、添加用户testuser赋予user权限可以访问1-128VF默认VF为128账号描述"Test user"密码为password123。1、创建zone别名(100是指当前设备Domain ID,1和2是指对应的index号)2,删除新接入设备的ZONE或保持ZONE配置一致。3、将zone添加到当前生效的CFG中。2、将zone添加到当前生效的CFG中。3、将zone添加到当前生效的CFG中。3,将添加的级联端口持续关闭。4、将当前zone生效。4、将当前zone生效。1、查看当前所有用户。

chenjunokok的博客 1837

linux kernel中__setup()函数介绍

setup1、__setup使用示例2、__setup宏原理3、__setup链接函数的调用 1、__setup使用示例 我们先看一个例子,在driver中,定义下面这一段函数,并加上__setup注册 static int __init skip_initramfs_param(char *str) { if (*str) return 0; do_skip_initramfs = 1; return 1; } __setup("skip_initramfs", skip_initramfs_p

baron-周贺贺-代码改变世界ctw 6840

IAR调试CC1310的错误:Fatal error:Failed to connect to the XDS emlulator (Error -241 @ 0x0:)

从simplelink_cc13x0_sdk_2_10_00_36导入collector工程后,rebuild后进行debug,出现了如图错误:Fatal error:Failed to connect to the XDS emlulator (connect ICEPick)...(Error -241 @ 0x0)A router subpath could not be accessed....

qq_40417648的博客 6228

Linux中__setup()实现原理以及源码分析

1. __setup()介绍 static __init int dma_debug_cmdline(char *str) { if (!str) return -EINVAL; if (strncmp(str, "off", 3) == 0) { pr_info("debugging disabled on kernel command line\n"); global_disable = true; } return 1; } static __init int dma_deb

assiduous_me的博客 2378

飞牛fnNAS个人小账本导入微信账单

本文介绍了将微信支付账单导入ezBookkeeping个人记账系统的详细方法。首先通过微信申请导出账单文件,接收后需进行Excel预处理:删除前导行、添加账户和分类列、整理金额格式等。在ezBookkeeping中需预先设置"微信"分类和账户。导入时需注意列映射关系,包括交易时间、账户名称等关键字段的对应设置。文章还提到处理交易标签、格式转换等细节问题,并建议避免使用"修改余额"功能。该方法同样适用于支付宝账单导入,解决了直接导入可能出现的格式不兼容问题。

dgnankai的专栏 482

在 Zynq 7010 上运行 VxWorks 7.0 的详细流程【持续更新】

本文介绍了在Zynq 7010开发板上运行VxWorks 7.0的完整流程。主要包括:1)使用Vivado创建硬件设计,配置Zynq模块并生成比特流文件;2)通过Workbench 4创建VxWorks工程,配置启动参数并生成镜像;3)下载运行步骤。此外还讲解了使用Workbench 4开发VSB和VIP工程的方法,包括工程创建、配置和调试流程。文中提供了关键操作截图和注意事项,为开发者提供了完整的Zynq 7010平台VxWorks开发解决方案。

weixin_45397344的博客 1223

android 在kernel中获取启动kernel命令行的参数

比如说要获取project_id这个参数 首先在kernel/init目录下的main.c中 int asus_PRJ_ID = 0; EXPORT_SYMBOL(asus_PRJ_ID); static int set_project_id(char *str) { printk("prj_id = %s\n", str); if( strcmp("0", str) == 0 ){

u013308744的专栏 2097

OpenClaw实战系列06:持久记忆与RAG知识库构建——让AI真正“记住”你

本文介绍了OpenClaw AI助理的持久记忆与RAG知识库构建功能。OpenClaw采用"文件即真理"的独特设计,所有记忆都以Markdown文件形式存储,支持直接编辑和Git版本管理。记忆系统分为三层:长期精炼记忆(MEMORY.md)、日常日志(按日期存储)和归档记忆。文章详细说明了环境配置步骤,包括安装必要组件、创建目录结构、设置API密钥,并提供了OpenClaw主配置文件的完整参数说明。该系统实现了跨会话、跨平台的持久化记忆,使AI助理能真正理解用户需求。

PeterPan的博客 1171

Linux内核 __setup宏分析

在解析cmdline时,我们经常会使用到__setup宏,用来处理kernel的cmdline。 #define __setup(str, fn) \ __setup_param(str, fn, fn, 0) #define __setup_param(str, unique_id, fn, early) \ static char __setup_str_##unique_id[] __in...

zhangdaxia2的博客 6332

高级数据结构之R树(R-tree)

R树(R-tree)是一种将B树扩展到多维情况下得到的数据结构,它最初由Antonin Guttman于1984年提出。B树的结点中会存储一个键的集合,这些键把线分成片段,沿着那条线的点仅属于一个片段。因此,B树使得我们可以很容易地找到点。如果把沿线各处的点表示成B树结点,我们就能够确定点所属唯一子结点,在那里可以找到该点。 Antonin Guttman在他提出R树的经典论文中给出的R树例子...

白马负金羁 1万+

基于截图详解:SAP GUI for Java 如何设置登录链接,以及 conn= 连接字符串该怎么写

摘要:SAP GUI for Java 的连接属性配置关键是在"高级"页签的"conn="后填写连接字符串。连接字符串格式取决于网络拓扑:直连应用服务器使用"/H/主机/S/端口";通过消息服务器负载均衡使用"/M/消息服务器/S/端口/G/组名";经SAProuter访问则需添加路由器前缀。配置时需注意专家模式会覆盖其他页签设置,且连接字符串还支持附加参数如客户端、语言和默认事务码。具体填写内容应根据Basis团队提供的系统信

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 250

__setup 在内核中的作用【转】

本文转载自:http://blog.youkuaiyun.com/lanmanck/article/details/7613305 本文来自: http://blog.chinaunix.net/uid-13798723-id-2871394.html 介绍的很详细,我也正好用了一次__setup(),蛮好用的:),今天回头看main.c,又搜索了一下,分享给大家: __set...

138

【Qt】QtCreator远程部署、调试程序

1)QtCreator 工具–> 选项 --> 设备 --> 添加2)设备设置向导选择–> Generic Linux Device --> 开启向导3)填写“标识配置的名称”(随便写)、设备IP、用户名 --> 下一步4)选择配对秘密文件,第一次配对,可以不填写,点击“下一步”5)点击“完成”6)设备添加成功,需要再配置SSH端口号、用户名、密码等7)保存SSH登陆密码:验证类型选择默认“Default”–> “创建新密钥”–> “Test”

郭老二 5193

__setup 在内核中的作用(转)

__setup( //做了一次完整的盗贼,我毫无修改的抄袭了一次,但有时间会做量身裁减的// from   http://www.linuxforum.net/forum/printthread.php?Cat=&Board=linuxK&main=470221&type=thread 关于__setup 在内核中的作用 问题:: 比如在printk.c有这样一句 __se

GoingArm的专栏 530

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

setup 函数在 Vue 3 中的作用是什么?什么时候会执行

setup()函数是Vue 3 中 Composition API 的核心入口,它在组件生命周期中扮演了非常关键的角色。setup()是 Vue 3 中组件逻辑的统一入口,在组件创建前执行,用于定义响应式状态、逻辑封装、生命周期注册、事件触发等,是 Composition API 的核心支点。就是把setup()函数**“自动内联展开”,省略return {}等冗余写法,让你写的每一行代码自动在 setup 环境中执行**。

Bruce__taotao的博客 2020

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

<script setup>中的setup作用以及和不带的区别对比

(即传统Options API)的区别主要体现在代码组织、复用性、类型支持等方面。函数是Composition API的核心入口,其作用与“不带。

bsklhao的博客 1070

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Vue 3中的setup()函数的作用是什么?

Vue 3中的setup()函数的作用是什么?

jnfy的博客 1139

linux的setup函数,__setup函数起什么作用

转自:=关于__setup 在内核中的作用你的这个问题,我从google上查找到了一些资料,再结合内核源代码,就在这里把这个问题说的清楚一点.首先,这里有一个简短的回答,从这上面的意思是这里会从main.c 中的checksetup函数中运行,这个函数是这样的static int __init checksetup(char *line){struct kernel_param *p;p = &a...

weixin_42416119的博客 1222

Python中Setup.py的作用是什么

Setup.py

gbz2000的博客 1674

vue3中setup的作用是什么?

我们可以在setup函数中声明响应式的数据和计算属性、注册事件处理函数、定义生命周期钩子函数、注册子组件、访问父级组件的属性和方法,以及访问路由和状态管理器等全局对象。Vue 3.0中的setup函数是一个全新的选项,它是在组件创建时执行的一个函数,用于替代Vue2.x中的beforeCreate和created钩子函数。在上面的代码中,我们使用provide函数提供了一个名为increment的函数,并在子组件中使用inject函数获取该函数。在setup函数中,我们返回了一个空对象。

2302_80729149的博客 1996

请说明 Vue 3 中的 setup() 函数的作用及其用法

setup()

有我更精彩的博客 1274

arduino中setup函数的作用_函数式编程中的副作用概念

前言为了清楚起见,请记住,副作用不是必需的坏事,有时副作用是有用的(尤其是在函数式编程范式之外)。今天聊一聊函数式编程中的隔离思想,它所想隔离的就是“副作用”我们先从其他角度来聊一聊副作用这个概念。生活中的副作用如果我听到副作用这个词后,第一反应是吃药? 。老话说是药三分毒,其中三分毒则为副作用。就比如你?感冒了,吃了一些西方某些国家研制的专利药品,然后感冒好了,但是感冒好了之后发现自己...

weixin_39789327的博客 1238

Linux内核__setup 宏的作用及分析

记录Linux中__setup 的作用

hinewcc的博客 1006
上一篇: SDIO接口
下一篇: 内核函数 do_div() 与 undefined reference to __udivdi3
#Page#
博客等级 码龄23年 1691粉丝 360原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值