Linux内核之 printk 打印

2023-05-16

Linux内核之 printk 打印

  • 前言
  • 一、printk 介绍
    • 1. printk 消息级别
    • 2.内核 printk 文件
  • 二、调整打印级别
    • 1.在 menuconfig 中修改
    • 2.在系统中修改(常用)
  • 三、使用示例
  • 四、查看打印
    • 1.dmesg
    • 2./proc/kmsg
  • 五、其他常见的用法
    • 1.pr_xx 用法
    • 2.dev_xxx 用法
    • 3.动态打印调试方法


前言

printk 在内核源码中用来记录日志信息的函数,只能在内核源码范围内使用,用法类似于 printf 函数。

printk 函数主要做两件事情:

1、将信息记录到 log 中;
2、调用控制台驱动来将信息输出。


一、printk 介绍

printk 将内核信息输出到内核信息缓冲区中,内核缓冲区在 kernel/printk/printk.c 中定义:

static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);

1. printk 消息级别

Linux 内核共提供了八种不同的消息级别,分为级别 0~7。数值越大,表示级别越低,对应的消息越不重要。相应的宏定义在 include/linux/kern_levels.h 文件中。

#define KERN_SOH   "\001"      /* ASCII Start Of Header */
#define KERN_SOH_ASCII '\001'

#define KERN_EMERG      KERN_SOH "0"   /* system is unusable */
#define KERN_ALERT      KERN_SOH "1"   /* action must be taken immediately */
#define KERN_CRIT       KERN_SOH "2"   /* critical conditions */
#define KERN_ERR        KERN_SOH "3"   /* error conditions */
#define KERN_WARNING    KERN_SOH "4"   /* warning conditions */
#define KERN_NOTICE     KERN_SOH "5"   /* normal but significant condition */
#define KERN_INFO       KERN_SOH "6"   /* informational */
#define KERN_DEBUG      KERN_SOH "7"   /* debug-level messages */

说明:

  • KERN_EMERG 表示紧急事件,一般是系统崩溃之前提示的消息;
  • KERN_ALERT 表示必须立即采取行动的消息;
  • KERN_CRIT 表示临界状态,通常涉及严重的硬件或软件操作失败;
  • KERN_ERR 用于报告错误状态,设备驱动程序会经常使用该级别来报告来自硬件的问题;
  • KERN_WARNING 对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重的问题;
  • KERN_NOTICE 表示有必要进行提示的正常情形,许多与安全相关的状况用这个级别进行汇报;
  • KERN_INFO 表示内核提示信息,很多驱动程序在启动的时候,用这个级别打印出它们找到的硬件信息;
  • KERN_DEBUG 用于调试信息。

2.内核 printk 文件

通过 /proc/sys/kernel/printk 文件可以调节 printk 的输出等级,该文件有 4 个数字值。例如,在 Ubuntu 上的值如下:

$ cat /proc/sys/kernel/printk
4       4       1       7

四个数值的含义如下:
控制台日志级别:优先级高于该值的消息将被打印至控制台;
默认的消息日志级别:将用该优先级来打印没有优先级的消息(即 printk 没有指定消息级别);
最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级);
默认的控制台日志级别:控制台日志级别的缺省值。

这四个值是在 kernel/printk/printk.c 中被定义的,如下:

int console_printk[4] = {
        CONSOLE_LOGLEVEL_DEFAULT,       /* console_loglevel */
        MESSAGE_LOGLEVEL_DEFAULT,       /* default_message_loglevel */
        CONSOLE_LOGLEVEL_MIN,           /* minimum_console_loglevel */
        CONSOLE_LOGLEVEL_DEFAULT,       /* default_console_loglevel */
};
EXPORT_SYMBOL_GPL(console_printk);

二、调整打印级别

调整 printk 打印级别可以使得在印 Log 时控制输出 Log 的信息量以及控制自己想要输出的信息级别,下面则介绍调整 printk 打印级别的几种方法:

1.在 menuconfig 中修改

