Kdump之kdump分析(续)

news/2024/7/5 23:18:44 标签: header, action, path, date, 测试, function
在第二个内核以类似ro root=LABEL=/  rhgb  quiet  irqpoll  maxcpus=1  reset_devices  memmap=exactmap memmap=640K@0K memmap=5264K@16384K   memmap=125152K@22288K
elfcorehdr=147440K memmap=56K#1834688K memmap=136K#1834744K
memmap=128K#1834880K  memmap=1024K$4193280K启动时,再次调用/etc/init.d/kdump start来启动
,由于此时/proc/vmcore存在且大小不为0,所以,
 

unction save_core()
{
    local kdump_path
    kdump_path=`grep ^path $KDUMP_CONFIG_FILE | cut -d' ' -f2-`
    if [ -z "$kdump_path" ]; then
        coredir="/var/crash/`date +"%Y-%m-%d-%H:%M"`"
    else
        coredir="${kdump_path}/`date +"%Y-%m-%d-%H:%M"`"
    fi

    mkdir -p $coredir
    cp --sparse=always /proc/vmcore $coredir/vmcore-incomplete
    exitcode=$?
    if [ $exitcode == 0 ]; then
        mv $coredir/vmcore-incomplete $coredir/vmcore
        $LOGGER "saved a vmcore to $coredir"
    else
        $LOGGER "failed to save a vmcore to $coredir"
    fi
    return $exitcode
}

function do_final_action()
{
    reboot
}

if [ -s /proc/vmcore ]; then #第二个内核启动后走此步!
        run_kdump_pre
        save_core
        run_kdump_post $?
        do_final_action


当初测试发现自动保存vmcore到/var/crash后会自动重启, 这个当时没明白,其实是由于do_final_action里调用重启命令了....(其实上述过程一般是走不到的,因为默认没挂载真实/分区之前就重启了,见下面分析!)

另外在/etc/kdump.conf中配置了makedumpfile来过滤和压缩页的,一直没有找到哪里使用这个文件及makedumpfile的, 后来才发现是在/sbin/mkdumprd(一个shell脚本)制作第二个 内核需要的initrd时使用的,第二个内核启动时以此initrd做临时根文件系统,initrd中的init来调用makedumpfile过滤压缩页的, 完了之后还是会重启机器的,看了下代码,其实后面还是可以像正常一样挂载真实的/文件系统。至于为啥此时就重启机器,我猜原因一是因为已经收集到需要的信息;原因二是由于此时能使用的内存有限,此时只能使用128M物理内存,加载剩余驱动或者服务等所需内存可能不够,测试中发现有时会在挂载真实的/文件系统时kernel panic.
用一张图总结下:



至于/sbin/kdump也就是kexec-tools中的kdump,没找到在哪里调用这个?看了下代码,这个只接受一个参数elfcorehdr,将原内存中相关信息Ehdr,pt_note(多个合并成一个),pt_load,note_bytes,Segments等等最终输出到stdout上,这个在使用时应该重定向到一个文件中才是?????


