最近安卓项目中想要获取内核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先处理,优点他们在内核启动阶段运行,都在设备驱动前预先运行。上定义代码,

#define __setup_param(str, unique_id, fn, early)            /
    static char __setup_str_##unique_id[] __initdata = str;    /
    static struct obs_kernel_param __setup_##unique_id    /
        __attribute_used__                /
        __attribute__((__section__(".init.setup")))    /
        __attribute__((aligned((sizeof(long)))))    /
        = { __setup_str_##unique_id, fn, early }
        
#define __setup(str, fn)                    /
    __setup_param(str, fn, fn, 0)
    
#define early_param(str, fn)                    /
    __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定义的其他解析参数函数。

使用例子:
static int __init scanner_setup(char *str)
{
    if (!str)
        return 0;
    if(!strcmp("se955",str)){
        scanner_id = SCANNER_SE955;
    }else if(!strcmp("ue966",str)){
        scanner_id = SCANNER_UE966;
    }else if(!strcmp("n4313",str)){
        scanner_id = SCANNER_N4313;
    }else if(!strcmp("n5600",str)){
        scanner_id = SCANNER_N5600;
    }else if(!strcmp("se655",str)){
        scanner_id = SCANNER_SE655;
    }else if(!strcmp("se4710",str)){
        scanner_id = SCANNER_SE4710;
    }else{
        scanner_id = SCANNER_SE4500;
    }
    printk("%s %d\n",__func__,scanner_id);
    return 1;
}
__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 
版权声明:本文为博主原创文章,转载请附上博文链接!

linux驱动——cmdline原理及利用相关推荐

  1. linux下nand flash驱动工作原理,1.3.4. Nand flash驱动工作原理

    1.3.4. Nand flash驱动工作原理 在介绍具体如何写Nand Flash驱动之前,我们先要了解,大概的整个系统,和Nand Flash相关的部分的驱动工作流程,这样,对于后面的驱动实现,才 ...

  2. Linux驱动中按键消抖原理

    为什么要用定时器来做按键消抖? 用到按键就要处理因为机械结构带来的按键抖动问题,也就是按键消抖.前面的实验中都是直接使用了延时函数来实现消抖,因为简单,但是直接用延时函数来实现消抖会浪费 CPU 性能 ...

  3. 利用Eclipse开发Linux驱动

    之前写Linux驱动都是在纯文本下完成的,最近发现原来可以使用Eclipse来开发,于是捣鼓了半天终于编译成功,感觉还不错.下面以Hello World驱动为例说一下使用Eclipse开发ARM-Li ...

  4. Linux 企业级安全原理和防范技巧

    Linux 企业级安全原理和防范技巧 1. 企业级Linux系统防护概述 1.1 企业级Linux系统安全威胁 1.2 企业级Linux系统安全立体式防范体系 1.2.1 Linux文件系统访问安全 ...

  5. Linux驱动之LCD驱动编写

    在Linux驱动之内核自带的S3C2440的LCD驱动分析这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动.用的LCD屏幕为tft屏,每个像素点为16bit.对 ...

  6. linux驱动篇之 driver_register 过程分析(一)

    linux驱动注册过程分析--driver_register(一) 个人笔记,欢迎转载,请注明出处,共同分享 共同进步 http://blog.csdn.net/richard_liujh/artic ...

  7. Linux 输入子系统原理理解(原创)

    linux    输入子系统原理理解(原创) 以前学了单独的按键设备驱动以及鼠标驱动,实际上,在linux中实现这些设备驱动,有一种更为推荐的方法,就是input输入子系统.平常我们的按键,触摸屏,鼠 ...

  8. Linux驱动:VFIO概述(vfio/iommu/device passthrough)

    <ARM SMMU原理与IOMMU技术("VT-d" DMA.I/O虚拟化.内存虚拟化)> <提升KVM异构虚拟机启动效率:透传(pass-through).DM ...

  9. linux驱动基础开发0——linux 设备驱动概述-转

    目前,Linux软件工程师大致可分为两个层次: (1)Linux应用软件工程师(Application Software Engineer):       主要利用C库函数和Linux API进行应用 ...

最新文章

  1. CSS 高级布局技巧
  2. unity 知道2点计算线段选择角度_影像测量仪实战技巧之角度测量
  3. HashMap源码解释
  4. 基于深度学习的图像修补/完整方法分析
  5. android沿曲线移动,Android动画学习Demo(3) 沿着贝塞尔曲线移动的Property Animation
  6. 全网最快安装JDK17教程(windows版本)
  7. 【matplotlib笔记】柱形图、直方图、散点图、饼图以及叠加图绘制
  8. 拓端tecdat|在python 深度学习Keras中计算神经网络集成模型
  9. 我的华为云售后日常(一)
  10. 微信公众号号开发小记(六)使用开源框架开发
  11. 单例模式【饿汉模式和懒汉模式异同点】
  12. Jmeter接口测试及接口性能测试
  13. Emlog模板fee2.0主题商业版
  14. [7 kyu] Exes and Ohs
  15. android开发隐藏图片,用美图看看安卓版教你如何隐藏私人图片(图文)
  16. STEP 标准基础概念-刘亚龙
  17. 计算机数值中的乘法除法原理
  18. java 根据ip获取mac地址,java服务器端根据ip获取客户端mac地址
  19. Python 医学知识图谱问答系统(一),建立医学知识图谱,基于neo4j知识图谱的医学问答体系
  20. vue+element ui 项目 后台管理系统

热门文章

  1. python线性表顺序存储实现_数据结构——基于C的线性表的顺序存储结构的基本操作的实现...
  2. laravel模板写php代码,Laravel框架之blade模板新手入门教程及小技巧
  3. 047_CSS3多列
  4. sublime python linux 安装教程,Sublime Text Windows及Linux Python环境搭建
  5. bat循环执行带参数_dos命令exit图文教程,结束退出CMD.EXE程序或当前bat批处理脚本...
  6. mysql sycho_Java面试题 - osc_p1rj1z8j的个人空间 - OSCHINA - 中文开源技术交流社区
  7. jq ajax异步上传图片插件,jQuery异步上传文件插件ajaxFileUpload详细介绍
  8. java 滚动条 滚动_广告条随滚动条的移动而移动
  9. java httpinvoker漏洞_Java反序列化漏洞学习
  10. java实现排程算法_康托展开算法和逆康托展开算法[Java实现]