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的打印级别,只有 ...
随机推荐
- gradle环境配置、
话不多说,直接上流程. 1.下载 gradle.zip文件,我以为已经为大家准备好了各个版本的下载地址. 链接: http://pan.baidu.com/s/1hqjIVlE 密码: 8ccb 本人 ...
- iOS 8 以后 MKMapView 代理不执行问题
因为ios8上,如果你使用了mapView,必须设置mapView的大小,必须把它添加显示在视图上. 可以将frame设为(0,0,0.1,0.1)
- JQuery基础总结下
JQuery动画与特效 show()和hide()方法可以用来显示和隐藏元素,toggle()方法用来切换显示和隐藏. $(selector).hide(speed,[callback]); $(se ...
- A Brief Review of Supervised Learning
There are a number of algorithms that are typically used for system identification, adaptive control ...
- H5的FormData对象完成ajax上传文件multiFile
最近工作中需要完成,ajax上传图片,可是input file +ajax是无法完成的: 于是寻找了许久,发现了H5 的一个对象FormData 使用方法如下: HTML: <form id=& ...
- php 序列化、json
序列化 和 反序列化1. serialize和unserialize函数 2. json_encode 和 json_decode 使用JSON格式序列化和反序列化3. var_export 和 ev ...
- jsp九大内置对象和四大作用域
看到网上一些Jsp内置对象介绍的都不是很全,今天我把各位大神的整理了一下. JSP九大对象:内置对象(又叫隐含对象,有9个内置对象):不需要预先声明就可以在脚本代码和表达式中随意使用. 一.reque ...
- Json 讲解
JSON详解 阅读目录 JSON的两种结构 认识JSON字符串 在JS中如何使用JSON 在.NET中如何使用JSON 总结 JSON的全称是”JavaScript Object Notation”, ...
- 2016 - 3 - 12 SQLite的学习之SQL语言入门
1.SQL语句的特点: 1.1 不区分大小写 1.2 每条语句以;结尾 2.SQL语句中常用关键字: select,insert,update,from,create,where,desc,order ...
- WKWebView
按错了...,原帖地址http://blog.csdn.net/cyforce/article/details/37657009 webkit使用WKWebView来代替IOS的UIWebView和O ...