Linux移植之tag参数列表解析过程分析

发布者:SerendipityRose最新更新时间:2024-08-26 来源: cnblogs关键字:Linux移植  tag 手机看文章 扫描二维码
随时随地手机看文章

172        __setup_param(str, fn, fn, 0)


先看__setup_param。它定义了两个参数,一个是char型的字符串__setup_str_##unique_id,另外一个为obs_kernel_param 结构体,它位于includelinuxInit.h。obs_kernel_param 结构体位于


.init.setup段,它的str参数即为__setup_str_##unique_id。__setup宏调用__setup_param传入两个参数str与fn,代表命令行名字与处理函数。

148    struct obs_kernel_param {

149        const char *str;

150        int (*setup_func)(char *);

151        int early;

152    };

 

2)、root=/dev/mtdblock3参数解析过程


回到initMain.c 中的start_kernel函数继续分析


525    setup_arch(&command_line);//返回的command_line是还未处理的命令行参数存放的首地址

526    setup_command_line(command_line);//static_command_line存放未处理的命令行参数,saved_command_line存放所有的命令行参数


544    printk(KERN_NOTICE 'Kernel command line: %sn', boot_command_line);//打印命令行参数

545        parse_early_param();//一些前期代码的初始化

546        parse_args('Booting kernel', static_command_line, __start___param,

547               __stop___param - __start___param,

548               &unknown_bootoption);//后续的命令处理


其中parse_early_param函数是对一些early属性的命令后做解析,它位于.early_param.init段,包括:cachepolicy=、nocache、nowb、ecc=、initrd=、mem=等等,我们的参数没有涉及到这类命令,所以不去细细的分析这个函数了。


重点关注parse_args函数,先分析函数的参数:


static_command_line                         :存放未处理的命令行参数首地址


__start___param                                 : 内核参数的存放地址,它处于__param段


__stop___param - __start___param  : 内核参数大小


unknown_bootoption                          : 处理函数


接着看到parse_args函数内部阶段,它位于kernelParams.c 下,可以看到在这里会将所有命令行处理完成。