修改 CONFIG_MESSAGE_LOGLEVEL_DEFAULT 的值,然后重新编译,更新内核。menuconfig 配置路径如下:

Kernel hacking  --->
    printk and dmesg options  --->
        (4) Default message log level (1-7)

2.在系统中修改(常用)

在系统运行期间,可以通过修改 /proc/sys/kernel/printk 中的值来改变内核打印效果。例如,屏蔽掉所有的内核 printk 打印,只需要把第一个数值调到最小值1或者0,此时可以敲如下 cmd:

echo 1       4       1      7 > /proc/sys/kernel/printk

echo 1 > /proc/sys/kernel/printk # 表示只修改第一个值

三、使用示例

在使用 printk 时我们会将消息级别放到最开始的位置,例如:

printk(KERN_EMERG   "GetIot: KERN_EMERG\n");
printk(KERN_ALERT   "GetIot: KERN_ALERT\n");
printk(KERN_CRIT    "GetIot: KERN_CRIT\n");
printk(KERN_ERR     "GetIot: KERN_ERR\n");
printk(KERN_WARNING "GetIot: KERN_WARNING\n");
printk(KERN_NOTICE  "GetIot: KERN_NOTICE\n");
printk(KERN_INFO    "GetIot: KERN_INFO\n");
printk(KERN_DEBUG   "GetIot: KERN_DEBUG\n");

如果没有设置消息的日志级别,默认使用 default_message_loglevel 级别(该值可由上述两种方式修改,即第二个数值)。

当 printk 中的消息日志级别小于当前控制台的日志级别(console_printk[0])时,printk 的信息就会在控制台上显示。但无论当前控制台日志级别是何值,即使没有在控制台打印出来,都可以通过下面两种方法查看日志:

  • 第一种是使用 dmesg 命令打印;
  • 第二种是通过 cat /proc/kmsg 来打印。

另外如果配置好并运行了 syslogd 或 klogd,没有在控制台上显示的 printk 的信息也会追加到 /var/log/messages.log 中。

四、查看打印

将上述示例代码添加到 最简单的内核模块 的 hello_init 函数中,编译并执行 insmod hello.ko 安装模块。

1.dmesg

执行 dmesg | tail 将会看到如下打印:

[20120.194934] module init success
[20120.194935] GetIot: KERN_EMERG
[20120.194937] GetIot: KERN_ALERT
[20120.194938] GetIot: KERN_CRIT
[20120.194939] GetIot: KERN_ERR
[20120.194940] GetIot: KERN_WARNING
[20120.194940] GetIot: KERN_NOTICE
[20120.194940] GetIot: KERN_INFO
[20120.194941] GetIot: KERN_DEBUG

2./proc/kmsg

也可以执行 cat /proc/kmsg 等待内核打印:

$ sudo cat /proc/kmsg 
<6>[20120.194934] module init success
<0>[20120.194935] GetIot: KERN_EMERG
<1>[20120.194937] GetIot: KERN_ALERT
<2>[20120.194938] GetIot: KERN_CRIT
<3>[20120.194939] GetIot: KERN_ERR
<4>[20120.194940] GetIot: KERN_WARNING
<5>[20120.194940] GetIot: KERN_NOTICE
<6>[20120.194940] GetIot: KERN_INFO
<7>[20120.194941] GetIot: KERN_DEBUG

五、其他常见的用法

1.pr_xx 用法

在 Linux 内核中除了直接使用 printk 加消息级别的方式,在 <linux/printk.h> 中还定义了 pr_notice、pr_info、pr_warn、pr_err 等接口。使用这些 pr_xxx 接口,就可以省去指定消息级别的麻烦。

#define pr_emerg(fmt, ...)     printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...)     printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...)      printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...)       printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...)   printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warn pr_warning
#define pr_notice(fmt, ...)    printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...)      printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)

#ifdef DEBUG
#define pr_devel(fmt, ...) \
	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_devel(fmt, ...) \
	no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif
