Chinaunix首页 | 论坛 | 博客
  • 博客访问: 183222
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 83
  • 用 户 组: 普通用户
  • 注册时间: 2016-03-23 13:37
文章分类

全部博文(80)

文章存档

2016年(80)

我的朋友

分类: LINUX

2016-03-23 15:37:38

     前两天把内核关于内核启动参数的一些知识彻底地分析了一遍《Linux内核源码分析--内核启动命令行的传递过程(Linux-3.0 ARMv7)》,发现了一些以前没有注意的细节问题,这里总结如下:

一、2.6.32以后的内核不再对cmdline中的未知参数输出警告信息
     以前在移植内核的时候,如果cmdline中有未知的参数,内核一般会打印如下警告:

  1. Unknown boot option `**********': ignoring
    但是这次我在uboot的bootargs中添加了内核未知的参数,比如“hello_linux.tekkaman=ninja”,但是在内核启动信息和dmesg中一点错误信息都没有,我感觉很奇怪,然后我又在同事的板子上试了下,一样没有任何错误信息。我查了下代码,按照逻辑,是不会有错误信息输出。哪以前怎么会有错误信息?
    后来我通过Git查找了内核针对这方面的修改,发现了如下提交:

  1. commit f066a4f6df68f03b565dfe867dde54dfeb26576e
  2. Author: Rusty Russell
  3. Date: Tue Dec 1 14:56:44 2009 +1030
  4. param: don't complain about unused module parameters.
  5. 参数:不抱怨未使用的模块参数。
  6. Jon confirms that recent modprobe will look in /proc/cmdline, so these
  7. cmdline options can still be used.
  8. 乔恩证实:新的modprobe会读取/proc/cmdline,所以这些
  9. 命令行选项仍然可能被使用。
  10. See
  11. Reported-by: Adam Williamson
  12. Cc: stable@kernel.org
  13. Signed-off-by: Rusty Russell
  14. Signed-off-by: Linus Torvalds
也就是说由于新版本的module-init-tool中的modprobe可以在挂外部.ko模块的时候读取/proc/cmdline(也就是内核启动参数cmdline的备份)中的参数,所有在内核启动的时候还暂时未知的参数可能在系统运行起来,挂载模块的时候被使用。所以在启动的时候提出警告实属不必要。所有这个警信代码被删除了。
这个提交的补丁如下:

  1. $ git diff f066a4f6df^..f066a4f6df
  2. diff --git a/init/main.c b/init/main.c
  3. index 5988deb..4051d75 100644
  4. --- a/init/main.c
  5. +++ b/init/main.c
  6. @@ -251,7 +251,7 @@ early_param("loglevel", loglevel);

  7. /*
  8. * Unknown boot options get handed to init, unless they look like
  9. - * failed parameters
  10. + * unused parameters (modprobe will find them in /proc/cmdline).
  11. */
  12. static int __init unknown_bootoption(char *param, char *val)
  13. {
  14. @@ -272,14 +272,9 @@ static int __init unknown_bootoption(char *param, char *val)
  15. if (obsolete_checksetup(param))
  16. return 0;

  17. - /*
  18. - * Preemptive maintenance for "why didn't my misspelled command
  19. - * line work?"
  20. - */
  21. - if (strchr(param, '.') && (!val || strchr(param, '.') < val)) {
  22. - printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param);
  23. + /* Unused module parameter. */
  24. + if (strchr(param, '.') && (!val || strchr(param, '.') < val))
  25. return 0;
  26. - }

  27. if (panic_later)
  28. return 0;
这个提交在2.6.32发布前被并入主线:

  1. $ git tag --contains f066a4f6df
  2. v2.6.32
  3. v2.6.33
  4. v2.6.33-rc1
  5. v2.6.33-rc2
  6. v2.6.33-rc3
  7. v2.6.33-rc4
  8. v2.6.33-rc5
  9. v2.6.33-rc6
  10. v2.6.33-rc7
  11. v2.6.33-rc8

就这个问题在:

点击(此处)折叠或打开

  1.  From  2009-09-11 16:28:54
  2. When passing a kernel parameter of the type:
  3. radeon.modeset=0
  4. the kernel will throw a warning message that says "Unknown boot option
  5. 'radeon.modeset=0'. Ignoring..." However, the parameter is not ignored, it is
  6. passed to (and parsed by) the radeon module.
  7. We (Fedora QA/BugZappers) find people are often confused or worried by this
  8. message when we ask them to use such a parameter, and worry that it is not
  9. being applied correctly. The kernel should not print this warning/error message
  10. when the parameter is of a format that will cause it to be passed to a kernel
  11. module.
  12. ------- Comment  From  2009-09-22 02:50:17 -------
  13. Is this because modern modprobe is scraping these options from /proc/cmdline?
  14. If so, yes, we should suppress those messages altogether.
  15. CC'd Jon, he'd know.
  16. ------- Comment  From  2009-09-22 04:51:52 -------
  17. I don't know how it's implemented, exactly, that may well be how it works. I
  18. just know that you can pass any module parameter as a kernel command line
  19. parameter in that format (modulename.moduleparameter=value) and it gets passed
  20. on somehow.
  21. ------- Comment  From  2009-11-26 17:43:30 -------
  22. ping? this still regularly causes confusion for users when we're trying to
  23. debug various issues, see
  24. for a recent example: it's a 'cosmetic' bug but with unfortunate effects.
  25. ------- Comment  From  2010-03-21 12:03:01 -------
  26. Yea, exactly that's what happens. Modprobe pulls out those arguments and
  27. processes them.
  28. I don't know why I missed this bug, but that should be fixed now. I even have
  29. daily reminders setup and should get CC'd on every module issue from now on.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
二、使用modprobe挂载.ko模块可以从cmdline中获取参数

    从上面的发现又牵出了一个新的发现,原来单独编译的内核模块参数是可以用modprobe挂载的时候从内核的cmdline中获得的。这个是我以前没有注意到的。于是我做了个实验:写一个简单的模块(仅在init函数中打印模块参数),然后在内核启动参数中增加这个参数的初始化。经几次实验,证实了这个功能。
    其实通过模块挂载的原理和模块的二进制结构的了解(详见《深入Linux内核构件》 第七章 模块),可以知道:其实这个功能是modprobe实现的。所以实现这个功能的必要条件是modprobe工具必须支持从/proc/cmdline读取字符串,并通过格式(模块名).(变量名)=(值)过滤出参数。

    这个大家特别注意一下参数的格式 :   

  1. (模块名).(变量名)=(值)

    在嵌入式中,高版本的busybox是支持的,现在最新的肯定支持,但是注意了,要配置busybox的时候不能选择"简化版的挂载工具",要配置为编译全功能的modprobe。

   在PC系统下也是支持的,在grub的内核启动参数中添加 hello_linux.tekkaman=ninja ,再用modprobe挂载模块。用dmesg看内核信息就可以看到实验结果。实验用的PC信息如下:

Linux Amethyst 3.2.12-gentoo #1 SMP Mon Apr 16 14:16:04 CST 2012 i686 AMD Athlon(tm) 64 X2 Dual Core Processor 4800+ AuthenticAMD GNU/Linux

module-init-tools version 3.16 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

嵌入式实验现象如下:

  1. # busybox modprobe hello_linux
  2. Hello, Linux !
  3. (0) Hello, ninja
  4. # cat /proc/cmdline
  5. console=ttyO2,115200n8 root=/dev/nfsroot nfsroot=10.10.10.2:/media/6a55c5a3-f467-4b31-a56a-73b57c5cd2a2/C6A816x/development/targetfs,nolock rw mem=176M@0x80000000 mem=39M@0x9BD00000 vram=90M notifyk.vpssm3_sva=0xBF900000 ip=10.10.10.10:10.10.10.2:0.0.1:255.255.255.0::eth0:off noinitrd earlyprink hello_linux.tekkaman=ninja
实验代码如下: test_module_i686.zip   


阅读(911) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~