pstore 从oops发生到保存dmesg的过程

本文探讨了Linux内核中的panic机制与kmsg_dump功能,解析了kmsg_dump_register的作用及其实现,并介绍了pstore模块如何利用这些机制来记录系统崩溃时的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



./kernel/panic.c:13:#include<linux/kmsg_dump.h>

./kernel/panic.c:136: kmsg_dump(KMSG_DUMP_PANIC);

./kernel/panic.c:411: kmsg_dump(KMSG_DUMP_OOPS);


linux/kmsg_dump.h的内容

enumkmsg_dump_reason {

KMSG_DUMP_UNDEF,

KMSG_DUMP_PANIC,

KMSG_DUMP_OOPS,

KMSG_DUMP_EMERG,

KMSG_DUMP_RESTART,

KMSG_DUMP_HALT,

KMSG_DUMP_POWEROFF,

};

/**

*struct kmsg_dumper - kernel crash message dumper structure

*@list: Entry in the dumper list (private)

*@dump: Call into dumping code which will retrieve the data with

*through the record iterator

*@max_reason: filter for highest reason number that should be dumped

*@registered: Flag that specifies if this is already registered

*/

structkmsg_dumper {

structlist_head list;

void(*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);

enumkmsg_dump_reason max_reason;

boolactive;

boolregistered;

/*private state of the kmsg iterator */

u32cur_idx;

u32next_idx;

u64cur_seq;

u64next_seq;

};

#ifdefCONFIG_PRINTK

voidkmsg_dump(enum kmsg_dump_reason reason);

boolkmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,

char *line, size_t size, size_t *len);

boolkmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,

char*line, size_t size, size_t *len);

boolkmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,

char *buf, size_t size, size_t *len);

voidkmsg_dump_rewind_nolock(struct kmsg_dumper *dumper);

voidkmsg_dump_rewind(struct kmsg_dumper *dumper);

intkmsg_dump_register(struct kmsg_dumper *dumper);

intkmsg_dump_unregister(struct kmsg_dumper *dumper);



注册kmsg_dump_register的实现在printk文件中


pstore是注册的是什么样的函数?

./fs/pstore/platform.c:445: kmsg_dump_register(&pstore_dumper);


staticstruct kmsg_dumper pstore_dumper = {

.dump= pstore_dump,

};


pstore_dump->psinfo->write(PSTORE_TYPE_DMESG, reason, &id,part,

oopscount, compressed, total_len, psinfo);



structpstore_info *psinfo;

staticchar *backend;


./ram.c:503: err= pstore_register(&cxt->pstore);


staticint ramoops_probe(struct platform_device *pdev)

{

structdevice *dev = &pdev->dev;

structramoops_platform_data *pdata = pdev->dev.platform_data;

structramoops_context *cxt = &oops_cxt;

size_tdump_mem_sz;

phys_addr_tpaddr;

interr = -

=====

}


