内核启动参数

学习了好几种fs后,我们先缓缓,再次了解参数,这次不是模块参数,而是启动参数了,该参数是引导程序bootloader传递给kernel的配置参数,与模块参数一样是只能在初始化加载时使用,交互性弱,功能切换强,属于“不动产”配置,越少修改越好。
使用内核启动参数,需要使用到include/linux/init.h文件里的如下宏:
#define __setup(str, fn) \
        __setup_param(str, fn, fn, 0)
其中,str为对应的启动参数名,fn是对该传入参数进行处理的函数。
而在Linux内核中也提供了整数参数值对应的处理函数,在lib/cmdline.c文件中有get_option和get_options两人函数的定义,前一个是针对于只有一个整数的情况,后一个则是针对以逗号分隔的一串整数的情况,而对于字符串则需要自行处理了,下面还是先上例子吧,注意这次源码需放至Kernel源码里来编译了,作为启动参数,当然是在内核的最前获取并处理了,还能留到模块加载时再处理吗?除非是获取处理后的值。
下面上代码并说明添加步骤:
1.在Linux Kernel源码下创建slam_boot_example目录:
执行cd ~/linux-3.13.6 && mkdir slam_boot_example命令;
2.在slam_boot_example添加如下文件:
a.Makefile文件,内容为obj-y += slam_boot_example.o b.slam_boot_example.c文件,内容如下:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>

#define MAX_SLAM_SIZE 5
#define MAX_SLAM_STRING_LEN 16

static int slam_boot_int;
static int slam_boot_int_array[MAX_SLAM_SIZE];
static char slam_boot_string[MAX_SLAM_STRING_LEN];

static int __init slam_parse_int(char *s)
{
        int ret;

        ret = get_option(&s, &slam_boot_int);
        if(ret == 1)
                printk("slam_boot_int=%d\n", slam_boot_int);
        return 1;
}

static int __init slam_parse_int_array(char *s)
{
        char * ret_slam_str;
        int i;

        ret_slam_str = get_options(s, MAX_SLAM_SIZE, slam_boot_int_array);
        if(*ret_slam_str != '\0')
        {
                printk("incorrect slam_boot_int_array parameters: %s\n", ret_slam_str);
        }
        else
        {
                printk("slam_boot_int_array=");
                for(i=1; i<MAX_SLAM_SIZE; i++)
                {
                        printk("%d",slam_boot_int_array[i]);
                        if(i<(MAX_SLAM_SIZE-1))
                                printk(",");
                }
                printk("\n");
                printk("slam_boot_int_array includes %d intergers\n", i);
        }
        return 1;
}

static int __init slam_parse_string(char *s)
{
        if(strlen(s) > MAX_SLAM_STRING_LEN)
        {
                printk("Too long slam_boot_string parameter!\n");
                printk("Maximum length is less than or equal to %d\n", MAX_SLAM_STRING_LEN);
        }
        else
        {
                memcpy(slam_boot_string, s, strlen(s)+1);
                printk("slam_boot_string=%s\n", slam_boot_string);
        }
        return 1;
}

__setup("slam_boot_int=", slam_parse_int);
__setup("slam_boot_int_array=", slam_parse_int_array);
__setup("slam_boot_string=", slam_parse_string);
3.修改Linux Kernel源码根目录下的Makefile,将core-y := usr/修改为core-y := usr/ slam_boot_example/
4.重新编译Linux Kernel,在Linux Kernel源码目录下执行make命令即可;
5.新内核安装好后,那如何传参数呢?我们使用的Ubuntu13.10默认使用Grub2,我们修改/etc/default/grub文件,将GRUB_CMDLINE_LINUX=”” 修改为GRUB_CMDLINE_LINUX=”slam_boot_int=7890 slam_boot_int_array=123,345,678,911 slam_boot_string=stxinu”
6.在Linux Kernel源码目录下执行make install命令安装编译好的Linux Kernel,此时的/boo/grub/grub.cfg里新启动项就包含上面的内容,接下来,我们重启Ubuntu吧,重启后在命令行下运行dmesg | grep slam可以看到如下输出:
[ 0.000000] slam_boot_int=7890
[ 0.000000] slam_boot_int_array=123,345,678,911
[ 0.000000] slam_boot_int_array includes 5 intergers
[ 0.000000] slam_boot_string=stxinu
因为在源码里的MAX_SLAM_SIZE是5,而i循环退出后值为5,故而上面输出是包含5个整型数,输出内容自行处理,关键还是会用这个启动参数。
至此,我们的启动参数体验了一下,后面继续走向另一个内核态与用户态交换数据的新高点吧。
参考网址:
http://www.embeddedlinux.org.cn/html/yingjianqudong/201304/17-2549.html
http://www.ibm.com/developerworks/cn/linux/l-kerns-usrs/index.html
http://wiki.ubuntu-tw.org/index.php?title=GRUB2%E4%B8%AD%E6%96%87%E6%8C%87%E5%8D%97%E7%AC%AC%E4%BA%8C%E7%89%88(%E4%B8%8A%EF%BC%89#.E8.A8.AD.E5.AE.9A_GRUB_2

评论

此博客中的热门博文

I/O映射之I/O端口

通过Netlink检测网线插拔

使用seq_file