kernel/printk.c
/*
* linux/kernel/printk.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* Modified to make sys_syslog() more flexible: added commands to
* return the last 4k of kernel messages, regardless of whether
* they've been read or not. Added option to suppress kernel printk's
* to the console. Added hook for sending the console messages
* elsewhere, in preparation for a serial line console (someday).
* Ted Ts'o, 2/11/93.
*/
#include <stdarg.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#define LOG_BUF_LEN 4096
static char buf[1024];
extern int vsprintf(char * buf, const char * fmt, va_list args);
extern void console_print(const char *);
#define DEFAULT_MESSAGE_LOGLEVEL 7 /* KERN_DEBUG */
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything more serious than KERN_DEBUG */
unsigned long log_size = 0;
struct wait_queue * log_wait = NULL;
int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
static void (*console_print_proc)(const char *) = 0;
static char log_buf[LOG_BUF_LEN];
static unsigned long log_start = 0;
static unsigned long logged_chars = 0;
/*
* Commands to sys_syslog:
*
* 0 -- Close the log. Currently a NOP. 关闭日志,当前不处理
* 1 -- Open the log. Currently a NOP. 打开日中
* 2 -- Read from the log. 从日志中读取
* 3 -- Read up to the last 4k of messages in the ring buffer. 在环形缓冲区中读取最近的4K消息
* 4 -- Read and clear last 4k of messages in the ring buffer 在环形缓冲区中读取并清空最近的4K消息
* 5 -- Clear ring buffer. 清空环形缓冲区
* 6 -- Disable printk's to console 禁制输出消息到控制台
* 7 -- Enable printk's to console 使消息输出到控制台
* 8 -- Set level of messages printed to console 设置消息的级别
*/
//系统日志
asmlinkage int sys_syslog(int type, char * buf, int len)
{
unsigned long i, j, count;
int do_clear = 0;
char c;
int error;
//权限检测
if ((type != 3) && !suser())
return -EPERM;
switch (type) {
case 0: /* Close log */
return 0;
case 1: /* Open log */
return 0;
case 2: /* Read from log */
if (!buf || len < 0)
return -EINVAL;
if (!len)
return 0;
//对指定位置进行写权限验证
error = verify_area(VERIFY_WRITE,buf,len);
if (error)
return error;
cli();
//
while (!log_size) {
if (current->signal & ~current->blocked) {
sti();
return -ERESTARTSYS;
}
interruptible_sleep_on(&log_wait);
}
i = 0;
while (log_size && i < len) {
//计算位置
c = *((char *) log_buf+log_start);
log_start++;
log_size--;
log_start &= LOG_BUF_LEN-1;
//开中断
sti();
//写入缓冲区
put_fs_byte(c,buf);
buf++;
i++;
//关中断
cli();
}
sti();
return i;
case 4: /* Read/clear last kernel messages */
do_clear = 1;
/* FALL THRU */
case 3: /* Read last kernel messages */
if (!buf || len < 0)//校验后读取数据,并清空
return -EINVAL;
if (!len)
return 0;
error = verify_area(VERIFY_WRITE,buf,len);
if (error)
return error;
count = len;
if (count > LOG_BUF_LEN)
count = LOG_BUF_LEN;
if (count > logged_chars)
count = logged_chars;
j = log_start + log_size - count;
for (i = 0; i < count; i++) {
c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
put_fs_byte(c, buf++);
}
if (do_clear)
logged_chars = 0;
return i;
case 5: /* Clear ring buffer */
logged_chars = 0;
return 0;
case 6: /* Disable logging to console */
console_loglevel = 1; /* only panic messages shown */
return 0;
case 7: /* Enable logging to console */
console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
return 0;
case 8:
if (len < 0 || len > 8)
return -EINVAL;
console_loglevel = len;
return 0;
}
return -EINVAL;
}
//输出
asmlinkage int printk(const char *fmt, ...)
{
va_list args;
int i;
char *msg, *p, *buf_end;
static char msg_level = -1;
long flags;
save_flags(flags);
cli();
va_start(args, fmt);
i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
buf_end = buf + 3 + i;
va_end(args);
for (p = buf + 3; p < buf_end; p++) {
msg = p;
//确定日志级别
if (msg_level < 0) {
if (
p[0] != '<' ||
p[1] < '0' ||
p[1] > '7' ||
p[2] != '>'
) {
p -= 3;
p[0] = '<';
p[1] = DEFAULT_MESSAGE_LOGLEVEL - 1 + '0';
p[2] = '>';
} else
msg += 3;
msg_level = p[1] - '0';
}
//循环拷贝日志内容
for (; p < buf_end; p++) {
log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
if (log_size < LOG_BUF_LEN)
log_size++;
else
log_start++;
logged_chars++;
if (*p == '\n')
break;
}
//输出到控制台
if (msg_level < console_loglevel && console_print_proc) {
char tmp = p[1];
p[1] = '\0';
(*console_print_proc)(msg);
p[1] = tmp;
}
if (*p == '\n')
msg_level = -1;
}
restore_flags(flags);
wake_up_interruptible(&log_wait);
return i;
}
/*
* The console driver calls this routine during kernel initialization
* to register the console printing procedure with printk() and to
* print any messages that were printed by the kernel before the
* console driver was initialized.
*/
//注册控制台输出,参数为函数指针
void register_console(void (*proc)(const char *))
{
int i,j;
int p = log_start;
char buf[16];
char msg_level = -1;
char *q;
//挂接回调函数
console_print_proc = proc;
//
for (i=0,j=0; i < log_size; i++) {
buf[j++] = log_buf[p];
p++; p &= LOG_BUF_LEN-1;
if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
continue;
buf[j] = 0;
q = buf;
if (msg_level < 0) {
msg_level = buf[1] - '0';
q = buf + 3;
}
if (msg_level < console_loglevel)
(*proc)(q);
if (buf[j-1] == '\n')
msg_level = -1;
j = 0;
}
}
kernel/printk.c的更多相关文章
- kernel printk信息显示级别
涉及文件:kernel/printk.c include/linux/kernel.h用printk内核会根据日志级别把消息打印到当前控制台上.信息正常输出前提是--日志输出级别(msg_log_le ...
- [kernel]内核日志及printk结构分析
一直都知道内核printk分级机制,但是没有去了解过,前段时间和一个同事聊到开机启动打印太多,只需要设置一下等级即可:另外今天看驱动源码,也看到类似于Printk(KERN_ERR "... ...
- linux内核调试技术之printk
原创博客:欢迎转载,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=6218383 1.简介(基于s3c2440 linux) 在内核调试技术之中 ...
- linux内核打印数据到串口控制台,printk数据不打印问题
linux内核打印数据到串口控制台问题 原文来源:http://i.cnblogs.com/EditPosts.aspx?opt=1 1.查看当前控制台的打印级别 cat /proc/sys/kern ...
- linux驱动中printk的使用注意事项
今天在按键驱动中增加printk(KERN_INFO "gpio_keys_gpio_isr()\n");在驱动加载阶段可以输出调试信息,但驱动加载起来后的信息,在串口端看不到输出 ...
- [linux-内核][转]内核日志及printk结构浅析
这段时间复习了一下内核调试系统,注意看了一下printk的实现以及内核日志的相关知识,这里做一下总结. 1.问题的引出: 做DPDK项目时,调试rte_kni.ko时,发现printk并不会向我们想想 ...
- linux中模块的构建,传参,和printk函数的简单使用
静态编译,动态加载应用想访问内核需要通过系统调用 驱动:1.模块(打包,加入内核)2.内核机制3.操作硬件 在Kconfig里面配置menuconfig的时候,不同的类型会在图形化界面的终端显示不用的 ...
- printk函数日志级别的设置【转】
本文转载自: 下面执行cat /proc/sys/kernel/printk 打印出的四个数字分别代表: 控制台日志级别.默认的消息日志级别.最低的控制台日志级别和默认的控制台日志级别 只有当prin ...
- 更改printk打印级别
1.查看当前控制台的打印级别 cat /proc/sys/kernel/printk 4 4 1 7 其中第一个"4"表示内核打印函数printk的打印级别,只有 ...
随机推荐
- useful tips for win7--close the noise volume(关掉win7开机、系统操作的声音)
how to close the voice of your PC? i) open your computer and then press F2 to enter the BIOS set-u ...
- javascript base64 字符转换
function Base64() { // private property _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr ...
- 【转】Nginx中upstream有以下几种方式:
1.轮询(weight=1) 默认选项,当weight不指定时,各服务器weight相同, 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除.upstream bak ...
- output和returnvalue的作用
贴两段代码. 1> public int ExecuteNonQuery(string pro, MobileOrder or) { SqlParameter ...
- iOS开发(OC)中的命名规范
开小差:最近发现自己有一个经验主义的毛病,不太容易接受新的知识,这对从事技术研发的人来说不太合理,需要改之. 正文:通过读写大量代码我有自己的一套编程思路和习惯,自认为自己的编码习惯还是不错的,代码结 ...
- mstsc连接服务器时如何避免每次在登陆窗口输入密码(rdp passwd decrypted )
http://blog.chinaunix.net/uid-1835840-id-2831518.html 我们经常需要连接很多服务器,或者服务器的ip经常变动.把连接的密码保存在rdp配置文件里,用 ...
- 自定义 Material Design风格的提示框
关闭 自定义 Material Design风格的提示框 2016-04-24 10:55 152人阅读 评论(0) 收藏 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. 其实在14年谷歌 ...
- CMD和AMD区别的概括
CMD和AMD区别 AMD CMD 关于依赖的模块 提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)), 延迟执行 关于依赖的位置 依赖前置 ...
- Javascript轮播 支持平滑和渐隐两种效果(可以只有两张图)
先上两种轮播效果:渐隐和移动 效果一:渐隐 1 2 3 4 效果二:移动 1 2 3 4 接下来,我们来大致说下整个轮播的思路: 一.先来看简单的,移动的,先上来一个图----移动效果图: 说明: ...
- Java优化
Java初级优化 1. 对于明确不需要派生的类,添加final修饰符,此时该类的所有方法都是final的.Java编译器会寻找机会内联(inline)所有的final方法.(能使性能提升50%)2. ...