no_console_suspend
转自 https://blog.csdn.net/tiantao2012/article/details/52330621
通过uboot 可以传递给kernel一个no_console_suspend的参数。
这个参数的意思是,在suspend的时候console 不进行suspend,否则console suspend之后其他driver在suspend 过程中印的log都显示不出来,因此加这个参数一般用于调试suspend 和 resume。
我们看看是如何kernel是如何是实现的.
http://lxr.free-electrons.com/source/kernel/printk/printk.c
2009 bool console_suspend_enabled = true;
2010 EXPORT_SYMBOL(console_suspend_enabled);
2011
2012 static int __init console_suspend_disable(char *str)
2013 {
2014 console_suspend_enabled = false;
2015 return 1;
2016 }
2017 __setup("no_console_suspend", console_suspend_disable);
kernel 用console_suspend_disable 来接收no_console_suspend,可见如果uboot 传递这个参数,则console_suspend_enabled = false
kernel 在suspend 过程会调用suspend_console 来suspend console,可见如果console_suspend_enabled=false的话,这个函数在2031行就返回了,console 就不进行suspend 过程了,这样其他driver就可以继续使用printk来打印log
2028 void suspend_console(void)
2029 {
2030 if (!console_suspend_enabled)
2031 return;
2032 printk("Suspending console(s) (use no_console_suspend to debug)
");
2033 console_lock();
2034 console_suspended = 1;
2035 up_console_sem();
2036 }
我们现在看看suspend_console 是如何阻止log显示的,
我们先看看prink的callstack
printk->vprintk_emit->console_trylock
2100 int console_trylock(void)
2101 {
2102 if (down_trylock_console_sem())
2103 return 0;
2104 if (console_suspended) {
2105 up_console_sem();
2106 return 0;
2107 }
2108 console_locked = 1;
2120 console_may_schedule = !oops_in_progress &&
2121 preemptible() &&
2122 !rcu_preempt_depth();
2123 return 1;
2124 }
继续调用down_trylock_console_sem
110 static int __down_trylock_console_sem(unsigned long ip)
111 {
112 if (down_trylock(&console_sem))
113 return 1;
114 mutex_acquire(&console_lock_dep_map, 0, 1, ip);
115 return 0;
116 }
这个函数回去获取console_sem 锁,但是由于我们已经在suspend_console 的时候调用down_console_sem 已经获取了这个锁,一次这里肯定是返回0的,所以不会调用
2080 void console_lock(void)
2081 {
2082 might_sleep();
2083
2084 down_console_sem();
2085 if (console_suspended)
2086 return;
2087 console_locked = 1;
2088 console_may_schedule = 1;
2089 }
down_console_sem 实现如下:
105 #define down_console_sem() do {
106 down(&console_sem);
107 mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
108 } while (0)
所有由于 vprintk_emit 中的console_trylock() 返回0,所以不会调用 console_unlock()来印log
正常情况下 vprintk_emit 中的console_trylock() 返回1,所以会调用 console_unlock()来印log
我们看看console_unlock的实现
2203 void console_unlock(void)
2204 {
call_console_drivers
2340 }
调用call_console_drivers
1434 static void call_console_drivers(int level,
1435 const char *ext_text, size_t ext_len,
1436 const char *text, size_t len)
1437 {
1438 struct console *con;
1439
1440 trace_console(text, len);
1441
1442 if (level >= console_loglevel && !ignore_loglevel)
1443 return;
1444 if (!console_drivers)
1445 return;
1446
1447 for_each_console(con) {
1448 if (exclusive_console && con != exclusive_console)
1449 continue;
1450 if (!(con->flags & CON_ENABLED))
1451 continue;
1452 if (!con->write)
1453 continue;
1454 if (!cpu_online(smp_processor_id()) &&
1455 !(con->flags & CON_ANYTIME))
1456 continue;
1457 if (con->flags & CON_EXTENDED)
1458 con->write(con, ext_text, ext_len);
1459 else
1460 con->write(con, text, len);
1461 }
1462 }
最终通过con->write将log显示到控制台上
- 上一篇:python操作mycat只操作主库
- 下一篇:励志前行,加速BCH创新落地