start_kernel()注解2

本文深入探讨了Linux操作系统启动过程中的关键步骤,特别是start_kernel()函数的执行细节,包括硬件配置、处理器架构设置、内存管理初始化等核心环节。
start_kernel()注解2
2010年06月17日
   /*
  Setup_arch()这个函数根据你的处理器,还有你的硬件平台设置你的系统,并解析Linux系统的命令行,设置0号进程,即Swapper进程的内在描述结构INIt_MM,系统内存管理初始化,统计并注册系统各种资源,还有其它一些相关的初始化
  */
  setup_arch(&command_line)
  {
  void __init setup_arch(char **cmdline_p)
  {
  struct tag *tags = (struct tag *)&init_tags;
  struct machine_desc *mdesc;
  char *from = default_command_line;
  setup_processor()
  {
  static void __init setup_processor(void)
  {
  extern struct proc_info_list __proc_info_begin, __proc_info_end;
  struct proc_info_list *list;
  /*
  * locate processor in the list of supported processor
  * types. The linker builds this table for us from the
  * entries in arch/arm/mm/proc-*.S
  */
  /*
  从所支持的处理器类型表中找出所需要的处理器,利用Proc-*.S里面的函数,链接器会为我们创建这个表格,根据汇编代码中获取的ARM处理器的主ID寄存器的值processor_id,从Proc.info中找到该处理器对应的处理器信息结构proc_info_list变量,
  */
  for (list = &__proc_info_begin; list cpu_mask) == list->cpu_val)//
  break;
  /*
  * If processor type is unrecognised, then we
  * can do nothing...
  */
  /*
  *如果处理器类型没有被认可,那么我们不做任何事情,
  */
  if (list >= &__proc_info_end) {
  printk("CPU configuration botched (ID %08x), unable "
  "to continue.\n", processor_id);
  while (1);
  }
  //如果被认可,我们保存CPU的名字到全局变量cpu_name中
  cpu_name = list->cpu_name;
  #ifdef MULTI_CPU
  //把该处理器的处理函数结构指针保存
  processor = *list->proc;
  #endif
  #ifdef MULTI_TLB
  //保存快表操作函数组指针
  cpu_tlb = *list->tlb;
  #endif
  #ifdef MULTI_USER
  //保存处理器用户空间操作函数组结构指针
  cpu_user = *list->user;
  #endif
  #ifdef MULTI_CACHE
  //保存Cache操作函数组结构指针
  cpu_cache = *list->cache;
  #endif
  //打印处理器名,ID,处理器的修正版本,体系结构信息
  printk("CPU: %s [%08x] revision %d (ARMv%s)\n",
  cpu_name, processor_id, (int)processor_id & 15,
  proc_arch[cpu_architecture()]);
  dump_cpu_info()
  {
  static void __init dump_cpu_info(void)
  {
  //读出处理器的ID
  unsigned int info = read_cpuid(CPUID_CACHETYPE);
  //打印处理器catche信息
  if (info != processor_id) {
  //以下是打印catche相关信息,如类型,组织形式,容量,块大小,相连性,
  printk("CPU: D %s %s cache\n", cache_is_vivt() ? "VIVT" : "VIPT",
  cache_types[CACHE_TYPE(info)]);
  if (CACHE_S(info)) {
  dump_cache("CPU: I cache", CACHE_ISIZE(info));
  dump_cache("CPU: D cache", CACHE_DSIZE(info));
  } else {
  dump_cache("CPU: cache", CACHE_ISIZE(info));
  }
  }
  }
  };
  //把它的处理器架构名字字符串arch_name + “L”传给system_utsname.machine,L是小端,B是大端 ENDIANNESS是小端
  sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
  //把体系架构版本字符串Elf_name + “L”传给elf_platform
  sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
  elf_hwcap = list->elf_hwcap;//硬件性能标志字传到全局变量中
  //刚才保存过的processor是该处理器的函数组结构变量,调用_proc_init()初始化函数
  cpu_proc_init()
  {
  processor._proc_init()
  };
  };
  // machine_arch_type:系统体系结构类型,定义了当前系统硬件平台编号,从.arch.info(体系结构信息表)中找到该平台的结构描述结构变量machine_desc,之后传给局部变量Mdesc
  mdesc = setup_machine(machine_arch_type)
  {
  static struct machine_desc * __init setup_machine(unsigned int nr)
  {
  extern struct machine_desc __arch_info_begin, __arch_info_end;
  struct machine_desc *list;
  /*
  * locate architecture in the list of supported architectures.
  从所支持的体系结构表中找出本体系结构
  */
  for (list = &__arch_info_begin; list nr == nr)//平台编号相同说明找到
  break;
  /*
  * If the architecture type is not recognised, then we
  * can co nothing...
  如果体系结构未被认可,啥也不做,
  */
  if (list >= &__arch_info_end) {
  printk("Architecture configuration botched (nr %d), unable "
  "to continue.\n", nr);
  while (1);
  }
  printk("Machine: %s\n", list->name);//打印体系结构 名字
  return list;
  }
  };
  machine_name = mdesc->name; //保存体系结构到全局变量中
  if (mdesc->soft_reboot) //如果soft_reboot不为0,将reboot_mode设为“S”说明是软件重启动,硬件重启动reboot_mode为“H”[b][/b]
  reboot_setup("s")
  {
  int __init reboot_setup(char *str)
  {
  reboot_mode = str[0];
  return 1;
  }
  };
  //如果param_offset 不为0,说明在系统内在基址+ param_offset处保存了[b]Bootloader[/b]中设置并传过来的系统参数,保存在这里的可以是老参数Param_stuct,也可以是新参数Tag
  if (mdesc->param_offset)
  tags = phys_to_virt(mdesc->param_offset)
  {
  #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
  #define PHYS_OFFSET (0x30000000UL)
  #define PAGE_OFFSET (0xc0000000UL)
  };
  2.6.10是老参数,我们会将它转成新的Tag 参数
  /*
  * If we have the old style parameters, convert them to
  * a tag list. //如果我们用的是旧格式参数,将他们转化成新格式的
  */
  if (tags->hdr.tag != ATAG_CORE)
  convert_to_tag_list(tags);// 将他们转化成新格式的,这里会将其转成连续存放 的新格式参数,
  if (tags->hdr.tag != ATAG_CORE)
  tags = (struct tag *)&init_tags;//如果param_offset[b]是0,那么就用默认参数[/b]
  if (mdesc->fixup) //成员函数有定义,调用之,做一些前期补充初始化并设置系统参数,这个函数很少定义而已, 
  mdesc->fixup(mdesc, tags, &from, &meminfo);
  if (tags->hdr.tag == ATAG_CORE) {//查看系统是否设置了核心参数(根文件系统是否是只读,内存页大小,根文件系统设备号)
  if (meminfo.nr_banks != 0)// 检查内存信息,不=0,说明前面调用过Fixup(),
  squash_mem_tags(tags)
  {
  void __init squash_mem_tags(struct tag *tag)
  { //将内存参数的结构(标签为ATAG_MEM)清除,其它参数不变
  for (; tag->hdr.size; tag = tag_next(tag))
  if (tag->hdr.tag == ATAG_MEM)
  tag->hdr.tag = ATAG_NONE;
  }
  };
  //分析连续排放在struct tag 结构变量 的地址Tags处所有有效参数设置标签,从。Taglist区根据参数标签字找出每个有效参数标签对应的Struct tagtable结构变量,执行Struct tagtable结构变量中的标签,解析相应参数设置标签的内容,这个版本的内核中有11个这样的结构,
  parse_tags(tags);
  }
  //设置Init_mm的成员变量,将Linux内核编译出来的代码段起始,结束地址,数据段结束地址,和整个内核结束地址分别保存到Start_code,end_code,end_data,Brk成员变量 中
  init_mm.start_code = (unsigned long) &_text;
  init_mm.end_code = (unsigned long) &_etext;
  init_mm.end_data = (unsigned long) &_edata;
  init_mm.brk = (unsigned long) &_end;
  //将1024字节的系统默认命令行字符串全局变量default_command_line复制到系统备份命令行字符全局变量saved_command_line中,[b][/b]
  memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
  saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
  //然后解析default_command_line中的每个命令,系统认识的系统参数设置命令,都有一个对应的 对应的 Struct early_params全局结构变量,变量中定义了命令参数名以及对应的命令解析函数,所有这些Struct early_params全局结构变量都是通过,Early_param()宏定义的,它们被连续放置在Early_param区,一条命令行可以设置多个参数命令,两个参数命令之间只能用空格隔开,参数命令内部不能用空格隔开,同一参数的不同属性用逗号隔开
  parse_cmdline(cmdline_p, from)
  {
  /*
  * Initial parsing of the command line.
  */
  static void __init parse_cmdline(char **cmdline_p, char *from)
  {
  char c = ' ', *to = command_line;
  int len = 0;
  for (;;) {
  if (c == ' ') {
  extern struct early_params __early_begin, __early_end;
  struct early_params *p;
  for (p = &__early_begin; p arg);
  if (memcmp(from, p->arg, len) == 0) {
  if (to != command_line)
  to -= 1;
  from += len;
  p->fn(&from);
  while (*from != ' ' && *from != '\0')
  from++;
  break;
  }
  }
  }
  c = *from++;
  if (!c)
  break;
  if (COMMAND_LINE_SIZE <= ++len)
  break;
  *to++ = c;
  }
  *to = '\0';
  *cmdline_p = command_line;
  }
  };
import idc import ida_bytes import ida_funcs import ida_segment import ida_ida import idautils import ida_name import ida_hexrays import json import struct import sys import traceback from collections import defaultdict # ===== 配置常量 ===== CONFIG = { "MODE": "GENERATE", # "GENERATE" 或 "FIND" "SIG_FILE": "anogs_signatures.json", "PATTERN_LENGTH": 16, "MAX_SEARCH_HITS": 3, "SEARCH_TOLERANCE": 1, # 模糊匹配容错字节数 "DEBUG": False } # ===== 兼容性工具函数 ===== class IDACompat: @staticmethod def get_kernel_version(): """跨版本获取IDA版本""" try: version = ida_ida.get_kernel_version() return f"{version.major}.{version.minor}" except: try: return idc.get_kernel_version() except: return "7.0" @staticmethod def is_code(ea): """检查地址是否为有效代码""" try: if not ida_bytes.is_loaded(ea): return False flags = ida_bytes.get_flags(ea) return ida_bytes.is_code(flags) except: return False @staticmethod def get_func_chunks(func): """获取函数所有代码块(兼容不同版本)""" try: if hasattr(ida_funcs, 'get_func_chunks'): return list(ida_funcs.get_func_chunks(func)) else: return [(func.start_ea, func.end_ea)] except: return [(func.start_ea, func.end_ea)] # ===== 核心搜索引擎 ===== class BinarySearchEngine: def __init__(self, config): self.config = config self.stats = defaultdict(int) def find_pattern(self, start_ea, end_ea, pattern, search_down=True): """增强型二进制搜索(支持模糊匹配)""" if isinstance(pattern, str): try: pattern = bytes.fromhex(pattern.replace(" ", "")) except ValueError: return idc.BADADDR pattern_len = len(pattern) if pattern_len == 0: return idc.BADADDR step = 4 if search_down else -4 current_ea = start_ea hits = 0 best_match = (idc.BADADDR, 0) # (地址, 匹配字节数) while (search_down and current_ea < end_ea) or (not search_down and current_ea > end_ea): try: if not ida_bytes.is_loaded(current_ea): current_ea += step continue # 尝试读取数据 try: data = ida_bytes.get_bytes(current_ea, pattern_len) if data: # 精确匹配检查 if data == pattern: if IDACompat.is_code(current_ea): hits += 1 if hits >= self.config["MAX_SEARCH_HITS"]: return current_ea current_ea += step continue # 模糊匹配检查 mismatch = sum(1 for a, b in zip(data, pattern) if a != b) if mismatch <= self.config["SEARCH_TOLERANCE"]: if IDACompat.is_code(current_ea): best_match = max(best_match, (current_ea, pattern_len - mismatch), key=lambda x: x[1]) except: pass current_ea += step except: current_ea += step continue return best_match[0] if best_match[1] > 0 else idc.BADADDR def find_function_by_hint(self, name, hint_addr): """多阶段函数查找策略""" if not hint_addr or hint_addr == idc.BADADDR: return None # 阶段1: 精确匹配 func = ida_funcs.get_func(hint_addr) if func and func.start_ea == hint_addr and IDACompat.is_code(hint_addr): self.stats["exact_match"] += 1 return hint_addr # 阶段2: 附近匹配(±4字节偏移) for offset in range(-4, 5, 2): ea = hint_addr + offset if IDACompat.is_code(ea): func = ida_funcs.get_func(ea) if func and func.start_ea == ea: self.stats["near_match"] += 1 print(f"?? Warning: {name} found with offset {offset} at 0x{ea:X}") return ea # 阶段3: 函数内包含hint地址 for seg_ea in idautils.Segments(): seg = ida_segment.getseg(seg_ea) if seg and (seg.perm & ida_segment.SEGPERM_EXEC): func_iter = idautils.Functions(seg.start_ea, seg.end_ea) for func_ea in func_iter: func = ida_funcs.get_func(func_ea) if func and func.start_ea <= hint_addr < func.end_ea: self.stats["contained_match"] += 1 print(f"?? Warning: {name} found contained in function at 0x{func.start_ea:X}") return func.start_ea # 阶段4: 特征码辅助定位 fallback_patterns = { "front_back_string_node": ["F0 47 00 D1", "A0 43 00 D1"], "tdm_dev_info": ["1F 20 03 D5", "E0 03 1F 2A"], "info_protection_flash": ["1F 00 00 B9", "1F 01 00 F9"], "case_thread": ["60 00 00 34", "20 01 00 35"] } if name in fallback_patterns: for pattern in fallback_patterns[name]: ea = self.find_pattern(ida_ida.inf_get_min_ea(), ida_ida.inf_get_max_ea(), pattern) if ea != idc.BADADDR: self.stats["pattern_match"] += 1 print(f"?? Warning: {name} found via fallback pattern at 0x{ea:X}") return ea self.stats["failed_match"] += 1 return None # ===== 数据定义 ===== FUNCTIONS = [ ("mrpccs_initialization", 0x249988), ("mrmponi_th_fb_fo", 0x259E48), ("monitor", 0x4BF5BC), ("front_back_string_node", 0x6C7DA0), ("lock_front_back_string_node", 0x262228), ("front_back_validation", 0x24E3E4), ("tdm_dev_info", 0x4BEE370), ("tdm_report", 0x4BEE88), ("Pushantidata3", 0x395AC4), ("memcpy_scanning", 0x2DEC64), ("info_protection_flash", 0x15419C), ("case_thread", 0x1423D8), ("case16", 0x1EB7BC), ("case23", 0x1D17D4), ("case35", 0x2A681C), ("solve_case35", 0x322884), ("case37", 0x1DDCC4), ("case38", 0x1DDE64), ("case47", 0x48D348) ] HINTS = [ {"bytes": "1F 20 03 D5", "desc": "NOP/RET指令"}, {"bytes": "00 00 80 D2", "desc": "MOV X0, #0"}, {"bytes": "E0 03 1F 2A", "desc": "MOV W0, WZR变体"}, {"bytes": "1F 00 00 B9", "desc": "STR WZR, [X0]"}, {"bytes": "1F 01 00 F9", "desc": "STR XZR, [X8]"}, {"bytes": "60 00 00 34", "desc": "CBZ W0, offset"}, {"bytes": "20 01 00 35", "desc": "CBNZ W0, offset"}, {"bytes": "10 00 00 14", "desc": "B指令"}, {"bytes": "4A 00 40 39", "desc": "LDRB W10, [X19]"} ] # ===== 主处理类 ===== class SignatureProcessor: def __init__(self, config): self.config = config self.engine = BinarySearchEngine(config) self.min_ea = ida_ida.inf_get_min_ea() self.max_ea = ida_ida.inf_get_max_ea() def generate_signatures(self): """生成签名数据""" data = { "functions": [], "hints": [], "metadata": { "ida_version": IDACompat.get_kernel_version(), "timestamp": idc.get_current_timestamp(), "input_hash": self._calculate_input_hash() }, "segments": self._collect_segment_info() } # 处理函数签名 print("\n?? Generating function signatures...") for name, hint_addr in FUNCTIONS: addr = self.engine.find_function_by_hint(name, hint_addr) if not addr: print(f"?? NOT FOUND: {name} (hint: 0x{hint_addr:X})") continue func = ida_funcs.get_func(addr) if not func: print(f"?? INVALID FUNCTION: {name} at 0x{addr:X}") continue try: # 获取函数上下文 context_start = max(func.start_ea - 8, self.min_ea) prologue = ida_bytes.get_bytes(context_start, 16) body = ida_bytes.get_bytes(func.start_ea, min(32, func.end_ea - func.start_ea)) # 获取调用引用(增强可靠性) xrefs = list(idautils.XrefsTo(addr)) data["functions"].append({ "name": name, "hint_address": hint_addr, "address": addr, "prologue": prologue.hex(), "body_sample": body.hex(), "size": func.end_ea - func.start_ea, "xrefs": [x.frm for x in xrefs[:5]], # 最多记录5个引用 "chunks": [{"start": s, "end": e} for s, e in IDACompat.get_func_chunks(func)] }) print(f"? GENERATED: {name} -> 0x{addr:X}") except Exception as e: print(f"?? ERROR PROCESSING: {name} - {str(e)}") if self.config["DEBUG"]: traceback.print_exc() # 处理行为特征 print("\n?? Searching for behavioral hints...") for hint in HINTS: ea = self.engine.find_pattern(self.min_ea, self.max_ea, hint["bytes"]) if ea != idc.BADADDR: data["hints"].append({ "description": hint["desc"], "address": ea, "pattern": hint["bytes"].replace(" ", ""), "disasm": self._get_disassembly(ea) }) print(f"? FOUND: '{hint['desc']}' at 0x{ea:X}") # 保存结果 try: with open(self.config["SIG_FILE"], "w") as f: json.dump(data, f, indent=2) print(f"\n?? Successfully saved signatures to {self.config['SIG_FILE']}") self._print_stats() return True except IOError as e: print(f"?? ERROR: Failed to save signature file - {str(e)}") return False def find_signatures(self): """查找签名匹配""" try: with open(self.config["SIG_FILE"], "r") as f: data = json.load(f) except (FileNotFoundError, json.JSONDecodeError) as e: print(f"?? ERROR: Failed to load signature file - {str(e)}") return False results = {"functions": {}, "hints": {}} # 验证签名文件 if not self._validate_signature_data(data): return False # 查找函数 print("\n?? Locating functions...") for func in data.get("functions", []): try: pattern = bytes.fromhex(func["prologue"][:16]) # 使用前导字节 ea = self.engine.find_pattern(self.min_ea, self.max_ea, pattern) if ea != idc.BADADDR: f = ida_funcs.get_func(ea) if f and f.start_ea == ea: results["functions"][func["name"]] = { "address": ea, "confidence": self._calculate_match_confidence(func, ea) } print(f"? FOUND: {func['name']} -> 0x{ea:X}") continue print(f"?? NOT FOUND: {func['name']}") except Exception as e: print(f"?? ERROR PROCESSING: {func.get('name', 'unknown')} - {str(e)}") # 匹配行为特征 print("\n?? Matching behavioral hints...") for hint in data.get("hints", []): try: ea = self.engine.find_pattern(self.min_ea, self.max_ea, hint["pattern"]) if ea != idc.BADADDR: results["hints"][hint["description"]] = ea print(f"? MATCHED: '{hint['description']}' at 0x{ea:X}") else: print(f"?? MISSING: '{hint['description']}'") except Exception as e: print(f"?? ERROR PROCESSING HINT: {hint.get('description', 'unknown')}") # 显示结果 self._display_find_results(results) return True def _calculate_input_hash(self): """计算输入文件哈希(用于验证)""" try: import hashlib md5 = hashlib.md5() with open(idc.get_input_file_path(), "rb") as f: while chunk := f.read(8192): md5.update(chunk) return md5.hexdigest() except: return "unknown" def _collect_segment_info(self): """收集段信息""" segments = [] for seg_ea in idautils.Segments(): seg = ida_segment.getseg(seg_ea) if seg: segments.append({ "start": seg.start_ea, "end": seg.end_ea, "name": ida_segment.get_segm_name(seg), "permissions": seg.perm, "bitness": 64 if seg.is_64bit() else 32, "type": "code" if (seg.perm & ida_segment.SEGPERM_EXEC) else "data" }) return segments def _get_disassembly(self, ea): """获取反汇编文本""" try: return idc.GetDisasm(ea) except: return "unknown" def _validate_signature_data(self, data): """验证签名数据有效性""" required_keys = ["functions", "hints", "metadata"] if not all(k in data for k in required_keys): print("?? ERROR: Invalid signature file format") return False # 版本兼容性检查 sig_version = data["metadata"].get("ida_version", "7.0") current_version = IDACompat.get_kernel_version() if sig_version.split(".")[0] != current_version.split(".")[0]: print(f"?? Warning: Signature created with IDA {sig_version}, running on {current_version}") return True def _calculate_match_confidence(self, func_data, found_ea): """计算匹配置信度(0-100)""" confidence = 50 # 基础分 # 地址精确匹配 if func_data["address"] == found_ea: confidence += 30 # 引用点匹配 xrefs = list(idautils.XrefsTo(found_ea)) common_xrefs = set(func_data.get("xrefs", [])) & set(x.frm for x in xrefs) confidence += min(10, len(common_xrefs) * 2) # 函数大小匹配 func = ida_funcs.get_func(found_ea) if func: size_ratio = min(1.0, func_data["size"] / (func.end_ea - func.start_ea)) confidence += int(size_ratio * 10) return min(100, confidence) def _print_stats(self): """打印处理统计信息""" print("\n?? Processing Statistics:") for k, v in self.engine.stats.items(): print(f"?? {k.replace('_', ' ').title()}: {v}") total_funcs = len(FUNCTIONS) found_funcs = total_funcs - self.engine.stats["failed_match"] print(f"?? Function Success Rate: {found_funcs}/{total_funcs} ({found_funcs/total_funcs*100:.1f}%)") def _display_find_results(self, results): """显示查找结果""" print("\n?? Search Results Summary:") print(f"?? Functions found: {len(results['functions'])}/{len(FUNCTIONS)}") for name, data in results["functions"].items(): print(f"?? {name}: 0x{data['address']:X} (Confidence: {data['confidence']}%)") print(f"?? Hints matched: {len(results['hints'])}/{len(HINTS)}") for desc, addr in results["hints"].items(): print(f"?? {desc}: 0x{addr:X}") # ===== 主程序入口 ===== def main(): print(f"?? IDA Signature Tool v2.0 (IDA {IDACompat.get_kernel_version()})") print(f"?? Mode: {CONFIG['MODE']}") try: processor = SignatureProcessor(CONFIG) if CONFIG["MODE"] == "GENERATE": return processor.generate_signatures() elif CONFIG["MODE"] == "FIND": return processor.find_signatures() else: print("?? Error: Invalid mode. Use 'GENERATE' or 'FIND'") return False except Exception as e: print(f"?? FATAL ERROR: {str(e)}") if CONFIG["DEBUG"]: traceback.print_exc() return False if __name__ == "__main__": try: if not main(): sys.exit(1) except Exception as e: print(f"?? UNHANDLED EXCEPTION: {str(e)}") sys.exit(1)
11-17
import tkinter as tk import time import sys import os import platform import ctypes import csv import threading import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from ctypes import windll, wintypes from collections import defaultdict from datetime import datetime # 解决中文警告问题 import matplotlib as mpl mpl.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] # 指定默认字体 mpl.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 class HighPrecisionTimer: """高精度计时器基类""" def __init__(self): self.start_time = 0 self.total_elapsed = 0 self.running = False self.interrupt_count = 0 # 中断计数器 self.core_usage = defaultdict(float) # 各核心使用时间 def start(self): """开始计时""" if not self.running: self.start_time = self.current_time() self.running = True def stop(self): """停止计时""" if self.running: elapsed = self.current_time() - self.start_time self.total_elapsed += elapsed self.update_core_usage(elapsed) # 更新核心使用情况 self.running = False def reset(self): """重置计时器""" self.total_elapsed = 0 self.running = False self.interrupt_count = 0 self.core_usage.clear() def current_elapsed(self): """获取当前已过时间(毫秒)""" if self.running: return self.total_elapsed + (self.current_time() - self.start_time) return self.total_elapsed def current_time(self): """抽象方法,由子类实现具体计时方案""" raise NotImplementedError("Subclasses must implement current_time()") def update_core_usage(self, elapsed): """更新核心使用情况""" # 此处为简化实现,实际项目中应使用系统API获取各核心使用数据 if platform.system() == 'Windows': # 模拟多核使用情况 for core in range(os.cpu_count()): self.core_usage[core] += elapsed * (0.3 + 0.6 * np.random.random()) else: # Linux系统可读取/proc/stat获取实际数据 self.core_usage[0] = elapsed # 默认单核心 def get_cpu_utilization(self, physical_time): if physical_time > 0: return min(100, max(0, (self.current_elapsed() / physical_time) * 100)) return 0 def record_interrupt(self): """记录中断事件""" self.interrupt_count += 1 class PerformanceCounterTimer(HighPrecisionTimer): """基于性能计数器的物理计时方案""" def __init__(self): super().__init__() # 获取性能计数器频率 if platform.system() == 'Windows': self.frequency = ctypes.c_int64() windll.kernel32.QueryPerformanceFrequency(ctypes.byref(self.frequency)) self.frequency = self.frequency.value else: # Linux/macOS使用time.perf_counter self.frequency = 1e9 # 1秒 = 1e9纳秒 def current_time(self): """获取当前性能计数器时间(毫秒)""" if platform.system() == 'Windows': counter = ctypes.c_int64() windll.kernel32.QueryPerformanceCounter(ctypes.byref(counter)) return (counter.value * 1000) / self.frequency # 转换为毫秒 else: # 跨平台方案 return time.perf_counter() * 1000 class CPUCycleTimer(HighPrecisionTimer): """基于CPU周期的计时方案""" def __init__(self): super().__init__() # 获取CPU频率 self.frequency = self.get_cpu_frequency() self.power_model = self.create_power_model() # 创建功耗模型 def get_cpu_frequency(self): """尝试获取CPU频率""" try: if platform.system() == 'Windows': # Windows获取CPU频率 import winreg key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"HARDWARE\DESCRIPTION\System\CentralProcessor\0") value, _ = winreg.QueryValueEx(key, "~MHz") winreg.CloseKey(key) return value * 1e6 # MHz转换为Hz else: # Linux/macOS获取CPU频率 with open('/proc/cpuinfo') as f: for line in f: if 'cpu MHz' in line: return float(line.split(':')[1].strip()) * 1e6 # 默认值 return 3.5e9 # 3.5 GHz except: return 3.5e9 # 3.5 GHz def current_time(self): """获取当前CPU周期计数并转换为毫秒""" if platform.system() == 'Windows': return time.perf_counter_ns() / 1_000_000 # 返回毫秒级精确时间 else: # 在实际应用中应使用RDTSC指令 return time.process_time() * 1000 def create_power_model(self): # 简化的线性模型: P = a * utilization + b return lambda u: 15 + 85 * (u/100) # 基础功耗15W + 动态功耗 def estimate_energy(self, physical_time): utilization = self.get_cpu_utilization(physical_time) power = self.power_model(utilization) # 当前功耗(W) time_seconds = physical_time / 1000 # 转换为秒 return power * time_seconds # 能耗(J) class TimerApp: """计时器应用GUI""" def __init__(self, root): self.root = root root.title("高精度计时器 - 专业版") root.geometry("800x600") root.resizable(True, True) # 创建两种计时器实例 self.performance_timer = PerformanceCounterTimer() self.cpu_cycle_timer = CPUCycleTimer() # 当前选中的计时方案 self.current_timer = self.performance_timer self.interrupt_monitor_running = False # 创建UI self.create_widgets() # 性能优化计数器 self.update_count = 0 # 启动UI更新循环 self.update_display() # 启动中断监控线程 self.start_interrupt_monitor() def create_widgets(self): """创建界面组件""" # 主框架 main_frame = tk.Frame(self.root) main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 左侧控制面板 control_frame = tk.Frame(main_frame) control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5) # 方案选择 mode_frame = tk.LabelFrame(control_frame, text="计时方案", padx=10, pady=10) mode_frame.pack(fill=tk.X, pady=5) self.mode_var = tk.StringVar(value="performance") modes = [("性能计数器 (物理时间)", "performance"), ("CPU周期 (CPU时间)", "cpu")] for text, mode in modes: rb = tk.Radiobutton(mode_frame, text=text, variable=self.mode_var, value=mode, command=self.switch_mode) rb.pack(anchor=tk.W, padx=5, pady=2) # 控制按钮 btn_frame = tk.Frame(control_frame) btn_frame.pack(fill=tk.X, pady=10) self.start_btn = tk.Button(btn_frame, text="开始", width=12, command=self.start_stop) self.start_btn.pack(side=tk.LEFT, padx=5) reset_btn = tk.Button(btn_frame, text="重置", width=12, command=self.reset) reset_btn.pack(side=tk.LEFT, padx=5) # 统计按钮 stats_btn = tk.Button(btn_frame, text="生成报告", width=12, command=self.generate_report) stats_btn.pack(side=tk.LEFT, padx=5) # CPU信息 info_frame = tk.LabelFrame(control_frame, text="系统信息", padx=10, pady=10) info_frame.pack(fill=tk.X, pady=5) cpu_freq = self.cpu_cycle_timer.frequency freq_text = f"CPU频率: {cpu_freq/1e9:.2f} GHz" if cpu_freq >= 1e9 else f"CPU频率: {cpu_freq/1e6:.0f} MHz" self.cpu_label = tk.Label(info_frame, text=freq_text, justify=tk.LEFT) self.cpu_label.pack(anchor=tk.W) cores_text = f"CPU核心数: {os.cpu_count()}" tk.Label(info_frame, text=cores_text, justify=tk.LEFT).pack(anchor=tk.W) # 中断统计 interrupt_frame = tk.LabelFrame(control_frame, text="中断统计", padx=10, pady=10) interrupt_frame.pack(fill=tk.X, pady=5) self.interrupt_label = tk.Label(interrupt_frame, text="中断次数: 0") self.interrupt_label.pack(anchor=tk.W) # 右侧数据显示 display_frame = tk.Frame(main_frame) display_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5) # 双模式时间显示 time_frame = tk.LabelFrame(display_frame, text="时间对比", padx=10, pady=10) time_frame.pack(fill=tk.X, pady=5) # 物理时间显示 - 添加颜色(蓝色) physical_frame = tk.Frame(time_frame) physical_frame.pack(fill=tk.X, pady=5) tk.Label(physical_frame, text="物理时间:", width=10).pack(side=tk.LEFT) self.physical_label = tk.Label(physical_frame, text="00:00:00.000", font=("Consolas", 12), fg="blue") self.physical_label.pack(side=tk.LEFT) # CPU时间显示 - 添加颜色(红色) cpu_frame = tk.Frame(time_frame) cpu_frame.pack(fill=tk.X, pady=5) tk.Label(cpu_frame, text="CPU时间:", width=10).pack(side=tk.LEFT) self.cpu_time_label = tk.Label(cpu_frame, text="00:00:00.000", font=("Consolas", 12), fg="red") self.cpu_time_label.pack(side=tk.LEFT) # 时间分解分析 analysis_frame = tk.LabelFrame(display_frame, text="时间分解分析", padx=10, pady=10) analysis_frame.pack(fill=tk.X, pady=5) # CPU利用率 - 添加颜色(绿色) util_frame = tk.Frame(analysis_frame) util_frame.pack(fill=tk.X, pady=2) tk.Label(util_frame, text="CPU利用率:", width=15).pack(side=tk.LEFT) self.util_label = tk.Label(util_frame, text="0.0%", fg="green") self.util_label.pack(side=tk.LEFT) # 系统等待时间 - 添加颜色(紫色) wait_frame = tk.Frame(analysis_frame) wait_frame.pack(fill=tk.X, pady=2) tk.Label(wait_frame, text="系统等待时间:", width=15).pack(side=tk.LEFT) self.wait_label = tk.Label(wait_frame, text="0.0 ms", fg="purple") self.wait_label.pack(side=tk.LEFT) # 能耗估算 - 添加颜色(橙色) energy_frame = tk.Frame(analysis_frame) energy_frame.pack(fill=tk.X, pady=2) tk.Label(energy_frame, text="能耗估算:", width=15).pack(side=tk.LEFT) self.energy_label = tk.Label(energy_frame, text="0.0 J", fg="orange") self.energy_label.pack(side=tk.LEFT) # 多核热力图 heatmap_frame = tk.LabelFrame(display_frame, text="多核利用率热力图", padx=10, pady=10) heatmap_frame.pack(fill=tk.BOTH, expand=True, pady=5) # 创建热力图 self.figure, self.ax = plt.subplots(figsize=(6, 3)) self.canvas = FigureCanvasTkAgg(self.figure, heatmap_frame) self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) # 初始化热力图对象 self.heatmap_img = None self.heatmap_texts = [] # 初始化热力图 self.init_heatmap() def init_heatmap(self): """初始化热力图对象""" cores = list(range(os.cpu_count())) util = [0] * len(cores) # 创建热力图数据 data = np.array(util).reshape(1, -1) # 创建图像对象 self.heatmap_img = self.ax.imshow(data, cmap='viridis', aspect='auto', vmin=0, vmax=100) # 创建文本标注 self.heatmap_texts = [] for i in range(len(cores)): text = self.ax.text(i, 0, f'{util[i]:.1f}%', ha='center', va='center', color='w') self.heatmap_texts.append(text) self.ax.set_title('CPU核心利用率 (%)') self.ax.set_xticks(range(len(cores))) self.ax.set_xticklabels([f'Core {core}' for core in cores]) self.ax.get_yaxis().set_visible(False) # 添加颜色条(只创建一次) self.figure.colorbar(self.heatmap_img, ax=self.ax) self.canvas.draw() def switch_mode(self): """切换计时方案""" selected = self.mode_var.get() if selected == "performance": self.current_timer = self.performance_timer else: self.current_timer = self.cpu_cycle_timer # 更新CPU频率显示 cpu_freq = self.cpu_cycle_timer.frequency freq_text = f"CPU频率: {cpu_freq/1e9:.2f} GHz" if cpu_freq >= 1e9 else f"CPU频率: {cpu_freq/1e6:.0f} MHz" self.cpu_label.config(text=freq_text) def start_stop(self): """开始/停止计时""" if self.current_timer.running: self.current_timer.stop() self.start_btn.config(text="开始") else: self.performance_timer.start() self.cpu_cycle_timer.start() self.start_btn.config(text="停止") def reset(self): """重置计时器""" self.performance_timer.reset() self.cpu_cycle_timer.reset() self.physical_label.config(text="00:00:00.000") self.cpu_time_label.config(text="00:00:00.000") self.util_label.config(text="0.0%") self.wait_label.config(text="0.0 ms") self.energy_label.config(text="0.0 J") self.interrupt_label.config(text="中断次数: 0") self.start_btn.config(text="开始") # 重置热力图 cores = list(range(os.cpu_count())) util = [0] * len(cores) self.update_heatmap(cores, util) def update_heatmap(self, cores, util): """高效更新热力图""" # 更新图像数据 data = np.array(util).reshape(1, -1) if self.heatmap_img is not None: self.heatmap_img.set_data(data) # 更新文本标注 for i, text in enumerate(self.heatmap_texts): text.set_text(f'{util[i]:.1f}%') # 只绘制变更部分 self.canvas.draw_idle() def start_interrupt_monitor(self): """启动中断监控线程""" if not self.interrupt_monitor_running: self.interrupt_monitor_running = True threading.Thread(target=self.monitor_interrupts, daemon=True).start() def monitor_interrupts(self): """模拟中断监控""" while self.interrupt_monitor_running: time.sleep(0.1) # 在实际应用中,这里应读取系统中断计数器 if self.current_timer.running: # 模拟随机中断 if np.random.random() < 0.02: # 2%概率发生中断 self.performance_timer.record_interrupt() self.cpu_cycle_timer.record_interrupt() self.root.after(0, self.update_interrupt_count) def update_interrupt_count(self): """更新中断计数显示""" count = self.performance_timer.interrupt_count self.interrupt_label.config(text=f"中断次数: {count}") def generate_report(self): """生成详细分析报告""" filename = f"timer_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" with open(filename, 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) # 写入报告头部信息 writer.writerow(["高精度计时器分析报告"]) writer.writerow(["生成时间", datetime.now().strftime("%Y-%m-%d %H:%M:%S")]) writer.writerow([]) # 写入系统信息 writer.writerow(["系统信息"]) writer.writerow(["操作系统", platform.platform()]) writer.writerow(["CPU核心数", os.cpu_count()]) cpu_freq = self.cpu_cycle_timer.frequency freq_text = f"{cpu_freq/1e9:.2f} GHz" if cpu_freq >= 1e9 else f"{cpu_freq/1e6:.0f} MHz" writer.writerow(["CPU频率", freq_text]) writer.writerow(["Python版本", sys.version]) writer.writerow([]) # 格式化时间函数 def format_ms(ms): hours, rem = divmod(ms, 3600000) minutes, rem = divmod(rem, 60000) seconds, milliseconds = divmod(rem, 1000) return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}.{int(milliseconds):03d}" # 写入时间指标 physical_time = self.performance_timer.total_elapsed cpu_time = self.cpu_cycle_timer.total_elapsed wait_time = max(0, physical_time - cpu_time) # 系统等待时间 writer.writerow(["时间指标"]) writer.writerow(["度量项", "数值(毫秒)", "格式化时间"]) writer.writerow(["物理时间", f"{physical_time:.3f}", format_ms(physical_time)]) writer.writerow(["CPU时间", f"{cpu_time:.3f}", format_ms(cpu_time)]) writer.writerow(["系统等待时间", f"{wait_time:.3f}", format_ms(wait_time)]) writer.writerow([]) # 写入性能指标 utilization = self.cpu_cycle_timer.get_cpu_utilization(physical_time) if physical_time > 0 else 0 energy = self.cpu_cycle_timer.estimate_energy(physical_time) if physical_time > 0 else 0 writer.writerow(["性能指标"]) writer.writerow(["CPU利用率", f"{utilization:.2f}%"]) writer.writerow(["系统中断次数", self.performance_timer.interrupt_count]) writer.writerow(["估算能耗", f"{energy:.2f} J"]) writer.writerow([]) # 写入多核分析 writer.writerow(["多核利用率分析"]) writer.writerow(["核心ID", "使用时间(毫秒)", "占比"]) # 计算核心使用占比 cores = sorted(self.cpu_cycle_timer.core_usage.keys()) total_cpu_time = max(1, cpu_time) # 防止除零 for core in cores: core_time = self.cpu_cycle_timer.core_usage.get(core, 0) percentage = (core_time / total_cpu_time) * 100 writer.writerow([f"Core {core}", f"{core_time:.3f}", f"{percentage:.2f}%"]) # 添加数学公式注解 writer.writerow([]) writer.writerow(["计算公式注解"]) writer.writerow(["CPU利用率", r"$\eta = \frac{T_{cpu}}{T_{physical}} \times 100\%$"]) writer.writerow(["系统等待时间", r"$\Delta t = T_{physical} - T_{cpu}$"]) writer.writerow(["能耗估算", r"$E = \int_{0}^{T} P(u(t)) \, dt$", "(P=功耗模型)"]) # 显示成功消息 tk.messagebox.showinfo("报告生成", f"分析报告已保存至:\n{os.path.abspath(filename)}") def update_display(self): """高效更新UI显示(优化性能)""" physical_ms = self.performance_timer.current_elapsed() cpu_ms = self.cpu_cycle_timer.current_elapsed() # 格式化时间为 HH:MM:SS.ms physical_str = self.ms_to_time_str(physical_ms) cpu_str = self.ms_to_time_str(cpu_ms) # 更新标签显示(使用高效更新方法) self.physical_label.config(text=physical_str) self.cpu_time_label.config(text=cpu_str) # 计算性能指标 utilization = self.cpu_cycle_timer.get_cpu_utilization(physical_ms) if physical_ms > 0 else 0 wait_time = max(0, physical_ms - cpu_ms) # 系统等待时间 energy = self.cpu_cycle_timer.estimate_energy(physical_ms) if physical_ms > 0 else 0 # 更新性能指标显示 self.util_label.config(text=f"{utilization:.1f}%") self.wait_label.config(text=f"{wait_time:.1f} ms") self.energy_label.config(text=f"{energy:.1f} J") # 每10次更新才刷新一次热力图(性能优化) self.update_count += 1 if self.update_count % 10 == 0 or not self.performance_timer.running: cores = sorted(self.cpu_cycle_timer.core_usage.keys()) if not cores: cores = list(range(os.cpu_count())) util = [0] * len(cores) else: total_time = max(1, self.cpu_cycle_timer.total_elapsed) util = [self.cpu_cycle_timer.core_usage[core] / total_time * 100 for core in cores] # 高效更新热力图 self.update_heatmap(cores, util) # 每100毫秒更新一次显示(采用动态更新间隔) update_interval = 100 if self.performance_timer.running else 500 self.root.after(update_interval, self.update_display) def ms_to_time_str(self, ms): """将毫秒数格式化为 HH:MM:SS.ms 字符串""" ms = max(0, ms) # 确保非负 seconds, milliseconds = divmod(ms, 1000) minutes, seconds = divmod(seconds, 60) hours, minutes = divmod(minutes, 60) return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}.{int(milliseconds):03d}" def update_heatmap(self, cores, util): """高效更新热力图(优化性能)""" # 创建热力图数据 data = np.array(util).reshape(1, -1) if hasattr(self, 'heatmap_img'): # 更新现有图像数据 self.heatmap_img.set_data(data) # 更新文本标注 for i, text in enumerate(self.heatmap_texts[:len(cores)]): text.set_text(f'{util[i]:.1f}%') else: # 首次创建热力图 self.heatmap_img = self.ax.imshow(data, cmap='viridis', aspect='auto', vmin=0, vmax=100) # 创建文本标注 self.heatmap_texts = [] for i in range(len(cores)): text = self.ax.text(i, 0, f'{util[i]:.1f}%', ha='center', va='center', color='w') self.heatmap_texts.append(text) self.ax.set_title('CPU核心利用率 (%)') self.ax.set_xticks(range(len(cores))) self.ax.set_xticklabels([f'Core {core}' for core in cores]) self.ax.get_yaxis().set_visible(False) self.figure.colorbar(self.heatmap_img, ax=self.ax) # 只绘制变更部分(性能优化) self.canvas.draw_idle() def __del__(self): """清理资源""" self.interrupt_monitor_running = False if __name__ == "__main__": root = tk.Tk() app = TimerApp(root) try: root.mainloop() finally: # 确保线程安全退出 app.interrupt_monitor_running = False 那这个代码中,选择计时方案还有什么意义吗?只要点击开始,两个都会开始计时,选择计时方案没有意义。而且感觉很多东西都没有意义
10-14
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值