144    while (*args) {//循环处理剩余的命令行,直到全部处理完成

145        int ret;

146        int irq_was_disabled;

147

148        args = next_arg(args, ¶m, &val);//找出下一个命令行参数*param为命令名称,*val为参数值

149        irq_was_disabled = irqs_disabled();

150        ret = parse_one(param, val, params, num, unknown);//处理


接着看到处理函数parse_one,它位于kernelParams.c 下。这里面还判断了一个内核的参数,我们传入的参数没有内核参数,内核参数存在于__param段,有:nousb、block2mtd_setup等等,我们传入的命令行参数没有内核参数,所以不关心


49    static int parse_one(char *param,

50                 char *val,

51                 struct kernel_param *params, 

52                 unsigned num_params,

53                 int (*handle_unknown)(char *param, char *val))

54    {

55        unsigned int i;

56

57        /* Find parameter */

58        for (i = 0; i < num_params; i++) {//从__param段找出与命令行参数相同的名字

59            if (parameq(param, params[i].name)) {

60                DEBUGP('They are equal!  Calling %pn',

61                       params[i].set);

62                return params[i].set(val, ¶ms[i]);//如果是内核的参数,那么直接传给内核参数,然后返回。

63            }

64        }

65    

66        if (handle_unknown) {//如果不是内核的参数,并且处理函数存在

67            DEBUGP('Unknown argument: calling %pn', handle_unknown);

68            return handle_unknown(param, val);//调用处理函数处理

69        }

70

71        DEBUGP('Unknown argument `%s'n', param);

72        return


接着看到handle_unknown函数,即unknown_bootoption函数,它位于initMain.c中,截取其中的一段程序


260        /* Change NUL term back to '=', to make 'param' the whole string. */

261        if (val) {//如果val不为空,做一些处理

262            /* param=val or param='val'? */

263            if (val == param+strlen(param)+1)

264                val[-1] = '=';

265            else if (val == param+strlen(param)+2) {

266                val[-2] = '=';

267                memmove(val-1, val, strlen(val)+1);

268                val--;

269            } else

270                BUG();

271        }

272    

273        /* Handle obsolete-style parameters */

274        if (obsolete_checksetup(param))

275            return 0;


接着看到obsolete_checksetup函数,它同样位于initMain.c中,这个函数大致的意思就是在.init.setup中找到符合的命令行参数,如果不是前期已经处理的参数(即early值为0的参数,那么调用处理函数处理它。它由__setup宏定义或者__setup_null_param宏定义(这两个宏定义前面已经介绍过了),搜索一下这两个宏定义,发现了__setup('root=', root_dev_setup);、__setup('init=', init_setup);、__setup('console=', console_setup);都在这里面被处理。


190    static int __init obsolete_checksetup(char *line)

191    {

192        struct obs_kernel_param *p;

193        int had_early_param = 0;

194    

195        p = __setup_start;//.init.setup的首地址

196        do {

197            int n = strlen(p->str);

198            if (!strncmp(line, p->str, n)) {//在.init.setup中寻找相符的命令行参数

199                if (p->early) {//如果early大于0,那么这个参数在前面已经处理过了

200                    /* Already done in parse_early_param?

201                     * (Needs exact match on param part).

202                     * Keep iterating, as we can have early

203                     * params and __setups of same names 8( */

204                    if (line[n] == '' || line[n] == '=')

205                        had_early_param = 1;

206                } else if (!p->setup_func) {//如果处理函数不存在,则报错

207                    printk(KERN_WARNING 'Parameter %s is obsolete,'

208                           ' ignoredn', p->str);

209                    return 1;

210                } else if (p->setup_func(line + n))//调用处理函数处理

211                    return 1;

212            }

213            p++;

214        } while (p < __setup_end);

215

216        return had_early_param;

217    }


接着分析__setup('root=', root_dev_setup)宏,它位于kernelPrintk.c下,可以看到它调用的是root_dev_setup函数来处理root=参数,接着看root_dev_setup函数


211    static int __init root_dev_setup(char *line)

212    {

213        strlcpy(saved_root_name, line, sizeof(saved_root_name));

214        return 1;

215    }

216

217    __setup('root=', root_dev_setup);


可以看到它的处理函数直接将root命令行参数拷贝到saved_root_name里,接着搜索一下在哪里调用的saved_root_name。找到了在initDo_mounts.c 中的prepare_namespace函数用到了它,这个函数的作用是挂接根文件系统的。列出部分代码:如何挂接根文件系统后面说明


430        if (saved_root_name[0]) {

431            root_device_name = saved_root_name;//将saved_root_name赋给root_device_name

432            if (!strncmp(root_device_name, 'mtd', 3)) {

433                mount_block_root(root_device_name, root_mountflags);

434                goto out;

435            }

436            ROOT_DEV = name_to_dev_t(root_device_name);

437            if (strncmp(root_device_name, '/dev/', 5) == 0)

438                root_device_name += 5;

439        }


3)、init=/linuxrc参数解析过程


前面已经分析了命令行参数的提取过程,这里直接看到宏定义__setup('init=', init_setup)。处理init=参数的是init_setup函数,来到Init_setup函数,它位于


initMain.c 中


315    static int __init init_setup(char *str)

316    {

317        unsigned int i;

318

319        execute_command = str;

320        /*

321         * In case LILO is going to boot us with default command line,

322         * it prepends 'auto' before the whole cmdline which makes

323         * the shell think it should execute a script with such name.

324         * So we ignore all arguments entered _before_ init=... [MJ]

325         */

326        for (i = 1; i < MAX_INIT_ARGS; i++)

327            argv_init[i] = NULL;

328        return 1;

329    }

330    __setup('init=', init_setup);


可以看到init_setup函数直接将init=的命令行参数拷贝到execute_command 中,搜索execute_command ,在initMain.c函数下找到了init_post函数,这是start_kernel函数最后调用的一个函数rest_init建立的一个进程函数。取出部分内容,可以看到execute_command是内核运行的根文件系统上的第一个进程

[1] [2] [3]
关键字:Linux移植  tag 引用地址:Linux移植之tag参数列表解析过程分析

上一篇:一、编写 s3c24x0 的 bootloader——介绍、看门狗及时钟设置
下一篇:Linux移植之内核启动过程start_kernel函数简析

推荐阅读最新更新时间:2024-11-13 16:47

【ARM】Linux驱动移植
#1驱动模块移植过程 ##1.1模块的第一种编译方法——改kconfig 第一步:改kconfig 文件在:Drivers/char/kconfig; tristate三态表示可以编译在模块 M ; bool表示只能被选择编 或不编 。 第二步:配置内核 make menuconfig后会自动生成供编译的.config文件。 wuchengbing@ubuntu:~/linux/kernel-2.6.13$ make menuconfig Device Drivers --- Character devices --- S3C2410 RTC Driver │ │
[单片机]
【ARM】<font color='red'>Linux</font>驱动<font color='red'>移植</font>
Linux-2.6.32.2内核在mini2440上的移植(十四)---移植看门狗驱动
移植环境 1,主机环境:VMare下CentOS 5.5 ,1G内存。 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linux-gcc v4.4.3,arm-none-linux-gnueabi-gcc v4.5.1。 4,开发板:mini2440,2M nor flash,128M nand flash。 5,u-boot版本:u-boot-2009.08 6,linux 版本:linux-2.6.32.2 7,参考文章: 嵌入式linux应用开发完全手册,韦东山,编著。 Mini2440 之Linux 移植开发实战指南 Linux-2.6.32.2 内核具有完善的S3C2440 的看梦狗驱动,我们只需配
[单片机]
嵌入式Linux之我行——u-boot-2009.08在2440上的移植详解(一)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器: arm-linux-gcc-4.3.2.tgz u-boot: u-boot-2009.08.tar.bz2 二、移植步骤 本次移植的功能特点包括: 支持Nand Flash读写 支持从Nor/Nand Flash启动 支持CS8900或者DM9000网卡 支持Yaffs文件系统 支持USB下载(还未实现) 1. 了解u-boot主要的目录结构和启动流程,如下图。 u-boot的stage1代码通常放在cpu/xxxx/sta
[单片机]
嵌入式<font color='red'>Linux</font>之我行——u-boot-2009.08在2440上的<font color='red'>移植</font>详解(一)
ARM9:如何将linux2.6.38内核移植到TQ2440
  下面是linux2.6.38内核移植到TQ2440的具体步骤:   1.修改根目录的Makefile中的ARCH=arm,CROSS-COMPILE=arm-linux-   2.在arch/arm/mach-s3c2440/mach-smdk2440.c中,将163行的s3c24xx_init_clocks(16934400)改为s3c24xx_init_clocks(12000000)。   3.修改arch/arm/tools/mach-types中379行的362改为168,因为uboot中定义的机器码是168.   4.修改arch/arm/boot/中的Makefile文件,在58行添加@cp -f
[单片机]
linux-2.6.32在mini2440开发板上移植-配置USB外设
编者:因为LINUX内核对S3C2440的Host驱动的已经支持,而且支持的外设相当的丰富,所以这一部分只是进行配置就可以使用。因为配置的东西较多,没有给出详细的截图,看手册上介绍的就很明白。需要手册的请留下邮箱索取。 1 配置和测试USB 键盘、扫描器和鼠标 在内核源代码目录的终端输入:make menuconfig,依次选择如下子菜单项: Device Drivers --- HID Devices --- 按空格键选中“USB Human Interface Device (full HID) support”,这样就配置好了USB键盘和鼠标项。 提示:这里的配置选项对应的内核源代码目录是:linux-
[单片机]
Boa服务器在ARM+Linux上的移植
一、Boa服务器介绍 Boa是一种非常小巧的Web服务器,其可执行代码只有大约60KB左右。 作为一种单任务Web服务器,Boa只能依次完成用户的请求,而不会fork出新的进程来处理并发连接请求。但Boa支持CGI,能够为CGI程序fork出一个进程来执行。Boa的设计目标是速度和安全。 二、移植环境 (1) 源码的获取 Boa的源码可以从网站www.boa.org获取 (2) Boa移植平台 n PC机(RedHat9.0操作系统) n 交叉编译工具,arm-linux,最好是2.9的 三、移植步骤 (1) 解压源码$ tar xzvf boa-0.94-14.tar.gz (2) $cd boa-0.
[单片机]
移植标准Linux 操作系统到S3C2410
1 前 言 目前 , 在嵌入式系统里基于ARM核的嵌入式处理器已经成为市场主流。随着ARM技术的广泛应用 , 建立面向ARM构架的嵌入式操作系统也就成为当前研究的热点。S3C2410是SAMSUNG公司基于ARM920T处理器内核开发的一款16/32位嵌入式处理器,运行 频率 高达200多M,具有MMU和高速缓存等丰富片上资源,是目前基于ARM920T内核的出货量最大的一款芯片。目前嵌入式操作系统也较多,如 Tor2nado 的VxWork、微软的 Windows CE等等。大量开发人员选择的却都是Linux,这是因为它源代码开放,可以轻松修改移植到自己的目标平台系统里使用。并且事实证明,效果令人满意。两者的结合必将在嵌入
[单片机]
S3C2440 Linux驱动移植——NAND驱动
1. 修改分区表 打开文件arch/arm/plat-s3c24xx/common-smdk.c,修改mtd_partition结构体数组。 修改后如下: view plain copy static struct mtd_partition smdk_default_nand_part = { = { .name = Uboot , .size = 0x00040000, .offset = 0x00000000, }, = { .name = K
[单片机]
S3C2440 <font color='red'>Linux</font>驱动<font color='red'>移植</font>——NAND驱动
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved