zoukankan      html  css  js  c++  java
  • linux驱动——cmdline原理及利用【转】

    转自:https://blog.csdn.net/qingzhuyuxian/article/details/82895416

    最近安卓项目中想要获取内核cmdline特定的启动参数,因为我们在他的U-BOOT中定制了启动参数,需要在驱动中处理,这个手段其实很常见,今天mark个脚印。

    内核中如果你用cat /proc/cmdline,你会看见大致如下的打印:

    console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0...。当然如果我也可以在我们的项目比如扫描头的型号加个字段scanner=se955,等号赋值,name和value跟前后字段以空格分割。

    那么如何从中获取呢?!

    方法一:直接获取原始的cmdline的,就是获取/proc/cmdline属性值,在代码中就是读取全局变量saved_command_line这个字符串,然后自行处理,缺点是这个处理的时机比较晚,在设备驱动中处理,优点开发者自由度比较大。

    方法二:利用内核的__setup或者early_param。这个两个函数宏实质上是一样的,就是early_param比__setup先处理,优点他们在内核启动阶段运行,都在设备驱动前预先运行。上定义代码,

    1.  
      #define __setup_param(str, unique_id, fn, early) /
    2.  
      static char __setup_str_##unique_id[] __initdata = str; /
    3.  
      static struct obs_kernel_param __setup_##unique_id /
    4.  
      __attribute_used__ /
    5.  
      __attribute__((__section__(".init.setup"))) /
    6.  
      __attribute__((aligned((sizeof(long))))) /
    7.  
      = { __setup_str_##unique_id, fn, early }
    8.  
       
    9.  
      #define __setup(str, fn) /
    10.  
      __setup_param(str, fn, fn, 0)
    11.  
       
    12.  
      #define early_param(str, fn) /
    13.  
      __setup_param(str, fn, fn, 1)

    其中结构体定义如下:

    struct obs_kernel_param {
    const char *str;
    int (*setup_func)(char *);
    int early;
    };
    链接时以这个结构体保存在.init.setup段,实际在存储上就是个结构体数组。仔细看链接文件vmlinux.lds时,你会发现.init.setup实际上就是大致有这样的描述

    __setup_start = .; 
    *(.init.setup) 
    __setup_end = .;

    它的意思就是你所有定义的struct obs_kernel_param结构体变量连续序排在__setup_start 和__setup_end 存储之间,到时候就可以在这2个标记之间搜索。而__setup_start这个标记只被do_early_param和obsolete_checksetup。而这2个函数都是在kernel/init/main.c下的函数start_kernel中运行,并且do_early_param先运行,接着obsolete_checksetup后运行。调用大致流程如下start_kernel->parse_early_param->parse_early_options->parse_args->parse_one->do_early_param,而start_kernel->parse_args->parse_one->unknown_bootoption->obsolete_checksetup。翻代码代码中可见先调用__early_param定义的解析参数函数及__setup定义的(console及earlycon)的参数解析函数

    接着再调用__setup定义的其他解析参数函数。

    使用例子:

    1.  
      static int __init scanner_setup(char *str)
    2.  
      {
    3.  
      if (!str)
    4.  
      return 0;
    5.  
      if(!strcmp("se955",str)){
    6.  
      scanner_id = SCANNER_SE955;
    7.  
      }else if(!strcmp("ue966",str)){
    8.  
      scanner_id = SCANNER_UE966;
    9.  
      }else if(!strcmp("n4313",str)){
    10.  
      scanner_id = SCANNER_N4313;
    11.  
      }else if(!strcmp("n5600",str)){
    12.  
      scanner_id = SCANNER_N5600;
    13.  
      }else if(!strcmp("se655",str)){
    14.  
      scanner_id = SCANNER_SE655;
    15.  
      }else if(!strcmp("se4710",str)){
    16.  
      scanner_id = SCANNER_SE4710;
    17.  
      }else{
    18.  
      scanner_id = SCANNER_SE4500;
    19.  
      }
    20.  
      printk("%s %d ",__func__,scanner_id);
    21.  
      return 1;
    22.  
      }
    23.  
      __setup("scanner=", scanner_setup);

    该段代码对应于cmdline中的... scanner=se955 ...,这样的话,kernel已启动会先搜索scanner=字符串,如果找到的话就把=号后面的字符串值传递给给回调函数scanner_setup,这样的话str参数就是se955,并且这些代码是在设备驱动运行之前。

    NOTE:我碰到的问题,如果同一个字段被比如scanner字段,__setup使用两次,__setup(“scanner=”,fun_1)和__setup(“scanner=”,fun_2)在2个文件中,那么只会有1个被使用,谁先被链接,谁运行,另一个失效,因为运行不到他,代码决定,只匹配第一个。

    --------------------- 本文来自 sgmenghuo 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/sgmenghuo/article/details/41251739?utm_source=copy

  • 相关阅读:
    常见设计模型
    Python多版本编译安装&修改Python默认启动版本
    环境变量
    关于Bash命令的一些理解
    Sublime安装激活
    Python虚拟环境搭建
    Deepin Bug记录
    Deepin的使用感受
    代码实现Win+Key
    link
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/12028548.html
Copyright © 2011-2022 走看看