#if defined(CONFIG_DYNAMIC_DEBUG)
#define pr_debug(fmt, ...)			\
	dynamic_pr_debug(fmt, ##__VA_ARGS__)
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
	printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
	no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

如上各 pr_xx 定义,都是对 printk + 级别的封装,故都能和 prink 一样在 Linux 内核中直接使用,但是对于 pr_devel() 需要在定义了 DEBUG 宏,pr_debug() 需要在定义了 DEBUGCONFIG_DYNAMIC_DEBUG 宏才有实意。

2.dev_xxx 用法

对于 Linux 驱动程序,在 <linux/dev_printk.h> 里也提供了一些驱动模型诊断宏,例如 dev_errdev_warndev_info 等等。使用它们,不仅可以按标记的消息级别打印,还会打印对应的设备和驱动信息,这对于驱动调试来说相当重要。

#define dev_emerg(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_emerg, KERN_EMERG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_crit, KERN_CRIT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_alert, KERN_ALERT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_warn, KERN_WARNING, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_notice, KERN_NOTICE, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)

#if defined(CONFIG_DYNAMIC_DEBUG) || \
	(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
#define dev_dbg(dev, fmt, ...)						\
	dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#elif defined(DEBUG)
#define dev_dbg(dev, fmt, ...)						\
	dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#else
#define dev_dbg(dev, fmt, ...)						\
({									\
	if (0)								\
		dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
})
#endif

如上 dev_xx 定义,其和 pr_xx 类似,都可以直接理解为 printk + 级别的封装,一般在 Linux 驱动程序中使用,同样需要注意,dev_dbg() 也不是无条件打印的,除非定义了 DEBUG 或设定了 CONFIG_DYNAMIC_DEBUG。一个相关约定是在已经开启了 DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。

补充:
menuconfig 中开启动态调试:

Kernel hacking  --->
    printk and dmesg options  --->
        [*] Enable dynamic printk() support

目前在 kernel 驱动代码中,都不再建议直接使用 printk 直接添加打印信息,而是使用 dev_info、dev_dbg、dev_err 之类的函数代替,虽然这些 dev_xxx 函数的本质还是使用 printk 打印的,但是相比起 printk,dev_xxx 的好处是:

  • 支持打印模块信息、dev 信息;
  • 支持动态调试(dynamic debug)方式。

3.动态打印调试方法

打开内核动态调试开关,make menuconfig 选中 CONFIG_DYNAMIC_DEBUG 以及 CONFIG_DEBUG_FS。Linux 启动后,使用命令行挂载上 dbgfs。

mkdir /mnt/dbg
mount -t debugfs none /mnt/dbg

使用下面方式控制你想输出 dev_dbg() 信息

  • 控制某个文件所有 dev_dbg()
echo -n "file xxx.c +p" > /mnt/dbg/dynamic_debug/control
  • 控制某个函数所有 dev_dbg()
echo -n "func xxx +p" > /mnt/dbg/dynamic_debug/control

运行程序,使用 dmesg 则可以看到相应 dev_dbg() 的输出信息。当调试结束,不再想输出 dev_dbg() 信息了,使用下面命令关闭即可。

echo -n "file xxx.c -p" > /mnt/dbg/dynamic_debug/control
echo -n "func xxx -p" > /mnt/dbg/dynamic_debug/control

动态打印调试的原理是,当编译选项 CONFIG_DYNAMIC_DEBUG 打开的时候,在编译阶段,kernel 会把所有使用 dev_dbg() 的信息记录在一个 table 中,这些信息我们可以从 /mnt/dbg/dynamic_debug/control 解析出来。

  • 开发版本,打开 CONFIG_DYNAMIC_DEBUGCONFIG_DEBUG_FS,配合 dbgfs 动态观测和调试内核代码;
  • 正式版本,关闭 CONFIG_DYNAMIC_DEBUGCONFIG_DEBUG_FS,所有 dbgfs 以及 dev_dbg 信息都从编译阶段自动移除。

参考链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux内核之 printk 打印 的相关文章

  • Java-异常

    什么是异常 xff1f 异常是指程序运行时 xff0c 导致正常流程被中断的事件 异常分类 可查异常 xff1a CheckedException xff08 要么try catch住 要么往外抛 xff0c 谁调用 xff0c 谁处理 如
  • 51单片机学习篇-- --蜂鸣器的使用

    开篇先说一句废话 本旺名字叫萨摩耶 xff0c xff0c Please 叫我旺财 xff0c xff0c xff0c 哈哈 xff0c 招财进宝嘛 xff01 蜂鸣器是个啥 蜂鸣器一般分为两种 xff0c 一种是无源蜂鸣器 xff0c 一
  • 51单片机学习篇-- --基于51单片机的串口通信协议

    开篇先说一句废话 本旺名字叫萨摩耶 xff0c xff0c Please 叫我旺财 xff0c xff0c xff0c 哈哈 xff0c 招财进宝嘛 xff01 开篇 计算机按照下行数据通信协议 xff0c 串口发送数据 xff0c 地址为
  • 卸载rancher出现的问题

    卸载rancher出现如下报错 error unable to retrieve the complete list of server APIs custom metrics k8s io v1beta1 the server is cu
  • docker审计日志过大导致磁盘IO

    问题 xff1a 节点发生磁盘io 节点审计日志量较大 xff0c 由于操作系统内核缺陷 xff0c 会低概率出现io卡主 影响版本 xff1a v1 15 11 v 1 17 9 查看节点是否有问题 1 登录节点 2 如果有类似下图的回显
  • linux 环境命令随记

    sh steve bourne bash bourne again shell gpl centos和ubuntu 默认使用 csh c shell C语言风格 tcsh ksh xff1a korb shell aix默认shell zs
  • sed命令的使用

    sed命令 格式 sed 选项 脚本命令 文件名 选项 n 使用安静silent模式 在一般sed的用法中 xff0c 所有来自stdin的内容一般都会被列出到屏幕上 但如果加上 n参数后 xff0c 则只有经过sed特殊处理的那一行 或者
  • docker安装和info信息

    docker 容器的历史 xff1a 1 Chroot Jail 就是我们常见的 chroot 命令的用法 它在 1979 年的时候就出现了 xff0c 被认为是最早的容器化技术之一 它可以把一个进程的文件系统隔离起来 2 The Free
  • docker镜像管理

    docker镜像管理 镜像结构和原理 镜像就是创建容器的模版 xff0c 含有容器启动所需要的文件系统及所需要的内容 xff0c 因此镜像主要用于方便和快速创建启动容器 镜像结构 xff1a 一个典型的 Linux文件系统由 bootfs
  • 容器操作基础命令随记

    容器操作基础命令 命令周期 一次性启动容器docker run 一次性运行容器 xff0c 退出后立即删除 xff0c 用于测试 root 64 localhost docker run rm alpine cat etc issue We
  • SRE-Google运维解密随记-1

    雇佣系统管理员 sysadmin 运维复杂的计算机系统 xff0c 是行业内一直以来的普遍做法 这些系统管理员负责将现成的软件组件部署于生产环境中 xff0c 对外提供某种业务服务 系统管理员的主要工作在于应对系统中产生的各种需要人工干预的
  • SpringCloud-Netflix并没有闭源、Eureka1.X也没有闭源

    网上流行的说法 xff1a Netflix的Eureka 闭源了 xff08 不实 xff09 引起一些人的焦虑 恐慌 xff0c SpringCloud Netflix是不是就不能用了 xff0c 没人维护了 真相 xff1a 1 Spr
  • SRE-Google运维解密随记-2-服务目标质量

    服务质量指标 SLI 服务质量目标 SLO 服务质量协议 SLA 这三项分别是指该服务最重要的一些基础指标 这些指标的预期值 xff0c 以及当指标不符合预期时的应对计划 事先选择好合适的指标有助于在故障发生时帮助SRE进行更好地决策 xf
  • SRE-Google运维解密随记-3-分布式系统的监控

    监控的大部分通用的术语 xff1a 监控 monitoring 收集 处理 汇总 xff0c 并且显示关于某个系统的实时量化数据 xff0c 例如请求的数量和类型 xff0c 错误的数量和类型 xff0c 以及处理用时 xff0c 应用服务
  • SRE-Google运维解密随记-4

    自动化系统的演进 草率地进行自动化可能在解决问题的同时产生出其他问题 因此 xff0c 虽然我们认为在大多数情况下以软件为基础的自动化是优于手动操作的 xff0c 但是比 这两个选择更好的方案是一个不需要这些的系统设计一个自治的系统 或者换
  • linux下查看wwn号

    linux终端命令行中通过 cat sys class fc host host port name 命令查看wwn号即可 cat sys class fc host host port name
  • Linux系统权限集中管理项目案例实践

    目录 1 1 etc syduoers配置语法注意事项 1 2 etc sudoers配置文件别名知识 1 3 在 etc sudoers配置文件中 xff0c 别名和配置语法的对应关系表 1 4 利用别名配置授权实践案例 2 企业环境中用
  • 故障记录-磁盘性能下降导致节点触发迁移

    2023 03 11 11 28 52 012 ERROR 139673393420032 send ZMQ message to tcp 9765 failed 34 action 34 34 get pool status 34 34
  • gsch和redirfs模块导致系统hang或者重启 。

    Trend Micro Deep Security Agent 与Gluster 文件系统不兼容导致夯机 modules 34 gsch and redirfs 34 causing frequent kernel panic Trend
  • RedHat Linux系统故障修复—— grub引导、MBR损坏修复过程

    一 故障问题 MBR损坏是一种非常常见的错误 xff0c 两种情况 xff1a 1 MBR文件损坏 2 grub目录被误删除 1 首先 xff0c MBR是安装在硬盘的第一个扇区上占用了512个字节 xff0c 其中前446字节是bootl

随机推荐

  • 在救援模式下收集 sosreport

    问题 如何在救援模式下收集 sosreport xff1f 对于无法正常启动的操作系统 xff0c 如何收集 sosreport xff1f Red Hat Enterprise Linux 系统无法启动 当技术支持人员需要相关信息来进行问
  • 在Linux系统救援环境中实现联网

    环境 救援环境下的红帽企业 Linux 5 6 7 8 9 问题 生成了 sosreport 在初始救援环境设置期间未启用网络 解决方案 使用 IP 命令套件 iproute 包 xff1a 1 ip link 将显示连接到系统的可用设备
  • Rsa读取pem公钥和私钥

    1 把pem文件用text打开 xff0c 把开头和结尾的begin和end内容删去 xff0c 只留下字符串内容 xff1b 2 用流读取文件中的字符串 xff1b 3 用以下代码生成公钥和私钥对象 xff1b public static
  • 当 rsync/scp 不可用时,从系统传输文件或者 sosreport。

    环境 红帽企业 Linux 5 x红帽企业 Linux 6 x红帽企业 Linux 7 x 问题 文件需要转移到另一个系统 xff0c 但是ssh和rsync未设置和 或允许 一个sosreport需要转移到另一个系统 红帽企业 Linux
  • 如何配置Linux操作系统内DNS配置不被DHCP自动更新

    问题原因 NetworkManager是一个软件工具 xff0c 旨在简化计算机网络的使用 NetworkManager可用于基于Linux内核和其他类Unix操作系统 目前主流Linux操作系统都使用NetworkManager进行网络自
  • 2021-09-27

    虚拟环境中用pip下载安装包却安装到base环境解决方案 原因解决方案 遇到的问题 xff1a windows环境下进入虚拟环境 xff0c 使用pip install指令安装包时发现没有安装到虚拟环境下 xff0c 而是安装到了base环
  • 网络服务(Neutron)安装配置 ,这一篇就够了!

    实验目标 OpenStack Networking xff08 neutron xff09 xff0c 允许创建 插入接口设备 xff0c 这些设备由其它的OpenStack服务管理 插件式的实现可以容纳不同的网络设备和软件 xff0c 为
  • ssh服务和日志的基本常识

    查看网桥 brctl show 创建链接 ln s mnt dir file mnt lianjie 1 查看进程 gnome system monltor ps 当前shell的进程 A 所有的进程 a shell中所有的进程 xff0c
  • ESP8266基础详细使用

    前言 刚买一块ESP8266 琢磨一天才弄明白怎么使用 xff0c 小白第一次弄这个确实不太友好 xff0c 这里记录一下 xff0c 怕以后自己用到又忘了 xff0c 在物联网这一方面ESP8266还是特别实用的 材料准备 淘宝 xff0
  • nvm安装流程

    nvm nvm是管理node版本的工具 一般我们会负责多个项目 xff0c 不同项目有不同版本的node环境 xff0c 此时就需要nvm对node版本进行切换处理 1 首先卸载node 2 nvm下载 安装包下载地址 xff1a http
  • 树莓派 raspbian (各版本)换国内源

    xff08 看到师兄的博客后感觉还行 xff0c 所以自己也来写下 xff0c 第一次写 xff0c 所以不会编排 xff0c 有什么错误希望被指出 xff0c 谢谢 xff09 相信来寻找换源的人都和一样知道为什么要换国内更新源了吧 xf
  • 树莓派4b的i2c配置及wiringPi通信

    一 配置i2c设备 1 xff09 在终端中操作 xff0c 输入指令 sudo raspi config 2 xff09 然后会出现设置界面 xff0c 然后跟着如下图片操作 第一项 xff1a Change User Password
  • 树莓派驱动之设备树覆盖

    一 前言 由于是初学者 xff0c 所以对于一些操作需要记录下方便自己查找 附上 xff1a 树莓派设备树官网 我只从官网上了解到一点点内容 xff0c 还有许多没看懂的和还没学的 一个常规的Arm Linux设备树 xff0c 主要是由源
  • ConcurrentHashMap 常用方法

    void clear 从该映射中移除所有映射关系 boolean containsKey Object key 测试指定对象是否为此表中的键 boolean containsValue Object value 如果此映射将一个或多个键映射
  • .vscode中常用的配置文件

    文件 一 安装常用插件二 c cpp properties json文件三 settings json文件 一 安装常用插件 根据自己需要安装相应的插件 xff1a span class token number 1 span span c
  • 操作系统相关知识

    目录 一 嵌入式操作系统二 实时操作系统 xff08 RTOS xff09 三 Freertos 操作系统四 Linux xff08 操作系统 xff09 五 Linux 和 FreeRTOS操作系统的区别 xff08 面试中被问到 xff
  • 结构体对齐(全)

    目录 一 结构体对齐规则二 结构体位域对齐规则 一 结构体对齐规则 1 第一个成员在与结构体偏移量为0的地址处 xff1b 2 其他成员变量要与自身类型的整数倍地址处对齐 xff1b 3 结构体总大小为要与 处理器字节数与成员类型所占字节数
  • C语言自我实现模块化打印log

    在一个嵌入式稍微大些的工程中实现模块化控制打印输出信息是很有必要的 xff0c 下面是模仿别人的实现的模块化打印 xff0c 需要时可以根据下面的实现代码去修改满足自己所需要的 xff01 xff01 xff01 span class to
  • 卸载ibus后无法进入桌面的解决方法

    过程 一 复现现象 xff1a 二 复现原因 xff1a 三 解决方法 xff1a 重新安装ubuntu桌面 一 复现现象 xff1a 开机进入 Ubuntu xff0c 输入密码成功后一直卡在这个页面 xff0c 无法进入 ubuntu
  • Linux内核之 printk 打印

    Linux内核之 printk 打印 前言一 printk 介绍1 printk 消息级别2 内核 printk 文件 二 调整打印级别1 在 menuconfig 中修改2 在系统中修改 xff08 常用 xff09 三 使用示例四 查看