• 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复制给调用者。

     
     



     
  • 相关阅读:
    HDU 4691
    cin和scanf的速度差别
    一点点webservice的小知识
    Geetest 极验验证 验证图片拼图
    web api post传一个参数时 值永远是null
    关于支付宝支付的
    发布网站后只能在服务器上访问 外网访问不了??
    sidePagination: "server"和responseHandler: responseHandler
    .net 找回密码的第一步 第二步 第三步的进程条
    关于设置一个全局只读变量来实现验证
  • 原文地址:https://www.cnblogs.com/aspirs/p/15471868.html
Copyright © 2020-2023  润新知