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先处理,优点他们在内核启动阶段运行,都在设备驱动前预先运行。上定义代码,
- #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?utm_source=copy
linux驱动——cmdline原理及利用【转】的更多相关文章
- linux驱动程序设计的硬件基础,王明学learn
linux驱动程序设计的硬件基础(一) 本章讲总结学习linux设备程序设计的硬件基础. 一.处理器 1.1通用处理器 通用处理器(GPP)并不针对特定的应用领域进行体系结构和指令集的优化,它们具有一 ...
- Linux驱动学习步骤(转载)
1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ls ...
- Linux驱动开发学习的一些必要步骤
1. 学会写简单的makefile 2. 编一应用程序,可以用makefile跑起来 3. 学会写驱动的makefile 4. 写一简单char驱动,makefile编译通过,可以insmod, ...
- linux驱动面试题2
1.什么是GPIO? general purpose input/output GPIO是相对于芯片本身而言的,如某个管脚是芯片的GPIO脚,则该脚可作为输入或输出高或低电平使用,当然某个脚具有复用的 ...
- Linux驱动之触摸屏程序编写
本篇博客分以下几部分讲解 1.介绍电阻式触摸屏的原理 2.介绍触摸屏驱动的框架(输入子系统) 3.介绍程序用到的结构体 4.介绍程序用到的函数 5.编写程序 6.测试程序 1.介绍电阻式触摸屏的原理 ...
- Linux驱动之LCD驱动编写
在Linux驱动之内核自带的S3C2440的LCD驱动分析这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动.用的LCD屏幕为tft屏,每个像素点为16bit.对 ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
- linux驱动工程面试必问知识点
linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...
- linux驱动面试题整理
1.字符型驱动设备你是怎么创建设备文件的,就是/dev/下面的设备文件,供上层应用程序打开使用的文件? 答:mknod命令结合设备的主设备号和次设备号,可创建一个设备文件. 评:这只是其中一种方式,也 ...
随机推荐
- 牛客国庆训练 H.千万别用树套树
链接https://ac.nowcoder.com/acm/contest/1108/H 国庆队内训练的题,当时还完全没思路,就没补.现在会树状数组了,倒是能想一想,不过网上题解好多用线段树传数组的? ...
- 前端小白webpack学习(四)
.less文件与.scss文件使用与.css文件相仿 less-loader使用需要借助less插件,终端输入npm i less less-loader -D安装; sass-loader使用需要借 ...
- 05-深入python的set和dict
一.深入python的set和dict 1.1.dict的abc继承关系 from collections.abc import Mapping,MutableMapping #dict属于mappi ...
- RabbitMQ 备份交换机(alternate-exchange)介绍
RabbitMQ之备份交换机(alternate-exchange) 1.备份交换器,AlternateExchange(AE) 备份交换器是为了实现没有路由到队列的消息,声明交换机的时候添加属性al ...
- JQuery之Ajax基础
众所周知JQuery中的Ajax主要用于数据传输,其数据传输格式为JSON格式数据,比XML格式数据传输更快. ajax 是 Asynchronous JavaScript and XML的简写,aj ...
- Spring Cloud系列:不重启eureka,清除down掉的服务
场景描述 做项目的时候,我的服务改了个ip,然后重新启动后,原ip的服务down掉了,但是没有清楚掉,还在上面,导致我用swagger测试的时候,访问不到真正up的程序.重启eureka又不划算,于是 ...
- reports buileder 触发器的写法
触发器写法: function CF_SHOULD_BACK_TIMEFormula return Number is--其他:取MES工时按工段分别统计产量.投入工时合计:应回报工时=移动数量*[∑ ...
- Windows系统Git安装教程(详解Git安装过程)
Windows系统Git安装教程(详解Git安装过程) 今天更换电脑系统,需要重新安装Git,正好做个记录,希望对第一次使用的博友能有所帮助! 获取Git安装程序 到Git官网下载,网站地址: ...
- C# SendAysnc 超时
业务方法 @@@code public override async Task<List<(IPEndPoint endPoint, byte[] data)>> Send ...
- find 常用命令
系统中总会不断产生一些文件,比如日志文件,不一定会用到也不会自动删除,这时候就需要手动删除,当然也可以转存到其他目录下.不好找的时候可以用find模糊查找,加个job定时任务自动执行定期删除文件1.添 ...