mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
实现内核日志系统 (#489)
* 实现写日志和读取日志,并且能够在用户态下执行dmesg命令查看日志 * 通过klogctl实现dmesg * 改用ConstGenericRingBuffer作内核缓冲区 * 更改缓冲区容量 * 将能够输出到控制台的日志级别改为日志级别枚举类,使用SpinLock控制KMSG,使用枚举类定义SYSLOG_ACTION,将do_syslog系统调用接口放在syscall.rs * fix warning * 完善do_syslog注释 * 将KMSG接入kinfo、kdebug等 * fix warning * 修复显示的秒数不正确,·以及无法通过CI的问题
This commit is contained in:
1
user/apps/dmesg/.gitignore
vendored
Normal file
1
user/apps/dmesg/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
dmesg
|
17
user/apps/dmesg/Makefile
Normal file
17
user/apps/dmesg/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
ifeq ($(ARCH), x86_64)
|
||||
export PREFIX=x86_64-linux-musl-
|
||||
else ifeq ($(ARCH), riscv64)
|
||||
export PREFIX=riscv64-linux-musl-
|
||||
endif
|
||||
|
||||
|
||||
export CC=$(PREFIX)gcc
|
||||
|
||||
all: dmesg
|
||||
mv dmesg $(DADK_CURRENT_BUILD_DIR)
|
||||
|
||||
dmesg: main.c
|
||||
$(CC) -static -o dmesg main.c dmesg.c
|
||||
|
||||
clean:
|
||||
rm dmesg *.o
|
86
user/apps/dmesg/dmesg.c
Normal file
86
user/apps/dmesg/dmesg.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "dmesg.h"
|
||||
|
||||
/**
|
||||
* @brief 识别dmesg程序的第一个选项参数
|
||||
*
|
||||
* @param arg dmesg命令第一个选项参数
|
||||
* @return int 有效时返回对应选项码,无效时返回 -1
|
||||
*/
|
||||
int getopt(char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
|
||||
return 0;
|
||||
else if (!strcmp(arg, "-c") || !strcmp(arg, "--read-clear"))
|
||||
return 4;
|
||||
else if (!strcmp(arg, "-C") || !strcmp(arg, "--clear"))
|
||||
return 5;
|
||||
else if (!strcmp(arg, "-l") || !strcmp(arg, "--level"))
|
||||
return 8;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 识别dmesg程序的第二个选项参数
|
||||
*
|
||||
* @param arg dmesg命令第一个选项参数
|
||||
* @return int 有效时返回设置的日志级别,无效时返回 -1
|
||||
*/
|
||||
int getlevel(char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "EMERG") || !strcmp(arg, "emerg"))
|
||||
return 0;
|
||||
else if (!strcmp(arg, "ALERT") || !strcmp(arg, "alert"))
|
||||
return 1;
|
||||
else if (!strcmp(arg, "CRIT") || !strcmp(arg, "crit"))
|
||||
return 2;
|
||||
else if (!strcmp(arg, "ERR") || !strcmp(arg, "err"))
|
||||
return 3;
|
||||
else if (!strcmp(arg, "WARN") || !strcmp(arg, "warn"))
|
||||
return 4;
|
||||
else if (!strcmp(arg, "NOTICE") || !strcmp(arg, "notice"))
|
||||
return 5;
|
||||
else if (!strcmp(arg, "INFO") || !strcmp(arg, "info"))
|
||||
return 6;
|
||||
else if (!strcmp(arg, "DEBUG") || !strcmp(arg, "debug"))
|
||||
return 7;
|
||||
else
|
||||
{
|
||||
printf("dmesg: unknown level '%s'\n", arg);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印dmesg手册
|
||||
*/
|
||||
void print_help_msg()
|
||||
{
|
||||
const char *help_msg = "Usage:\n"
|
||||
" dmesg [options]\n\n"
|
||||
"Display or control the kernel ring buffer.\n\n"
|
||||
"Options:\n"
|
||||
" -C, --clear clear the kernel ring buffer\n"
|
||||
" -c, --read-clear read and clear all messages\n"
|
||||
" -l, --level <list> restrict output to defined levels\n"
|
||||
" -h, --help display this help\n\n"
|
||||
"Supported log levels (priorities):\n"
|
||||
" emerg - system is unusable\n"
|
||||
" alert - action must be taken immediately\n"
|
||||
" crit - critical conditions\n"
|
||||
" err - error conditions\n"
|
||||
" warn - warning conditions\n"
|
||||
" notice - normal but significant condition\n"
|
||||
" info - informational\n"
|
||||
" debug - debug-level messages\n";
|
||||
printf("%s\n", help_msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印dmesg错误使用的信息
|
||||
*/
|
||||
void print_bad_usage_msg()
|
||||
{
|
||||
const char *bad_usage_msg = "dmesg: bad usage\nTry 'dmesg --help' for more information.";
|
||||
printf("%s\n", bad_usage_msg);
|
||||
}
|
31
user/apps/dmesg/dmesg.h
Normal file
31
user/apps/dmesg/dmesg.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief 识别dmesg程序的第一个选项参数
|
||||
*
|
||||
* @param arg dmesg命令第一个选项参数
|
||||
* @return int 有效时返回对应选项码,无效时返回 -1
|
||||
*/
|
||||
int getopt(char *arg);
|
||||
|
||||
/**
|
||||
* @brief 识别dmesg程序的第二个选项参数
|
||||
*
|
||||
* @param arg dmesg命令第一个选项参数
|
||||
* @return int 有效时返回设置的日志级别,无效时返回 -1
|
||||
*/
|
||||
int getlevel(char *arg);
|
||||
|
||||
/**
|
||||
* @brief 打印dmesg手册
|
||||
*/
|
||||
void print_help_msg();
|
||||
|
||||
/**
|
||||
* @brief 打印dmesg错误使用的信息
|
||||
*/
|
||||
void print_bad_usage_msg();
|
113
user/apps/dmesg/main.c
Normal file
113
user/apps/dmesg/main.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include "dmesg.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int len = 1;
|
||||
char *buf = NULL;
|
||||
int opt;
|
||||
unsigned int color = 65280;
|
||||
|
||||
// 获取内核缓冲区大小
|
||||
len = klogctl(10, buf, len);
|
||||
|
||||
if (len < 16 * 1024)
|
||||
len = 16 * 1024;
|
||||
if (len > 16 * 1024 * 1024)
|
||||
len = 16 * 1024 * 1024;
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL)
|
||||
{
|
||||
perror("");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
// 无选项参数,默认打印所有日志消息
|
||||
len = klogctl(2, buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 获取第一个选项参数
|
||||
opt = getopt(argv[1]);
|
||||
|
||||
// 无效参数
|
||||
if (opt == -1)
|
||||
{
|
||||
print_bad_usage_msg();
|
||||
return -1;
|
||||
}
|
||||
// 打印帮助手册
|
||||
else if (opt == 0)
|
||||
{
|
||||
print_help_msg();
|
||||
return 0;
|
||||
}
|
||||
// 4 -> 读取内核缓冲区后,清空缓冲区
|
||||
// 5 -> 清空内核缓冲区
|
||||
else if (opt == 4 || opt == 5)
|
||||
{
|
||||
len = klogctl(opt, buf, len);
|
||||
}
|
||||
// 读取特定日志级别的消息
|
||||
else if (opt == 8)
|
||||
{
|
||||
// 无指定日志级别参数,打印错误使用信息
|
||||
if (argc < 3)
|
||||
{
|
||||
print_bad_usage_msg();
|
||||
return -1;
|
||||
}
|
||||
|
||||
int level = -1;
|
||||
|
||||
// 获取日志级别
|
||||
// 这里加1的原因是:如果klogctl的第三个参数是0,不会发生系统调用
|
||||
level = getlevel(argv[2]) + 1;
|
||||
|
||||
if (level == -1)
|
||||
return -1;
|
||||
|
||||
klogctl(8, buf, level);
|
||||
len = klogctl(2, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
// 当前打印内容
|
||||
// 0: 日志级别
|
||||
// 1: 时间戳
|
||||
// 2: 代码行号
|
||||
// 3: 日志消息
|
||||
unsigned int content = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c[2];
|
||||
c[0] = buf[i];
|
||||
c[1] = '\0';
|
||||
syscall(100000, &c[0], color, 0);
|
||||
if (content == 0 && buf[i] == '>')
|
||||
{
|
||||
content++;
|
||||
}
|
||||
else if (content == 1 && buf[i] == ']')
|
||||
{
|
||||
color = 16744448;
|
||||
content++;
|
||||
}
|
||||
else if (content == 2 && buf[i] == ')')
|
||||
{
|
||||
color = 16777215;
|
||||
content++;
|
||||
}
|
||||
else if (content == 3 && buf[i] == '\n')
|
||||
{
|
||||
color = 65280;
|
||||
content = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user