• uboot&&grub 调试内核时的参数


    目前信创设备有bootloader or grub引导内核,其中

    grub:

     linux  /bzImage console=ttyS0,115200 ramdisk_size=60000 earlycon=ppl011,mmio32,0x28001000  bonding.miimon=100 bonding.mode=active-backup libata.dma=5 quiet root=/dev/ram0 rw pci=noaer pcie_aspm=off net.ifnames=0
     initrd  /initrd.gz

    bootload:

    bootargs root=/dev/mtdblock2 console=ttySAC0 init=/linuxrc
    • root:指定根文件系统的位置,比如:root=/dev/mtdblock3 , mtdblock3 代表mtdparts的第4分区 (第一个分区为mtdblock0) 如果指定 root=/dev/nfs,还需要指定nfsroot=serverip:nfs_dir
    • console:设置控制台参数,比如:console=ttySAC0,115200 , 使用串口0作为控制台,波特率为115200 。串口设备要根据实际的设备名称来设置。
    • rootfstype:指定根文件系统的类型,这个选项需要跟root一起配合使用,一般如果根文件系统是ext2的话,有没有这个选项是无所谓的,但是如果是jffs2,squashfs等文件系统的话,就需要rootfstype指明文件系统的类型,不然会无法挂载根分区。
    • ramdisk_size:指定创建的ramdisk的大小,ramdisk是将内存中的一块区域作为物理磁盘使用的一种技术
    • init:指定内核启动后第一个执行的脚本,比如:init=/linuxrc
    • initrd:指定ramdisk在内存中的位置和大小

    有个疑问grub or uboot 解析完参数后传给内核! 内核怎样解析参数。

    以quite net.ifname=0  log_level为例:

    init/main.c中:

    static int __init quiet_kernel(char *str)
    {
        console_loglevel = CONSOLE_LOGLEVEL_QUIET;
        return 0;
    }
    early_param("quiet", quiet_kernel);
    static int __init loglevel(char *str)
    {
        int newlevel;
        /*
         * Only update loglevel value when a correct setting was passed,to prevent blind crashes (when loglevel being set to 0) thatare quite hard to debug
         */
        if (get_option(&str, &newlevel)) {
            console_loglevel = newlevel;
            return 0;
        }
        return -EINVAL;
    }
    early_param("loglevel", loglevel);

      当内核 cmdline 中设定了 quiet 参数后,quiet_kernel 函数会被调用,这个函数会将 console_loglevel 设定为CONSOLE_LOGLEVEL_QUIET=4

      我们知道内核是依次执行各个section代码段代码。来看early_param的宏定义展开。

    /*
     * Only for really core code.  See moduleparam.h for the normal way.
     *
     * Force the alignment so the compiler doesn't space elements of the
     * obs_kernel_param "array" too far apart in .init.setup.
     */
    #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 }
    
    #define __setup(str, fn)                        \
        __setup_param(str, fn, fn, 0)
    
    /*
     * NOTE: fn is as per module_param, not __setup!
     * Emits warning if fn returns non-zero.
     */
    #define early_param(str, fn)                        \
        __setup_param(str, fn, fn, 1)

    扩展后结果为:

     static const char __setup_str_loglevel[] __initconst  __aligned(1) = "loglevel";     
        struct obs_kernel_param _setup_loglevel 
          __used __section(.init.setup)
          __attribute__((aligned((sizeof(long)))))
        = { .str = "__setup_str_loglevel", .setup_func = loglevel, .early = 1, };
    /* These are for everybody (although not all archs will actually
       discard it in modules) */
    #define __init        __section(.init.text) __cold notrace
    #define __initdata    __section(.init.data)
    #define __initconst    __constsection(.init.rodata)
    #define __exitdata    __section(.exit.data)
    #define __exit_call    __used __section(.exitcall.exit)

    其含义为:

    • const char __setup_str_loglevel[]其值为 “loglevel”,存放在 .init.rodata section 中并以 1 字节为单位对齐
    • struct obs_kernel_param _setup_loglevel 此结构体以 sizeof(long) 字节对齐并存放到 .init_setup section 中

    内核启动的时候其会调用如下函数:

    start_kernel
    setup_arch parse_early_param parse_early_options parse_args parse_one do_early_param
    /* Arch code calls this early on, or if not, just before other parsing. */
    void __init parse_early_param(void)
    {
        static int done __initdata;
        static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
    
        if (done)
            return;
    
        /* All fall through to do_early_param. */
        strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
        parse_early_options(tmp_cmdline);
        done = 1;
    }
    /* Check for early params. */
    static int __init do_early_param(char *param, char *val,
                     const char *unused, void *arg)
    {
        const struct obs_kernel_param *p;
    
        for (p = __setup_start; p < __setup_end; p++) {
            if ((p->early && parameq(param, p->str)) ||
                (strcmp(param, "console") == 0 &&
                 strcmp(p->str, "earlycon") == 0)
            ) {
                if (p->setup_func(val) != 0)
                    pr_warn("Malformed early option '%s'\n", param);
            }
        }
        /* We accept everything at this stage. */
        return 0;
    }
    #define INIT_SETUP(initsetup_align)                    \
            . = ALIGN(initsetup_align);                \
            VMLINUX_SYMBOL(__setup_start) = .;            \
            *(.init.setup)                        \
            VMLINUX_SYMBOL(__setup_end) = .;

      do_early_params 函数的第一个参数是上层传入的 cmd 的唯一标识,然后 do_early_params 函数遍历 __setup_start以及 __setup_end代码段区域内遍历每一个 cmd实例--->obs_kernel_param,匹配到了则调用相应的 setup_func hook函数!!
    关于section,目前内核连接各个模块等都是通过section来存放链接。

       以下为内核启动参数参考:

    Console Options                        
    参数 说明 选项 内核配置/文件  
    console=Options 用于说明输出设备 ttyn 终端 ttySn[,options], ttyUSB0[,options] 串口uart,io,addr[,options],uart,mmio,addr[,options]&<60;    
    netconsole=[src-port]@[src-ip]/[dev],[target-port]@target-ip/[targetmac-address]    
    debug Enable kernel debugging. 启动时将所有的调试信息都输出到控制台    
    quiet Disable all log messages. 相当于loglevel=KERN_WARNING    
    earlyprintk=[vga|serial][,ttySn[,baudrate]][,keep] 打印传统的控制台初始化前的信息,主要是硬件相关的信息    
    loglevel=level 设置默认的控制台记录级别 所有的较高级别的信息将被打印(0-7) /proc/sys/kernel/printk  
    log_buf_len=n[KMG] 设置内核记录缓冲区大小 为2的冥 CONFIG_LOG_BUF_SHIFT  
    initcall_debug 调试系统初始化函数 跟踪系统启动时用到的所有的函数    
    kstack=n Oops栈的多少个字被输出 n为整数    
    time 在记录信息前面显示时间      
     
    Interrupt Options(Advanced Programmable Interrupt Controller APIC)  
    apic=[quiet|verbose|debug] 改变ACPI子系统启动时的记录级别 默认为quite    
    noapic 不用任何IOAPICs      
    lapic 使本地ACPI有效 即使BOIS使得它无效,也要让它有效    
    nolapic 不使用ACPI      
    noirqbalance 使内核内建的Irq平衡逻辑无效      
    irqfixup 基本的中断问题修复 当一个中断没有被处理,搜索所有的中断处理看看能不能用    
    irqpoll 扩展的中断问题修复 在每一个时钟中断,检查每一个中断处理    
    noirqdebug 禁止未处理的中断自动探测 默认情况下,内核试着探测并且禁止未处理的中断源,以免引起未知的问题,这个选项禁止该功能。    
     
    Memory Options  
    highmem=n 说明高内存区域的大小 强制高端内存有大小为n的精确的内存区域,不管系统有没有高端内存,也可以用于减少大内存系统中的高端内存大小    
    hugepages=n 设置hugetlb页的数量      
    ihash_entries=n 设置Inode哈希表的大小 用于覆盖内核的默认值    
    max_addr=n 设置内存的最大地址 内核将忽略在该地址以上的物理内存    
    mem=n[KMG] 设置内存使用的内存数 当使用memmap选项时,能避免物理地址空间的冲突。如果不用memmap选项,可能引起PCI设备被放到未用的RAM空间。    
    mem=nopentium 内核禁用大页(4M)      
    memmap=exactmap 使用特定的内存映像      
    memmap=n[KMG]@start[KMG] 强制内核使用特定的内存区域 n,是表内存区域的大小,start指内存区域的开始位位置    
    noexec=[on|off] 禁/启用内核将一个内存区域映像为不可执行内存的的功能。默认为on.    
    reserve=n[KMG] 强制内核忽略IO内存区域 预留IO内存区域    
    vmalloc=n[KMG] 强制vmalloc有的个特定的大小 可用于增加vmalloc区域的最小值,也可以用于减少vmalloc的大小,增加更多的空间用于直接映射内核RAM    
    norandmaps 不用地址空间随机化 默认内核随机化程序启动的地址,该选项禁用该功能 /proc/sys/kernel/randomize_va_space写0相当      
    vdso=[0|1] 禁/启用vdso映像 (Virtual Dynamic Shared Object),默认为启用  
         
    Suspend Options  
    resume=suspend_device 说明休眠文件的分区设备  
    noresume 禁用休眠功能  
     
    Ramdisk Options  
    initrd=filename initrd Ramdisk的位置 说明内核启动时要用到的Ramdisk的位置    
    load_ramdisk=n 从软盘加载Ramdisk n=1,则从软盘加载ramdisk    
    noinitrd 不用任何Initrd,即使参数时面指定了      
    prompt_ramdisk=1 在从软驱中读取ramdisk之前提示用户      
    ramdisk_blocksize=n ramdisk的块尺寸      
    ramdisk_size=n 说明ramdisk的大小      
             
    Root Disk Options  
    ro 启动时以只读方式挂载根文件系统 如果在它之前有rw的选项,ro将会取代它  
    root=device 说明系统启动的根文件系统 nnnn 十六的制备号(以内核可识别的方式表示major和minor)/dev/nfs/dev/<diskname>/dev/<diskname><decimal>/dev/<diskname>p<decimal>(要求diskname以数字结尾)  
    rootdelay=n 挂载文件系统前的延迟 主要是当根文件系统在USB or FireWire设备上  
    rootflags=options 根文件系统挂载选项    
    rootfstype=type 根文件系统的类型 例如:rootfstype=ext3  
    rw 启动时以读写方式挂载根文件系统    
     
    Init Options  
    init=filename 在Init时,应该执行的程序 默认为/sbin/Init  
    rdinit=full_path_name 从ramdisk中运行Init进行 指定的文件必须是在ramdisk而不是在root文件系统中  
    S 运行Init在单用户模式中    
     
    Network Options  
    netdev=[irq],[io],[mem_start],[mem_end],[name] 设备各咱网络参数  
    thash_entries 设置TCP连接哈希表的最大数目  
     
    Network File System Options  
    lockd.nlm_grace_period=n 设备恰当的锁管理周期 以秒为单位  
    lockd.nlm_tcpport=port 为NFS锁管理者设置端口(TCP)    
    lockd.nlm_timeout=n NFS锁管理者超时 默认为十秒  
    lockd.nlm_udpport=port 为NFS锁管理者设置端口(UDP)    
    nfsroot=[server-ip:]root-dir[,nfs-options] 为无盘系统,说明NFS根文件系统,如果参数没有设置默认为/tftpboot/client_ip_address  
    nfs.callback_tcpport=port 为回调通道设置NFSv4&<60;TCP端口    
     
    Hardware-Specific Options  
    nousb 没有USB设备      
    lp=[0|port[,port…]|reset|auto] 设置并行端口和其模式 lp=auto内核将检查所有端口,看有没有IEEE&<60;1284兼容的打印机    
    parport=[setting[,setting…] 说明并行端口参数  
    parport_init_mode=[spp|ps2|epp|ecp|ecpepp] 并行端口初始化模式  
    nr_uarts=n 最大的UART被注册的数目  
    panic=n 系统panic后重启最大等时间 默认为0,系统将不重新启动,仅仅挂起  
    pause_on_oops=n 告诉内核,当第一个Oops出现后,挂起所有的CPU,n秒,以便记录下现场  
    combined_mode=[combined|ide|libata] 说明IDE驱动  
  • 相关阅读:
    linux grep显示行数和上下行内容
    Network-Emulator Network-Emulator-Toolkit网络模拟器使用详细介绍(弱网测试工具)
    Fiddler抓包8-打断点(bpu)
    fiddler---Fiddler弱网测试
    详谈基数排序
    hadoop下的Pipes(用C++进行hadoop程序开发)
    hadoop环境安装及简单Map-Reduce示例
    每天一道面试题(2):实现strncpy
    每天一道面试题(1):快速排序
    结合源码看nginx-1.4.0之nginx多进程机制详解
  • 原文地址:https://www.cnblogs.com/codestack/p/16412716.html
Copyright © 2020-2023  润新知