资讯详情

Kdump之kexec源码分析

知道kexec还是在linuxsir看一篇介绍其应用的帖子, 经常用kexec快速启动内核的步骤如下: (1).kexec -l <kernel-image> --append="<command-line-options>" [--initrd=xxxxxxxxxxx一般需要,但在某些情况下可以选择] 例如: kexec -l /boot/vmlinuz-2.6.31 --append="root=/dev/sda6 ro nomce vga=0x317" --initrd=xxxxxxxxxxx (2).kexec -e 再或者用kexec -p 下面仅分析kexe -l & -e的形式

int main(int argc, char *argv[]) { int do_load = 1; int do_exec = 0; int do_load_jump_back_helper = 0; int do_shutdown = 1; int do_sync = 1; int do_ifdown = 0; int do_unload = 0; int do_reuse_initrd = 0; void *entry = 0; char *type = 0; char *endptr; int opt; int result = 0; int fileind; static const struct option options[] = { KEXEC_ARCH_OPTIONS { 0, 0, 0, 0}, }; static const char short_options[] = KEXEC_OPT_STR; opterr = 0; /* Don't complain about unrecognized options here */ while ((opt = getopt_long(argc, argv, short_options, &nbs;          options, 0)) != -1) {         switch(opt) {         case OPT_HELP:             usage();             return 0;         case OPT_VERSION:             version();             return 0;         case OPT_NOIFDOWN:             do_ifdown = 0;             break;         case OPT_FORCE:             do_load = 1;             do_shutdown = 0;             do_sync = 1;             do_ifdown = 1;             do_exec = 1;             break;         case OPT_LOAD://here1:             do_load = 1;             do_exec = 0;             do_shutdown = 0;             break;         case OPT_UNLOAD:             do_load = 0;             do_shutdown = 0;             do_sync = 0;             do_unload = 1;             break;         case OPT_EXEC://here3:             do_load = 0;             do_shutdown = 0;             do_sync = 1;             do_ifdown = 1;             do_exec = 1;             break;         case OPT_LOAD_JUMP_BACK_HELPER:             do_load = 0;             do_shutdown = 0;             do_sync = 1;             do_ifdown = 1;             do_exec = 0;             do_load_jump_back_helper = 1;             kexec_flags = KEXEC_PRESERVE_CONTEXT;             break;         case OPT_ENTRY:             entry = (void *)strtoul(optarg, &endptr, 0);             if (*endptr) {                 fprintf(stderr,                     "Bad option value in --load-jump-back-helper=%s\n",                     optarg);                 usage();                 return 1;             }             break;         case OPT_LOAD_PRESERVE_CONTEXT:             do_load = 1;             do_exec = 0;             do_shutdown = 0;             do_sync = 1;             kexec_flags = KEXEC_PRESERVE_CONTEXT;             break;         case OPT_TYPE:             type = optarg;             break;         case OPT_PANIC://here2:             do_load = 1;             do_exec = 0;             do_shutdown = 0;             do_sync = 0;             kexec_flags = KEXEC_ON_CRASH;             break;         case OPT_MEM_MIN:             mem_min = strtoul(optarg, &endptr, 0);             if (*endptr) {                 fprintf(stderr,                     "Bad option value in --mem-min=%s\n",                     optarg);                 usage();                 return 1;             }             break;         case OPT_MEM_MAX:             mem_max = strtoul(optarg, &endptr, 0);             if (*endptr) {                 fprintf(stderr,                     "Bad option value in --mem-max=%s\n",                     optarg);                 usage();                 return 1;             }             break;         case OPT_REUSE_INITRD:             do_reuse_initrd = 1;             break;         default:             break;         }     }     if ((kexec_flags & KEXEC_ON_CRASH) && !is_crashkernel_mem_reserved()) {         printf("Memory for crashkernel is not reserved\n");         printf("Please reserve memory by passing ");         printf("\"crashkernel=X@Y\" parameter to the kernel\n");         die("Then try loading kdump kernel\n");     }     if (do_load && (kexec_flags & KEXEC_PRESERVE_CONTEXT) &&      mem_max == ULONG_MAX) {         printf("Please specify memory range used by kexeced kernel\n");         printf("to preserve the context of original kernel with \n");         die("\"--mem-max\" parameter\n");     }     fileind = optind;     /* Reset getopt for the next pass; called in other source modules */     opterr = 1;     optind = 1;     result = arch_process_options(argc, argv);//先进来,一般情况下result返回为0     /* Check for bogus options */     if (!do_load) {         while((opt = getopt_long(argc, argv, short_options,                      options, 0)) != -1) {             if ((opt == '?') || (opt >= OPT_ARCH_MAX)) {                 usage();                 return 1;             }         }     }     if (do_reuse_initrd){         check_reuse_initrd();         arch_reuse_initrd();     }     if (do_unload) {         result = k_unload(kexec_flags);     }     if (do_load && (result == 0)) { //here1,here2:         result = my_load(type, fileind, argc, argv, kexec_flags, entry);//====>trap into     }     /* Don't shutdown unless there is something to reboot to! */     if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded()) {         die("Nothing has been loaded!\n");     }     if ((result == 0) && do_shutdown) {         result = my_shutdown();     }     if ((result == 0) && do_sync) {         sync();     }     if ((result == 0) && do_ifdown) {         ifdown();     }     if ((result == 0) && do_exec) { //here3:         result = my_exec();//=================>trap into     }     if ((result == 0) && do_load_jump_back_helper) {         result = my_load_jump_back_helper(kexec_flags, entry);     }     fflush(stdout);     fflush(stderr);     return result; }

/*  *    Load the new kernel  */ static int my_load(const char *type, int fileind, int argc, char **argv,          unsigned long kexec_flags, void *entry)//****************** {     char *kernel;     char *kernel_buf;     off_t kernel_size;     int i = 0;     int result;     struct kexec_info info;//1.注意这个结构体     long native_arch;     int guess_only = 0;     memset(&info, 0, sizeof(info));     info.segment = NULL;     info.nr_segments = 0;     info.entry = NULL;     info.backup_start = 0;     info.kexec_flags = kexec_flags;     result = 0;     if (argc - fileind <= 0) {         fprintf(stderr, "No kernel specified\n");         usage();         return -1;     }     kernel = argv[fileind];     /* slurp in the input kernel */     kernel_buf = slurp_decompress_file(kernel, &kernel_size);//kernel_buf中含有解压缩的内核 #if 0     fprintf(stderr, "kernel: %p kernel_size: %lx\n",         kernel_buf, kernel_size); #endif     if (get_memory_ranges(&info.memory_range, &info.memory_ranges,         info.kexec_flags) < 0) {         fprintf(stderr, "Could not get memory layout\n");         return -1;     }     /* if a kernel type was specified, try to honor it */     if (type) {         for (i = 0; i < file_types; i++) {             if (strcmp(type, file_type[i].name) == 0)                 break;         }         if (i == file_types) {             fprintf(stderr, "Unsupported kernel type %s\n", type);             return -1;         } else {             /* make sure our file is really of that type */

   /*   此处用到的变量file_type的结构体 struct file_type {     const char *name;     probe_t *probe;     load_t  *load;     usage_t *usage; };//类似指定回调函数 struct file_type file_type[] = {     { "multiboot-x86", multiboot_x86_probe, multiboot_x86_load,       multiboot_x86_usage },     { "elf-x86", elf_x86_probe, elf_x86_load, elf_x86_usage },     { "bzImage", bzImage_probe, bzImage_load, bzImage_usage },     { "beoboot-x86", beoboot_probe, beoboot_load, beoboot_usage },     { "nbi-x86", nbi_probe, nbi_load, nbi_usage }, };    */             if (file_type[i].probe(kernel_buf, kernel_size) < 0)                 guess_only = 1;         }     }     if (!type || guess_only) {         for (i = 0; i < file_types; i++) {             if (file_type[i].probe(kernel_buf, kernel_size) >= 0)                 break;         }         if (i == file_types) {             fprintf(stderr, "Cannot determine the file type "                     "of %s\n", kernel);             return -1;         } else {             if (guess_only) {                 fprintf(stderr, "Wrong file type %s, "                     "file matches type %s\n",                     type, file_type[i].name);                 return -1;             }         }     }     if (file_type[i].load(argc, argv, kernel_buf,              kernel_size, &info) < 0) { //===========>trap into elf_x86_load         fprintf(stderr, "Cannot load %s\n", kernel);         return -1;     }     /* If we are not in native mode setup an appropriate trampoline */     native_arch = physical_arch();     if (native_arch < 0) {         return -1;     }     info.kexec_flags |= native_arch;     if (arch_compat_trampoline(&info) < 0) {         return -1;     }     if (info.kexec_flags & KEXEC_PRESERVE_CONTEXT) {         add_backup_segments(&info, mem_min, mem_max - mem_min + 1);     }     /* Verify all of the segments load to a valid location in memory */     for (i = 0; i < info.nr_segments; i++) {         if (!valid_memory_segment(&info, info.segment +i)) {             fprintf(stderr, "Invalid memory segment %p - %p\n",                 info.segment[i].mem,                 ((char *)info.segment[i].mem) +                 info.segment[i].memsz);             return -1;         }     }     /* Sort the segments and verify we don't have overlaps */     if (sort_segments(&info) < 0) {         return -1;     }     /* if purgatory is loaded update it */     update_purgatory(&info);//这个对新内核做下hash来进行完整性检测,,并将前640k保留起来(没仔细看,根据kdump相关资料猜得,可能有误,以后确认)     if (entry)         info.entry = entry; #if 0     fprintf(stderr, "kexec_load: entry = %p flags = %lx\n",         info.entry, info.kexec_flags);     print_segments(stderr, &info); #endif     result = kexec_load(         info.entry, info.nr_segments, info.segment, info.kexec_flags);//====================>     if (result != 0) {         /* The load failed, print some debugging information */         fprintf(stderr, "kexec_load failed: %s\n",             strerror(errno));         fprintf(stderr, "entry = %p flags = %lx\n",             info.entry, info.kexec_flags);         print_segments(stderr, &info);     }     return result; }

标签: 集成电路cc2520rhdr

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司