我的分析是基于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原理的更多相关文章

  1. [转载]Linux Bond的原理及其不足

    本文转自http://www.yunweipai.com/archives/1969.html 支持原创.尊重原创,分享知识! 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做 ...

  2. Linux Bond的原理及其不足

    http://www.tektea.com/archives/1969.html. 在企业及电信Linux服务器环境上,网络配置都会使用Bonding技术做网口硬件层面的冗余,防止单个网口应用的单点故 ...

  3. linux下的X server:linux图形界面原理

    linux下的X server:linux图形界面原理   Moblin Core是在Gnome Mobile的平台上建立.我以前玩Linux,提交的都和图像没有关系,连Xwindows都不用启动,开 ...

  4. Linux Kbuild工作原理分析(以DVSDK生成PowerVR显卡内核模块为例)

    一.引文 前篇博文<Makefile之Linux内核模块的Makefile写法分析>,介绍了Linux编译生成内核驱动模块的Makefile的写法,但最近在DVSDK下使用Linux2.6 ...

  5. [转帖]linux下的X server:linux图形界面原理

    linux下的X server:linux图形界面原理 https://www.cnblogs.com/liangxiaofeng/p/5034912.html linux下的X server:lin ...

  6. Linux 文件删除原理_009

    ***了解Linux文件删除原理先了解一下文件inode索引节点,每个文件在Linux系统里都有唯一的索引节点(身份证号) inode.如果文件存在硬链接,那这个文件和这个文件的硬链接的inode是相 ...

  7. Java网络编程和NIO详解6:Linux epoll实现原理详解

    Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...

  8. 转 Linux内存管理原理

    Linux内存管理原理 在用户态,内核态逻辑地址专指下文说的线性偏移前的地址Linux内核虚拟3.伙伴算法和slab分配器 16个页面RAM因为最大连续内存大小为16个页面 页面最多16个页面,所以1 ...

  9. ARM Linux系统调用的原理

    转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交 ...

随机推荐

  1. crt证书iis 中引用 程序目录提示 System.UnauthorizedAccessException:拒绝访问

    在站点根目录添加 Authenticated Users 权限

  2. R语言的精度和时间效率比较(简单版)

    R语言的最大数值 在R语言里面,所能计算的最大数值可以用下面的方法获得: ###R可计算最大数值 .Machine 在编程的时候注意不要超过这个数值.当然,普通情况下也不可能超过的. R语言的最大精度 ...

  3. jQuery 的自定义事件

    jQuery  中,想要自动触发自定义事件,必须满足2个条件: 1.事件必须是通过on 来绑定的. 2.事件必须是通过trigger / triggerHandler 来触发. 格式如下: $(fun ...

  4. 第十四周翻译-《Pro SQL Server Internals, 2nd edition》

    <Pro SQL Server Internals, 2nd edition> 作者:Dmitri Korotkevitch 翻译:赖慧芳 译文: 设计和优化索引 定义一种应用于所有地方的 ...

  5. 函数QFileSystemModelPrivate::_q_fileSystemChanged

    由于Qt的体系过于庞大,即使是某个模块,分析起来也十分困难.对于QFileSystemModel,我们在这里对单个重要函数慢慢分析 1 /*! \internal The thread has rec ...

  6. Zynq系列程序逻辑固化方法

    1.创建一个BOOT镜像 该小节主要讲述zynq平台利用软件套件SDK创建一个可固化BOOT镜像. 1.1  选择Ad9361_Eque1工程,选择Xilinx Tools → Create Boot ...

  7. c++单链表冒泡排序(交换结点),链表增删改查,运算符重载

    #include <iostream> #include <stdlib.h> #include <time.h> #include <fstream> ...

  8. centos6.5安装Mysql5.6及更改密码

    (一) centos6.5安装Mysql5.6 二进制文件安装的方法分为两种: 第一种是不针对特定平台的通用安装方法,使用的二进制文件是后缀为.tar.gz的压缩文件: 第二种是使用RPM或其他包进行 ...

  9. Python使用requests库,requests.post格式会引发参数不存在问题

    Content-Type: application/json #############↓↓↓成功↓↓↓############# import requests url = 'http://loca ...

  10. python--基本数据 类型

    数据就是我们变量的值:python中变量保存的是内存地址 变量必须先赋值或者声明才能使用!! 1.数值型 整型 int (python3中int就是长整型,与python2中int不同,另外,pyth ...