int main(int argc, char **argv)
{
    char *start_addr_str, *end;
    unsigned long long start_addr;
    Elf64_Ehdr *ehdr;
    Elf64_Phdr *phdr;
    void *notes, *headers;
    size_t note_bytes, header_bytes;
    int fd;
    int i;
    start_addr_str = 0;
    if (argc > 2) {
        fprintf(stderr, "Invalid argument count\n");
        exit(9);
    }
    if (argc == 2) {
        start_addr_str = argv[1];//第一个内核的ELF头所在的物理地址先传给kdump,然后被作为命令行参数(elfcorehdr=)传递给新启动的转储内核.第二个内核的启动参数最终大概为这个终形式

        //root=/=Label irqpoll maxcpus=1 reset_device memmap=exactmap memmap=640K@0 memmap=X@16384 elfcorehdr=Z memmap=Y@U ....

    }
    if (!start_addr_str) {
        start_addr_str = getenv("elfcorehdr");
    }
    if (!start_addr_str) {
        fprintf(stderr, "Cannot find the start of the core dump\n");
        exit(1);
    }
    start_addr = strtoull(start_addr_str, &end, 0);
    if ((start_addr_str == end) || (*end != '\0')) {
        fprintf(stderr, "Bad core dump start addres: %s\n",
            start_addr_str);
        exit(2);
    }
    
    fd = open(DEV_MEM, O_RDONLY);//打开第一个内核的内存/dev/mem !!!!!

    if (fd < 0) {
        fprintf(stderr, "Cannot open " DEV_MEM ": %s\n",
            strerror(errno));
        exit(3);
    }

    /* Get the elf header */
    ehdr = map_addr(fd, sizeof(*ehdr), start_addr);

    /* Verify the ELF header */
    if (    (ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
        (ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
        (ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
        (ehdr->e_ident[EI_MAG3] != ELFMAG3) ||
        (ehdr->e_ident[EI_CLASS] != ELFCLASS64) ||
        (ehdr->e_ident[EI_DATA] != ELFDATALOCAL) ||
        (ehdr->e_ident[EI_VERSION] != EV_CURRENT) ||
        (ehdr->e_type != ET_CORE) ||
        (ehdr->e_version != EV_CURRENT) ||
        (ehdr->e_ehsize != sizeof(Elf64_Ehdr)) ||
        (ehdr->e_phentsize != sizeof(Elf64_Phdr)) ||
        (ehdr->e_phnum == 0))
    {
        fprintf(stderr, "Invalid Elf header\n");
        exit(4);
    }
    
    /* Get the program header */
    phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff);

    /* Collect up the notes */
    note_bytes = 0;
    notes = collect_notes(fd, ehdr, phdr, &note_bytes);
    
    /* Generate new headers */
    header_bytes = 0;
    headers = generate_new_headers(ehdr, phdr, note_bytes, &header_bytes);//=====>


    /* Write out everything */
    //由于刚开始第一个内核可能不止一个p_note段,这里合并成一个,写到STDOUT_FILENO

    //最后布局如下

write_all(STDOUT_FILENO, headers, header_bytes);
    write_all(STDOUT_FILENO, notes, note_bytes);
    for(i = 0; i < ehdr->e_phnum; i++) {
        unsigned long long offset, size;
        size_t wsize;
        if (phdr[i].p_type != PT_NOTE) {
            continue;
        }
        offset = phdr[i].p_offset;
        size = phdr[i].p_filesz;
        wsize = MAP_WINDOW_SIZE;
        if (wsize > size) {
            wsize = size;
        }
        for(;size > 0; size -= wsize, offset += wsize) {
            void *buf;
            wsize = MAP_WINDOW_SIZE;
            if (wsize > size) {
                wsize = size;
            }
            buf = map_addr(fd, wsize, offset);
            write_all(STDOUT_FILENO, buf, wsize);
            unmap_addr(buf, wsize);
        }
    }
    free(notes);
    close(fd);
    return 0;
}


http://www.niftyadmin.cn/n/1402567.html

相关文章

kdump转储的内核实现

前面一篇文章介绍了kexec和kdump的思想&#xff0c;本文着重讲它们的另一个方面&#xff0c;就是kdump到底是如何转储垮掉内核的内存映像的。首先定义一个链表&#xff0c;它很重要。 static LIST_HEAD(vmcore_list); unsigned long long elfcorehdr_addr ELFCORE_ADDR_MAX; /…

基于kexec的崩溃转储机制

设计 当一个内核转储发生的时候kdump使用kexec启动一个备份 的内核 。这个备份启动的内核只是使用少量的内存&#xff0c;并且这些内存由第一个内核提供 。这样设计保证了第一个内核启动且正在运行中的DMA不会破坏第二个内核的运行 。 在内核崩溃之前所有关于核心映…

linux内核调度器

O(1):略 BFS:http://www.ibm.com/developerworks/cn/linux/l-cn-bfs/index.html?cadrs- CFS:http://www.ibm.com/developerworks/cn/linux/l-completely-fair-scheduler/

Linux 是如何支持SMP的

一篇关于Linux 是如何支持SMP的文档: http://download.csdn.net/detail/lucien_cc/4345491

Linux中定时器的算法实现

定时器的作用 定时器在操作系统中起到了举足轻重的作用。在做IO操作时&#xff0c;需要超时机制保证任务不处于无休止的等待状态&#xff1b;在延时处理时&#xff0c;可以通过“闹表”进行相对准点的唤醒操作。在多任务操作系统中&#xff0c;定时器是一种非常常用的资源。 对…

使用 kexec 快速重启 Linux

http://www.ibm.com/developerworks/cn/linux/l-kexec/index.html

Linux DM9000网卡驱动程序完全分析

http://www.linuxidc.com/Linux/2011-03/33850.htm

SYN-Flood遭遇战——Linux内核SYN-Cookie实现探究

SYN Flood好使啊&#xff0c;成本低廉&#xff0c;简单暴力&#xff0c;杀伤力强&#xff0c;更重要的是&#xff1a;无解&#xff0c;一打一个准&#xff01;这种攻击充分利用了TCP协议的弱点&#xff0c;可以很轻易将你的网络打趴下。如果监控和应急不到位的话&#xff0c;那…