kernel log buf dump function kmsg_dump_get_buffer()

kernel log buf dump function kmsg_dump_get_buffer()

4.19/kernel/printk/printk.c

复制代码
void kmsg_dump(enum kmsg_dump_reason reason)
{
    struct kmsg_dumper *dumper;
    unsigned long flags;

    if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
        return;

    rcu_read_lock();
    list_for_each_entry_rcu(dumper, &dump_list, list) {
        if (dumper->max_reason && reason > dumper->max_reason)
            continue;

        /* initialize iterator with data about the stored records */
        dumper->active = true;

        logbuf_lock_irqsave(flags);
        dumper->cur_seq = clear_seq;
        dumper->cur_idx = clear_idx;
        dumper->next_seq = log_next_seq;
        dumper->next_idx = log_next_idx;
        logbuf_unlock_irqrestore(flags);

        /* invoke dumper which will iterate over records */
        dumper->dump(dumper, reason);

        /* reset iterator */
        dumper->active = false;
    }
    rcu_read_unlock();
}
复制代码

 

复制代码
bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
              char *buf, size_t size, size_t *len)
{
    unsigned long flags;
    u64 seq;
    u32 idx;
    u64 next_seq;
    u32 next_idx;
    size_t l = 0;
    bool ret = false;

    if (!dumper->active)
        goto out;

    logbuf_lock_irqsave(flags);
    if (dumper->cur_seq < log_first_seq) {
        /* messages are gone, move to first available one */
        dumper->cur_seq = log_first_seq;
        dumper->cur_idx = log_first_idx;
    }

    /* last entry */
    if (dumper->cur_seq >= dumper->next_seq) {
        logbuf_unlock_irqrestore(flags);
        goto out;
    }

    /* calculate length of entire buffer */
    seq = dumper->cur_seq;
    idx = dumper->cur_idx;
    while (seq < dumper->next_seq) {
        struct printk_log *msg = log_from_idx(idx);

        l += msg_print_text(msg, true, NULL, 0);
        idx = log_next(idx);
        seq++;
    }

    /* move first record forward until length fits into the buffer */
    seq = dumper->cur_seq;
    idx = dumper->cur_idx;
    while (l >= size && seq < dumper->next_seq) {
        struct printk_log *msg = log_from_idx(idx);

        l -= msg_print_text(msg, true, NULL, 0);
        idx = log_next(idx);
        seq++;
    }

    /* last message in next interation */
    next_seq = seq;
    next_idx = idx;

    l = 0;
    while (seq < dumper->next_seq) {
        struct printk_log *msg = log_from_idx(idx);

        l += msg_print_text(msg, syslog, buf + l, size - l);
        idx = log_next(idx);
        seq++;
    }

    dumper->next_seq = next_seq;
    dumper->next_idx = next_idx;
    ret = true;
    logbuf_unlock_irqrestore(flags);
out:
    if (len)
        *len = l;
    return ret;
}
EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
复制代码

 

下面两个变量表示kernel log buf最后一个clear log buffer后的位置(index)
dumper->cur_seq
dumper->cur_idx
下面两个变量表示kernel log buf里指向buf开头的seq、idx:
log_first_seq
log_first_idx
下面变量表示kernel log buf下一个写log的位置:
dumper->next_seq

kmsg_dump_get_buffer()函数会先计算kernel log buf目前总的size,如果这个len和此函数参数len要大,会将seq、idx前移,直到log buf size小于等于参数len,即会将会将log buf开头部分去掉,之后再将后面的log buf整体复制到函数参数buf所表示的buffer里,所以这会将kernel log buf里最新的log复制给调用者。

 
 



 

 

posted @   aspirs  阅读(313)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示