You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux C程序写入/dev/kmsg后dmesg无输出问题排查

问题根因

你的代码存在两个直接导致写入失败的问题:

  • 低级笔误:打开/dev/kmsg得到的文件描述符存在fdKmsg变量中,但调用close()时传入了从未定义的变量fd。如果编译时没有开启严格警告,这个未初始化的自动变量会取栈上的随机垃圾值,传入close()只会触发EBADF错误,合法的fdKmsg不会被正常关闭;更严重的是,代码存在未定义行为时,部分编译器会直接优化掉前面的dprintf写入逻辑,导致写入操作根本不执行。
  • 不符合/dev/kmsg的写入规范:向/dev/kmsg写入日志时,标准格式要求在消息头部添加<N>形式的日志级别前缀,N和内核printk的级别定义完全对应:
    • 0:KERN_EMERG 系统不可用
    • 1:KERN_ALERT 必须立即处理
    • 2:KERN_CRIT 临界错误
    • 3:KERN_ERR 常规错误
    • 4:KERN_WARNING 警告
    • 5:KERN_NOTICE 普通提示
    • 6:KERN_INFO 信息
    • 7:KERN_DEBUG 调试信息
      部分内核版本会直接丢弃不带合法级别前缀的写入消息,不会加入内核日志环形缓冲区。你提到的echo "foo" > /dev/kmsg能生效,是因为部分新版内核给shell场景的写入做了兼容,会自动补默认级别,但这种逻辑不覆盖所有用户程序写入场景,显式添加前缀才是可移植的标准写法。
  • 额外隐患:你没有检查dprintf的返回值,碰到设备忙、写入被限流等问题时,完全无法感知写入失败。

不需要额外调用fsync(),/dev/kmsg是字符设备,写入操作直接进入内核printk环形缓冲区,不存在块设备的页缓存刷盘逻辑,fsync对它无意义。

修正后可运行代码
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
  int fdKmsg = open("/dev/kmsg", O_WRONLY);
  if (fdKmsg < 0)
  {
    perror("open /dev/kmsg failed");
    return 1;
  }

  // <5>为NOTICE级别,可根据需求调整0-7的数值
  int ret = dprintf(fdKmsg, "<5>-- Hello World --\n");
  if (ret < 0)
  {
    perror("write kmsg failed");
    close(fdKmsg);
    return 1;
  }

  close(fdKmsg);
  return 0;
}
验证方式

用root权限编译运行上述代码后,执行dmesg | tail即可看到你写入的日志条目。如果普通用户执行dmesg看不到内容,检查kernel.dmesg_restrict sysctl参数,该参数为1时会限制非root用户读取内核日志。

内容的提问来源于stack exchange,提问作者Maxthecat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 17:24:19