博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
setup_early_printk()函数分析
阅读量:4095 次
发布时间:2019-05-25

本文共 3636 字,大约阅读时间需要 12 分钟。

关于setup_early_printk()函数,主要用来注册用于启动阶段显示的控制台。内核中声明了一个全局变量early_console,并将定义的全局变量early_console_prom赋值给它,随后开始注册early_console_prom所抽象的终端。上述原型如下:

struct console *early_console;static void early_console_write(struct console *con, const char *s, unsigned n){
while (n-- && *s) {
if (*s == '\n') prom_putchar('\r'); prom_putchar(*s); s++; }}static struct console early_console_prom = {
.name = "early", .write = early_console_write, .flags = CON_PRINTBUFFER | CON_BOOT, .index = -1,};void __init setup_early_printk(void){
if (early_console) return; early_console = &early_console_prom; register_console(&early_console_prom);}

关于控制台注册函数的原型如下:

void register_console(struct console *newcon){
int i; unsigned long flags; struct console *bcon = NULL; struct console_cmdline *c; static bool has_preferred; if (console_drivers) //判断是否具有控制台驱动,console_drivers为全局变量,其类型为struct console。 //如果具有控制台驱动,则检测该控制台驱动是否已注册。 //假设当前位于内核启动的最初阶段,因此该变量为空。 for_each_console(bcon) if (WARN(bcon == newcon, "console '%s%d' already registered\n", bcon->name, bcon->index)) return; if (console_driver && newcon->flags & CON_BOOT) {
//如果具有控制台驱动,且所要注册的控制台具有CON_BOOT标识,则检测已有的控制台驱动是否具有CON_BOOT标识,如果没有,则提示所要注册的控制台太迟。 for_each_console(bcon) {
if (!(bcon->flags & CON_BOOT)) {
pr_info("Too late to register bootconsole %s%d\n", newcon->name, newcon->index); return; } } } if (console_drivers && console_drivers->flags & CON_BOOT) //如果具有控制台驱动,且控制台驱动标识为CON_BOOT,则将已存在的控制台赋值给所要注册的控制台。 bcon = console_drivers; if (!has_preferred || bcon || !console_drivers) has_preferred = preferred_console >= 0; if (!has_preferred) {
if (newcon->index < 0) newcon->index = 0; //更改所要注册的中断的索引号。即将-1更正为0。 if (newcon->setup == NULL || newcon->setup(newcon, NULL) == 0) {
//如果所要注册的控制台不存在setup函数,或是setup函数返回为0,则修改其flags标识属性。 newcon->flags |= CON_ENABLED; if (newcon->device) {
//如果该控制台也具有device函数,则执行下面两步操作。 newcon->flags |= CON_CONSDEV; has_preferred = true; } } } //在内核启动阶段,console_cmdline数组为空,因此不进入下述的循环结构体中 for (i = 0, c = console_cmdline; i < MAX_CMDLINECONSOLES && c->name[0]; i++, c++) {
//遍历全局数组console_cmdline数组,该数组类型为struct console_cmdline。 if (!newcon->match || newcon->match(newcon, c->name, c->index, c->options) != 0) {
//如果所要注册的控制台不存在match函数,或是执行返回值不为0。则执行以下代码。 BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name)); //console_cmdline与console结构体中的name变量的长度均为16。 if (strcmp(c->name, newcon->name) != 0) continue; if (newcon->index >= 0 && newcon->index != c->index) continue; if (newcon->index < 0) newcon->index = c->index; if (_braille_register_console(newcon, c)) return; if (newcon->setup && newcon->setup(newcon, c->options) != 0) break; } newcon->flags |= CON_ENABLED; if (i == preferred_console) {
newcon->flags |= CON_CONSDEV; has_preferred = true; } break; } if (!(newcon->flags & CON_ENABLED)) //检查所要注册的控制台是否已使能 return; if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) newcon->flags &= ~CON_PRINTBUFFER; console_lock(); if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
//如果console_drivers链表为空,且所要注册的设备具有CON_CONSDEV标识,则执行以下操作。 newcon->next = console_drivers; console_drivers = newcon; //将所要注册的控制台插入console_drivers链表中 if (newcon->next) newcon->next->flags &= ~CON_CONSDEV; } else {
newcon->next = console_drivers->next; console_drivers->next = newcon; } ... if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) && !keep_bootcon) {
for_each_console(bcon) if (bcon->flags & CON_BOOT) unregister_console(bcon); //卸载已注册的控制台驱动 }}

综上,便是内核中注册控制台驱动的过程。

转载地址:http://upxii.baihongyu.com/

你可能感兴趣的文章
前端设计之特效表单
查看>>
前端设计之CSS布局:上中下三栏自适应高度CSS布局
查看>>
Java的时间操作玩法实例若干
查看>>
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>
计算机网络-网络协议模型
查看>>
计算机网络-OSI各层概述
查看>>
Java--String/StringBuffer/StringBuilder区别
查看>>
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>