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的打印级别,只有 ...
随机推荐
- keep the bar green to keep the code clean——Junit详解(二)
测试用例&测试套件 举个栗子: 编写MyStack类模拟栈,并对其进行测试用例编写测试: 编写文件删除方法,并对其删除测试. 不再做演示,戳此获取代码 MyStack类: public cla ...
- CVPR历年Best Papers
作者:我爱机器学习原文链接:CVPR历年Best Papers CVPR (Computer Vision)(2000-2016) 年份 标题 一作 一作单位 2016 Deep Residual L ...
- PHP初步(上)
一.php语法 PHP是一种嵌入式脚本语言,所以,我们需要标记出哪些是PHP代码,哪些是html代码.当html和php代码进行混编的时候,文件必须要以php结尾(否则Apache不会将这个文件交给p ...
- sql返回两个日期之间的日期_函数实现
-- Description:返回两段日期之间的所有日期 <Description,,>-- ============================================ ...
- Action的搜索顺序(Struts2搜索Action的机制)
当访问如下链接时, http://localhost:8080/struts2Demo/path1/path2/path3/LoginAction.action 第一步:判断当前路径下action是否 ...
- Dynamic Programming
We began our study of algorithmic techniques with greedy algorithms, which in some sense form the mo ...
- iOS 自动化打包
理想的情况:不打开工程的情况下,直接双击就能打包出一个IPA文件,这样就可以让测试直接使用 itools 进行安装. 分如下两种情况: 1)不依赖cocoapod 管理项目的自动化. 如果没有一个简 ...
- css3弹性盒子温习
弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成. 弹性容器通过设置 display 属性的值为 flex 或 inline-flex将其定义为弹性容器. 弹性 ...
- 好文mark
用oracle的dblink连接mysql. http://f.dataguru.cn/thread-267150-1-1.html hadoop的机架感知: 本地化策略,以及备份都要知道哪个节点在哪 ...
- iOS 服务器回空数据的处理
后端返回一个数组类型的数据,但是数据里面包含"<null>","(null)"等,本地缓存写入数据失败,write to File: 方法限制, 可 ...