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的打印级别,只有 ...
随机推荐
- 7个步骤:让JavaScript变得更好
Dan Odell介绍了他编写的七步写出无瑕代码的计划,是在简化过程中最有用的工具. 随着浏览器性能提高,伴随着新的HTML5的编程接口的稳步采用,网页上的JavaScript的音量在逐渐增加.然 ...
- Microsoft Azure Project Oxford 体验
2015年4月29日,微软在Build 2015大会上发布了一个震撼人心的项目: Project Oxford, 可以帮助直接实现图像理解.人脸识别.语音识别.语音合成等功能.虽然说这是号称研究院的项 ...
- While循环
package ForType; public class ForType { /** * @param args */ public static void main(String[] args) ...
- MFC-01-Chapter01:Hello,MFC---1.3 第一个MFC程序(01)
#include <afxwin.h> class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; cl ...
- 对于.NET Socket连接的细节记录
如果客户端直接连接一个不存在的服务器端,客户端会抛出异常: 如果在连接过程中,客户端强制关闭了连接(没有调用Close直接关闭了程序),服务器端会抛出异常: 如果在连接过程中,客户端调用了Close, ...
- asp.net文件下载文件另存为
这是一个困惑已久的问题…… 首先,用<a>标签的href打开浏览器能解读的文件(如txt,jpg,pdf等),会自动打开,无法做到弹出另存为的效果. 其次,网上搜索了各种JS解决办法,包括 ...
- Java泛型中的? super T语法
? super T 语法将泛型类限制为所有T的超类(包括T自身),但只能用于参数中,不可以在返回值用加以限定.如果不加以限定,假设某个函数头为? super Manager get()由于编译器不知道 ...
- SQL获取汉字首字母
)) ) as begin ) ) collate Chinese_PRC_CI_AS,letter )) insert into @t(chr,letter) select '吖','A' unio ...
- 转:js中this、call、apply的用法
(一)关于this首先关于this我想说一句话,这句话记住了this的用法你也就差不多都能明白了:this指的是当前函数的对象.这句话可能比较绕,我会举出很多例子和这句话呼应的!(看下文)1.首先看下 ...
- [转]PYTHON-SCRAPY-WINDOWS下的安装笔记
分类: Crawler.Net Python2014-05-15 13:36 127人阅读 评论(0) 收藏 举报 PYTHON SCRAPY 1.安装PYTHON2.7.6,下载地址:https:/ ...