./pstore.h:47:structpstore_info {

/*types */

enumpstore_type_id {

PSTORE_TYPE_DMESG =0,

PSTORE_TYPE_MCE =1,

PSTORE_TYPE_CONSOLE =2,

PSTORE_TYPE_FTRACE =3,

/*PPC64 partition types */

PSTORE_TYPE_PPC_RTAS =4,

PSTORE_TYPE_PPC_OF =5,

PSTORE_TYPE_PPC_COMMON =6,

PSTORE_TYPE_UNKNOWN =255

};

structmodule;

structpstore_info {

structmodule *owner;

char *name;

spinlock_t buf_lock; /*serialize access to 'buf' */

char *buf;

size_t bufsize;

structmutex read_mutex; /* serialize open/read/close */

int flags;

int (*open)(structpstore_info *psi);

int (*close)(structpstore_info *psi);

ssize_t (*read)(u64*id, enum pstore_type_id *type,

int*count, struct timespec *time, char **buf,

bool*compressed, struct pstore_info *psi);

int (*write)(enumpstore_type_id type,

enumkmsg_dump_reason reason, u64 *id,

unsignedint part, int count, bool compressed,

size_tsize, struct pstore_info *psi);

int (*write_buf)(enumpstore_type_id type,

enumkmsg_dump_reason reason, u64 *id,

unsignedint part, const char *buf, bool compressed,

size_tsize, struct pstore_info *psi);

int (*erase)(enumpstore_type_id type, u64 id,

intcount, struct timespec time,

structpstore_info *psi);

void *data;

};

#define PSTORE_FLAGS_FRAGILE 1

#ifdefCONFIG_PSTORE

externint pstore_register(struct pstore_info *);

externbool pstore_cannot_block_path(enum kmsg_dump_reason reason);




staticstruct ramoops_context oops_cxt = {

.pstore= {

.owner =THIS_MODULE,

.name ="ramoops",

.open =ramoops_pstore_open,

.read =ramoops_pstore_read,

.write_buf =ramoops_pstore_write_buf,

.erase =ramoops_pstore_erase,

},

};


platform.c

intpstore_register(struct pstore_info *psi)

{

structmodule *owner = psi->owner;

if(backend && strcmp(backend, psi->name))

return-EPERM;

spin_lock(&pstore_lock);

if(psinfo) {

spin_unlock(&pstore_lock);

return-EBUSY;

}

if(!psi->write)

psi->write= pstore_write_compat;

psinfo= psi;


下一步,哪里通过 pstore文件系统,把保存的数据读出的?

我有多台运行openwrt 12的AP设备,在运行四天之后发生设备异常重启,1.两台笔记本,一台连LAN口,一台连无线,双向PING包,AP设备发生重启 CPU 0 Unable to handle kernel paging request at virtual address e79190a0, epc == 800eca00, ra == 800cff34 [347296.030000] Call Trace: [347296.030000] [<800eca00>] sync_supers+0x44/0x124 [347296.030000] [<800cff34>] bdi_sync_supers+0x34/0x58 [347296.030000] [<8008ea08>] kthread+0x90/0x98 [347296.030000] [<80066950>] kernel_thread_helper+0x10/0x18 2. 两台笔记本,一台连LAN口,一台连无线,双向PING包,AP设备发生重启 Unhandled kernel unaligned access[#1]: [347296.020000] Call Trace: [347296.020000] [<800eca00>] sync_supers+0x44/0x124 [347296.020000] [<800cff34>] bdi_sync_supers+0x34/0x58 [347296.020000] [<8008ea08>] kthread+0x90/0x98 [347296.020000] [<80066950>] kernel_thread_helper+0x10/0x18 3.两台笔记本,一台连LAN口,一台连无线,双向PING包,AP设备发生重启 Unhandled kernel unaligned access[#1]: [347296.020000] Call Trace: [347296.020000] [<800eca00>] sync_supers+0x44/0x124 [347296.020000] [<800cff34>] bdi_sync_supers+0x34/0x58 [347296.020000] [<8008ea08>] kthread+0x90/0x98 [347296.020000] [<80066950>] kernel_thread_helper+0x10/0x18 4.两台笔记本,一台连LAN口,一台连无线,双向PING包,AP设备发生重启 Data bus error, epc == 8006ad60, ra == 8006af14 [347296.020000] Call Trace: [347296.020000] [<8006ad60>] emulate_load_store_insn+0x220/0x2f8 [347296.020000] [<8006af14>] do_ade+0xdc/0x158 [347296.020000] [<80064e20>] ret_from_exception+0x0/0xc [347296.020000] [<800eca00>] sync_supers+0x44/0x124 [347296.020000] [<800cff34>] bdi_sync_supers+0x34/0x58 [347296.020000] [<8008ea08>] kthread+0x90/0x98 [347296.020000] [<80066950>] kernel_thread_helper+0x10/0x18 5.两台笔记本,一台连LAN口,一台连无线,双向PING包,AP设备发生重启 Data bus error, epc == 8006ad60, ra == 8006af14 [347296.020000] Call Trace: [347296.020000] [<8006ad60>] emulate_load_store_insn+0x220/0x2f8 [347296.020000] [<8006af14>] do_ade+0xdc/0x158 [347296.020000] [<80064e20>] ret_from_exception+0x0/0xc [347296.020000] [<800eca00>] sync_supers+0x44/0x124 [347296.020000] [<800cff34>] bdi_sync_supers+0x34/0x58 [347296.020000] [<8008ea08>] kthread+0x90/0x98 [347296.020000] [<80066950>] kernel_thread_helper+0x10/0x18 6.未连无线挂机,访问WEB界面重启 CPU 0 Unable to handle kernel paging request at virtual address eea005a0, epc == 8007de74, ra == 80133614 [389773.160000] Call Trace: [389773.160000] [<8007de74>] __sysctl_head_next+0x3c/0x108 [389773.160000] [<80133614>] proc_sys_lookup+0x10c/0x13c [389773.160000] [<800f350c>] d_alloc_and_lookup+0x54/0x90 [389773.160000] [<800f3a80>] do_lookup+0x2a8/0x390 [389773.160000] [<800f5808>] path_lookupat+0x148/0x708 [389773.160000] [<800f5df8>] do_path_lookup+0x30/0xa4 [389773.160000] [<800f751c>] user_path_at_empty+0x60/0xa8 [389773.160000] [<800f7574>] user_path_at+0x10/0x1c [389773.160000] [<800e8a0c>] sys_faccessat+0xb4/0x1cc [389773.160000] [<8006c584>] stack_done+0x20/0x40 7.未连无线挂机,访问WEB界面重启 CPU 0 Unable to handle kernel paging request at virtual address e9a3088c, epc == 8007de74, ra == 80133614 [393501.240000] Call Trace: [393501.240000] [<8007de74>] __sysctl_head_next+0x3c/0x108 [393501.240000] [<80133614>] proc_sys_lookup+0x10c/0x13c [393501.240000] [<800f350c>] d_alloc_and_lookup+0x54/0x90 [393501.240000] [<800f3a80>] do_lookup+0x2a8/0x390 [393501.240000] [<800f5808>] path_lookupat+0x148/0x708 [393501.240000] [<800f5df8>] do_path_lookup+0x30/0xa4 [393501.240000] [<800f751c>] user_path_at_empty+0x60/0xa8 [393501.240000] [<800f7574>] user_path_at+0x10/0x1c [393501.240000] [<800e8a0c>] sys_faccessat+0xb4/0x1cc [393501.240000] [<8006c584>] stack_done+0x20/0x40 8.输入cat /proc/sys/fs/file补全命令时重启 [502416.700000] Unhandled kernel unaligned access[#1]: [502416.700000] Call Trace: [502416.700000] [<8007de74>] __sysctl_head_next+0x3c/0x108 [502416.700000] [<801333ec>] proc_sys_readdir+0x118/0x234 [502416.700000] [<800f9f7c>] vfs_readdir+0xb4/0xdc [502416.700000] [<800fa16c>] sys_getdents64+0x74/0xe8 [502416.700000] [<8006c584>] stack_done+0x20/0x40 9.运行四天,访问WEB界面重启 [357658.830000] Unhandled kernel unaligned access[#1]: [357658.830000] Call Trace: [357658.830000] [<8007de74>] __sysctl_head_next+0x3c/0x108 [357658.830000] [<80133614>] proc_sys_lookup+0x10c/0x13c [357658.830000] [<800f350c>] d_alloc_and_lookup+0x54/0x90 [357658.830000] [<800f3a80>] do_lookup+0x2a8/0x390 [357658.830000] [<800f5808>] path_lookupat+0x148/0x708 [357658.830000] [<800f5df8>] do_path_lookup+0x30/0xa4 [357658.830000] [<800f751c>] user_path_at_empty+0x60/0xa8 [357658.830000] [<800f7574>] user_path_at+0x10/0x1c [357658.830000] [<800e8a0c>] sys_faccessat+0xb4/0x1cc [357658.830000] [<8006c584>] stack_done+0x20/0x40
06-14
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值