Linux之prink原理
我的分析是基于Linux4.15.1
1.看看kernel是如何调用到console初始化函数的:
分两条线:
a.start_kernel --> console_init --> call = __con_initcall_start
去调用放在__con_initcall_start和__con_initcall_end之间的所有函数,看看这个区间的有哪些函数.
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
b.start_kernel --> rest_init --> kernel_init --> kernel_init_freeable --> do_basic_setup --> do_initcalls .
do_initcalls()将按顺序从由__initcall_start开始,到__initcall_end结束的section中以函数指针的形式取出这些编译到内核的驱动模块中初始化函数起始地址,来依次完成相应的初始化.
2.看看跟单板芯片相关的函数是如何放到__initcall这个section的。
在drivers/tty/serial/samsung.c里面有如下定义:console_initcall(s3c24xx_serial_console_init);,去include/linux/init.h里面查看console_initcall的定义:
#define console_initcall(fn) \
static initcall_t __initcall_##fn \
__used __section(.con_initcall.init) = fn
因此在执行console_init的时候,s3c24xx_serial_console_init也会被调用,进而执行register_console(&s3c24xx_serial_console);,结构体s3c24xx_serial_console的定义如下,
static struct console s3c24xx_serial_console = {
.name = S3C24XX_SERIAL_NAME,
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -,
.write = s3c24xx_serial_console_write,
.setup = s3c24xx_serial_console_setup,
.data = &s3c24xx_uart_drv,
};
相当于将此结构体注册进内核,注意这里的名称:#define S3C24XX_SERIAL_NAME "ttySAC",是不是很眼熟,没错,这个就是我们在bootargs里面设置的console的名称。
这里也有一个write函数,就是通过这个函数将打印信息送到串口上的。
在register_console的时候,还会调用每个console的setup函数,对应于s3c2440的话,就是s3c24xx_serial_console_setup函数了。
if (!has_preferred) {
if (newcon->index < )
newcon->index = ;
if (newcon->setup == NULL ||
newcon->setup(newcon, NULL) == 0) {
newcon->flags |= CON_ENABLED;
if (newcon->device) {
newcon->flags |= CON_CONSDEV;
has_preferred = true;
}
}
}
console就这样注册进内核了,如果细看注册过程,其实是将此console的信息记录到static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];这个数组里面了,也由此可知内核最多允许8个console。
3.再看看我们传进去的console是如何跟上面注册的相关联起来的。
上面的代码是内核自动会运行的,所以可以看出,内核在初始化的时候注册了一个名为ttySAC*的console,里面还有write的函数直接操作串口,一般这个console就是ttySAC0了,这就是为什么我们在uboot里面传参数的时候console=ttySAC0的原因,就是为了跟内核里面注册的console名称匹配,每一款芯片可能这个名字都不一样,要自己看源码。
接下来就看我们传进去的console=ttySAC0是如何跟内核自动注册的console关联起来的。
在内核里面搜索"console="看看哪里解析了我们传进来的参数:
可以搜到在kernel/printk/printk.c里面有如下定义:
__setup("console=", console_setup);
当uboot通过"console="传入参数时,内核里面是用__setup宏申明的方法来处理的,前提是要名称匹配,也就是说,内核是通过调用console_setup来处理uboot传入的“console=”这个命令行的,也就是在console_cmdline[MAX_CMDLINECONSOLES]这个数组里面查看是否有相同的名称的console:
for (i = , c = console_cmdline;
i < MAX_CMDLINECONSOLES && c->name[];
i++, c++) {
if (strcmp(c->name, name) == && c->index == idx) {
if (!brl_options)
preferred_console = i;
return ;
}
}
如果找到名称匹配的,则将其记录在preferred_console这个变量里,关于console_setup这个函数的分析,网上很多,我这里就不细讲了。
这样用户指定的console就用起来了。
梳理一遍:
用户指定console --> 在内核注册的console里面有这个设备 --> 于是通过名字建立了关系。
Linux之prink原理的更多相关文章
- [转载]Linux Bond的原理及其不足
本文转自http://www.yunweipai.com/archives/1969.html 支持原创.尊重原创,分享知识! 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做 ...
- Linux Bond的原理及其不足
http://www.tektea.com/archives/1969.html. 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做网口硬件层面的冗余,防止单个网口应用的单点故 ...
- linux下的X server:linux图形界面原理
linux下的X server:linux图形界面原理 Moblin Core是在Gnome Mobile的平台上建立.我以前玩Linux,提交的都和图像没有关系,连Xwindows都不用启动,开 ...
- Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)
一.引文 前篇博文<Makefile之Linux内核模块的Makefile写法分析>,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6 ...
- [转帖]linux下的X server:linux图形界面原理
linux下的X server:linux图形界面原理 https://www.cnblogs.com/liangxiaofeng/p/5034912.html linux下的X server:lin ...
- Linux 文件删除原理_009
***了解Linux文件删除原理先了解一下文件inode索引节点,每个文件在Linux系统里都有唯一的索引节点(身份证号) inode.如果文件存在硬链接,那这个文件和这个文件的硬链接的inode是相 ...
- Java网络编程和NIO详解6:Linux epoll实现原理详解
Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...
- 转 Linux内存管理原理
Linux内存管理原理 在用户态,内核态逻辑地址专指下文说的线性偏移前的地址Linux内核虚拟3.伙伴算法和slab分配器 16个页面RAM因为最大连续内存大小为16个页面 页面最多16个页面,所以1 ...
- ARM Linux系统调用的原理
转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交 ...
随机推荐
- 浅析android系统设计中的回调思想
一.为何写作本文 在慢慢深入接触android开发的过程中,我越来越发现android中(至少应用曾的开发)用到了很多回调的思想.比如activity的生命周期,fragment的生命周期,皆是回调 ...
- Python with open as函数
可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件. 当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入. 只有调用close ...
- 使用junit和eclemma进行简单的代码测试
1.Junit和Hamcrest的安装 可以在https://mvnrepository.com/上面下载所需要的Junit和Hamcrest的jar包,然后在项目中新建一个lib文件夹,将下载好的j ...
- oracle插入数据的时候报错:ORA-00928: 缺失 SELECT 关键字
比如:插入数据的时候是这样的insert into a value('哈哈'); 报的是这样的错误:ORA-00928: 缺失 SELECT 关键字 其实就是value少了一个s,在oracle中,插 ...
- Js函数基本介绍
1. 函数的创建 在JavaScript里面创建函数的关键字为function 函数名:就是在我们调用函数的时候需要书写的标识符 形参:全称为形式参数,调用函数的时候,这个函数所需要的参数是什么 实参 ...
- 实现对HashMap的value排序
问题:如何对HashMap中的value值进行排序 关键点:1.取HashMap的Map.Entry,放入List2.利用Collections.sort(List, Comparator<? ...
- js显示表单的提交验证
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 阶段02JavaWeb基础day02&03JavaScript
javascript知识体系 ECMAScript javascript与html结合方式 内部: <script type="text/javaScript">*** ...
- JS-斜杠和反斜杠的转换
例子:var url = "http://localhost:64177/Home/AccordionIndex"; 将斜杠转换成反斜杠: url = url .replace(& ...
- Selenium常用API详解介绍
转至元数据结尾 由 黄从建创建, 最后修改于一月 21, 2019 转至元数据起始 一.selenium元素定位 1.selenium定位方法 2.定位方法的用法 二.控制浏览器操作 1.控制 ...