提交 f6ec0278 编写于 作者: 鸿蒙内核源码分析's avatar 鸿蒙内核源码分析

内核日志缓冲区 Dmesg 实现部分代码注释

搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
上级 ae8bbdea
......@@ -45,9 +45,9 @@ STATIC INLINE VOID OsSetCurrCpuSp(UINTPTR regSp)
__asm__ __volatile__("mov sp, %0" :: "r"(regSp));
}
#define OS_SYSTEM_NORMAL 0
#define OS_SYSTEM_EXC_CURR_CPU 1
#define OS_SYSTEM_EXC_OTHER_CPU 2
#define OS_SYSTEM_NORMAL 0 //当前CPU都处于空闲状态
#define OS_SYSTEM_EXC_CURR_CPU 1 //当前CPU处于执行状态
#define OS_SYSTEM_EXC_OTHER_CPU 2 //其他CPU处于执行状态
extern UINT32 OsGetSystemStatus(VOID);
extern VOID BackTraceSub(UINTPTR regFP);
......
......@@ -119,8 +119,8 @@ UINT32 OsGetSystemStatus(VOID)
UINT32 flag;
UINT32 cpuID = g_currHandleExcCpuID;//全局变量 当前执行CPU ID
if (cpuID == INVALID_CPUID) {
flag = OS_SYSTEM_NORMAL;
if (cpuID == INVALID_CPUID) {//当前CPU处于空闲状态的情况
flag = OS_SYSTEM_NORMAL;
} else if (cpuID == ArchCurrCpuid()) {//碰到了正在执行此处代码的CPU core
flag = OS_SYSTEM_EXC_CURR_CPU;//当前CPU
} else {
......
......@@ -76,7 +76,7 @@ STATIC VOID ErrorMsg(VOID)
const CHAR *p = "Output illegal string! vsnprintf_s failed!\n";
UartPuts(p, (UINT32)strlen(p), UART_WITH_LOCK);
}
//串口输出,打印消息的本质就是从串口输出buf
STATIC VOID UartOutput(const CHAR *str, UINT32 len, BOOL isLock)
{
#ifdef LOSCFG_SHELL_DMESG
......@@ -90,7 +90,7 @@ STATIC VOID UartOutput(const CHAR *str, UINT32 len, BOOL isLock)
UartPuts(str, len, isLock);
#endif
}
//输出日志
VOID OutputControl(const CHAR *str, UINT32 len, OutputType type)
{
switch (type) {
......@@ -120,7 +120,7 @@ STATIC VOID OsVprintfFree(CHAR *buf, UINT32 bufLen)
(VOID)LOS_MemFree(m_aucSysMem0, buf);
}
}
//
VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type)
{
INT32 len;
......@@ -163,11 +163,11 @@ VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type)
}
*(bBuf + len) = '\0';
systemStatus = OsGetSystemStatus();
if ((systemStatus == OS_SYSTEM_NORMAL) || (systemStatus == OS_SYSTEM_EXC_OTHER_CPU)) {
OutputControl(bBuf, len, type);
} else if (systemStatus == OS_SYSTEM_EXC_CURR_CPU) {
OutputControl(bBuf, len, EXC_OUTPUT);
systemStatus = OsGetSystemStatus();//获取系统的状态
if ((systemStatus == OS_SYSTEM_NORMAL) || (systemStatus == OS_SYSTEM_EXC_OTHER_CPU)) {//当前CPU空闲或其他CPU运行时
OutputControl(bBuf, len, type);//
} else if (systemStatus == OS_SYSTEM_EXC_CURR_CPU) {//当前CPU正在执行
OutputControl(bBuf, len, EXC_OUTPUT);//串口以无锁的方式输出
}
OsVprintfFree(bBuf, bufLen);
}
......
......@@ -53,19 +53,19 @@ extern VOID LOS_LkPrint(INT32 level, const CHAR *func, INT32 line, const CHAR *f
#define LOS_EMG_LEVEL 0
#define LOS_COMMON_LEVEL (LOS_EMG_LEVEL + 1)
#define LOS_COMMON_LEVEL (LOS_EMG_LEVEL + 1) //日志等级:普通
#define LOS_ERR_LEVEL (LOS_COMMON_LEVEL + 1) //日志等级:错误类
#define LOS_ERR_LEVEL (LOS_COMMON_LEVEL + 1)
#define LOS_WARN_LEVEL (LOS_ERR_LEVEL + 1) //日志等级:警告类
#define LOS_WARN_LEVEL (LOS_ERR_LEVEL + 1)
#define LOS_INFO_LEVEL (LOS_WARN_LEVEL + 1) //日志等级:信息类
#define LOS_INFO_LEVEL (LOS_WARN_LEVEL + 1)
#define LOS_DEBUG_LEVEL (LOS_INFO_LEVEL + 1) //日志等级:调试类
#define LOS_DEBUG_LEVEL (LOS_INFO_LEVEL + 1)
#define LOS_TRACE_LEVEL (LOS_DEBUG_LEVEL + 1) //日志等级:跟踪类
#define LOS_TRACE_LEVEL (LOS_DEBUG_LEVEL + 1)
#define PRINT_LEVEL LOS_ERR_LEVEL
#define PRINT_LEVEL LOS_ERR_LEVEL //默认打印错误类
typedef VOID (*pf_OUTPUT)(const CHAR *fmt, ...);
......@@ -101,11 +101,11 @@ extern void dprintf(const char *fmt, ...);
#define PRINT_RELEASE(fmt, args...) LOS_LkPrint(LOS_COMMON_LEVEL, __FUNCTION__, __LINE__, fmt, ##args)
#define PRINT_TRACE(fmt, args...) LOS_LkPrint(LOS_TRACE_LEVEL, __FUNCTION__, __LINE__, fmt, ##args)
typedef enum {
NO_OUTPUT = 0,
UART_OUTPUT = 1,
CONSOLE_OUTPUT = 2,
EXC_OUTPUT = 3
typedef enum { //输出类型
NO_OUTPUT = 0,
UART_OUTPUT = 1, //串口输出
CONSOLE_OUTPUT = 2, //控制台输出
EXC_OUTPUT = 3 //只输出当前CPU所执行任务的Log
} OutputType;
extern VOID OsVprintf(const CHAR *fmt, va_list ap, OutputType type);
......
......@@ -44,12 +44,12 @@ extern "C" {
/*
* The dmesg buffer is start with this info structure, then the log.
*/
*///dmesg缓冲区从这个信息结构开始,然后是日志内容
typedef struct {
UINT32 logSize; /* The size of log in buffer */
UINT32 logHead; /* The index of the first log data. Data_out_flag */
UINT32 logTail; /* The index where to write, write in and plus one. Data_it_flag */
CHAR *logBuf; /* The log buffer addr */
UINT32 logSize; /* The size of log in buffer */ //日志buf的大小
UINT32 logHead; /* The index of the first log data. Data_out_flag */ // 第一个日志数据的索引
UINT32 logTail; /* The index where to write, write in and plus one. Data_it_flag */ //尾部日志索引位置
CHAR *logBuf; /* The log buffer addr */ //指向缓冲区开始位置
} DmesgInfo;
extern UINT32 OsDmesgInit(VOID);
......
......@@ -70,14 +70,14 @@ extern "C" {
#define BUF_MAX_INDEX (g_logBufSize - 1)
LITE_OS_SEC_BSS STATIC SPIN_LOCK_INIT(g_dmesgSpin);
STATIC DmesgInfo *g_dmesgInfo = NULL;
STATIC UINT32 g_logBufSize = 0;
STATIC VOID *g_mallocAddr = NULL;
STATIC UINT32 g_dmesgLogLevel = 3;
STATIC UINT32 g_consoleLock = 0;
STATIC UINT32 g_uartLock = 0;
LITE_OS_SEC_BSS STATIC SPIN_LOCK_INIT(g_dmesgSpin);//dmesg自旋锁初始化
STATIC DmesgInfo *g_dmesgInfo = NULL; //日志缓冲区描述符
STATIC UINT32 g_logBufSize = 0; //日志buf大小,默认8K
STATIC VOID *g_mallocAddr = NULL; //dmesg buf地址
STATIC UINT32 g_dmesgLogLevel = 3; //默认日志等级 LOS_ERR_LEVEL = 3
STATIC UINT32 g_consoleLock = 0; //控制台锁
STATIC UINT32 g_uartLock = 0; //串口锁
STATIC const CHAR *g_levelString[] = {
"EMG",
"COMMON",
......@@ -107,13 +107,13 @@ STATIC VOID OsUnlockUart(VOID)
g_uartLock = 0;
}
STATIC UINT32 OsCheckError(VOID)
STATIC UINT32 OsCheckError(VOID)//检查缓冲区是否异常
{
if (g_dmesgInfo == NULL) {
return LOS_NOK;
}
if (g_dmesgInfo->logSize > g_logBufSize) {
if (g_dmesgInfo->logSize > g_logBufSize) {//超出缓冲区大小了
return LOS_NOK;
}
......@@ -124,7 +124,7 @@ STATIC UINT32 OsCheckError(VOID)
return LOS_OK;
}
//读取日志缓冲区数据,buf带走数据
STATIC INT32 OsDmesgRead(CHAR *buf, UINT32 len)
{
UINT32 readLen;
......@@ -141,17 +141,17 @@ STATIC INT32 OsDmesgRead(CHAR *buf, UINT32 len)
return 0;
}
readLen = len < logSize ? len : logSize;
readLen = len < logSize ? len : logSize;//最长只能读走g_dmesgInfo->logSize
if (head < tail) { /* Case A */
ret = memcpy_s(buf, len, logBuf + head, readLen);
if (head < tail) { /* Case A */ //不用循环的情况 head 在 tail前
ret = memcpy_s(buf, len, logBuf + head, readLen);//从head的位置一次性直接copy走
if (ret != EOK) {
return -1;
}
g_dmesgInfo->logHead += readLen;
g_dmesgInfo->logSize -= readLen;
} else { /* Case B */
if (readLen <= (g_logBufSize - head)) {
g_dmesgInfo->logHead += readLen;//已占用缓冲区增加
g_dmesgInfo->logSize -= readLen;//可用缓冲区大小减少
} else { /* Case B */
if (readLen <= (g_logBufSize - head)) {
ret = memcpy_s(buf, len, logBuf + head, readLen);
if (ret != EOK) {
return -1;
......@@ -306,22 +306,22 @@ UINT32 OsCheckUartLock(VOID)
{
return g_uartLock;
}
//初始化内核dmesg缓存区,即内核为日志开辟的一个8K缓冲区,dmesg的管理是一个buf的循环管理.
UINT32 OsDmesgInit(VOID)
{
CHAR* buffer = NULL;
buffer = (CHAR *)malloc(KERNEL_LOG_BUF_SIZE + sizeof(DmesgInfo));
buffer = (CHAR *)malloc(KERNEL_LOG_BUF_SIZE + sizeof(DmesgInfo));//注意这里用的是malloc分配,但鸿蒙做了适配调用了LOS_MemAlloc
if (buffer == NULL) {
return LOS_NOK;
}
g_mallocAddr = buffer;
g_dmesgInfo = (DmesgInfo *)buffer;
g_dmesgInfo->logHead = 0;
g_dmesgInfo->logTail = 0;
g_dmesgInfo->logSize = 0;
g_dmesgInfo->logBuf = buffer + sizeof(DmesgInfo);
g_logBufSize = KERNEL_LOG_BUF_SIZE;
g_mallocAddr = buffer;//@note_what 取名g_mallocAddr 用于记录日志缓冲区感觉怪怪的
g_dmesgInfo = (DmesgInfo *)buffer;//整个buf的开头位置用于放置DmesgInfo
g_dmesgInfo->logHead = 0;//头部日志索引位置,注意buf中会存在很多的日志内容,每条独立
g_dmesgInfo->logTail = 0;//尾部日志索引位置
g_dmesgInfo->logSize = 0;//日志占用buf大小
g_dmesgInfo->logBuf = buffer + sizeof(DmesgInfo);//日志内容紧跟在DmesgInfo之后
g_logBufSize = KERNEL_LOG_BUF_SIZE;//buf大小 8K
return LOS_OK;
}
......@@ -722,6 +722,24 @@ dmesg命令用于控制内核dmesg缓存区。
dmesg dmesg [-c/-C/-D/-E/-L/-U]
dmesg -s [size] dmesg -l [level dmesg > [fileA]
参数说明
参数 参数说明 取值范围
-c 打印缓存区内容并清空缓存区。N/A
-C 清空缓存区。N/A
-D/-E 关闭/开启控制台打印。 N/A
-L/-U 关闭/开启串口打印。 N/A
-s size 设置缓存区大小 size是要设置的大小。 N/A
-l level 设置缓存等级。 0 - 5
> fileA 将缓存区内容写入文件。N/A
使用指南
该命令依赖于LOSCFG_SHELL_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg":
Debug ---> Enable a Debug Version ---> Enable Shell ---> Enable Shell dmesg
......@@ -788,7 +806,7 @@ ERR_OUT:
return -1;
}
SHELLCMD_ENTRY(dmesg_shellcmd, CMD_TYPE_STD, "dmesg", XARGS, (CmdCallBackFunc)OsShellCmdDmesg);//采用shell命令静态注册方式
SHELLCMD_ENTRY(dmesg_shellcmd, CMD_TYPE_STD, "dmesg", XARGS, (CmdCallBackFunc)OsShellCmdDmesg);//shell dmesg命令 静态注册方式
#ifdef __cplusplus
#if __cplusplus
......
git add -A
git commit -m 'zzz/pic 上传
git commit -m '内核日志缓冲区 Dmesg 实现部分代码注释
搜索 @note_pic 可以查看全部字符图
搜索 @note_why 是注者尚未看明白的地方,如果您看明白了,请告诉注者完善
搜索 @note_thinking 是注者的思考和吐槽的地方
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册