diff --git a/afl-gotcpu.c b/afl-gotcpu.c index 630b7ff..6281afe 100644 --- a/afl-gotcpu.c +++ b/afl-gotcpu.c @@ -1,35 +1,29 @@ -/* - Copyright 2015 Google LLC All rights reserved. +/* + 版权所有 2015 Google LLC 保留所有权利。 - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: + 根据Apache License, 版本2.0(“许可证”)授权; + 除非遵守许可证,否则不得使用此文件。 + 您可以在以下网址获得许可证的副本: http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. + 除非适用法律要求或书面同意,否则按照许可证分发的软件是基于“原样”分发的基础上进行的, + 不提供任何明示或暗示的保证或条件。 + 请参阅许可证,了解许可证下的具体语言,以了解权限和限制。 */ -/* - american fuzzy lop - free CPU gizmo +/* + 美国模糊跳 - 免费CPU小工具 ----------------------------------- - Written and maintained by Michal Zalewski + 由Michal Zalewski 编写和维护 - This tool provides a fairly accurate measurement of CPU preemption rate. - It is meant to complement the quick-and-dirty load average widget shown - in the afl-fuzz UI. See docs/parallel_fuzzing.txt for more info. + 这个工具提供了一个相当准确的CPU抢占率测量。 + 它旨在补充afl-fuzz UI中显示的快速且粗略的负载平均小部件。更多信息请参见docs/parallel_fuzzing.txt。 - For some work loads, the tool may actually suggest running more instances - than you have CPU cores. This can happen if the tested program is spending - a portion of its run time waiting for I/O, rather than being 100% - CPU-bound. + 对于一些工作负载,该工具实际上可能建议您运行的实例数量超过您拥有的CPU核心数。如果被测试的程序在其运行时间中花费了一部分时间等待I/O,而不是100% CPU绑定,这种情况可能会发生。 - The idea for the getrusage()-based approach comes from Jakub Wilk. + 基于getrusage()的方法的想法来自Jakub Wilk。 */ #define AFL_MAIN @@ -55,119 +49,151 @@ #endif /* __linux__ */ -/* Get unix time in microseconds. */ +/* + 获取以微秒为单位的Unix时间。 +*/ static u64 get_cur_time_us(void) { - + // 定义一个timeval结构体变量tv,用于存储当前时间 struct timeval tv; + // 定义一个timezone结构体变量tz,用于存储时区信息 struct timezone tz; + // 使用gettimeofday函数获取当前时间,并存储到tv和tz中 gettimeofday(&tv, &tz); + // 将秒转换为微秒,并加上微秒部分,返回当前时间的微秒值 return (tv.tv_sec * 1000000ULL) + tv.tv_usec; - } - -/* Get CPU usage in microseconds. */ +/* + 获取CPU使用时间,以微秒为单位。 +*/ static u64 get_cpu_usage_us(void) { - + // 定义一个rusage结构体变量u,用于存储资源使用情况 struct rusage u; + // 使用getrusage函数获取当前进程的资源使用情况,并存储到u中 getrusage(RUSAGE_SELF, &u); + // 计算用户态和核心态的总使用时间(微秒),并返回 return (u.ru_utime.tv_sec * 1000000ULL) + u.ru_utime.tv_usec + (u.ru_stime.tv_sec * 1000000ULL) + u.ru_stime.tv_usec; - } -/* Measure preemption rate. */ +/* + 测量抢占率。 +*/ static u32 measure_preemption(u32 target_ms) { - + // 定义两个易失性变量,用于循环测试 static volatile u32 v1, v2; + // 定义变量用于存储开始和结束的时间(微秒),以及CPU使用时间 u64 st_t, en_t, st_c, en_c, real_delta, slice_delta; + // 定义循环重复次数 s32 loop_repeats = 0; + // 获取当前时间(微秒) st_t = get_cur_time_us(); + // 获取当前CPU使用时间(微秒) st_c = get_cpu_usage_us(); repeat_loop: - + // 设置v1为一个忙循环的计数 v1 = CTEST_BUSY_CYCLES; + // 执行忙循环,同时v2自增 while (v1--) v2++; + // 调用sched_yield(),让出CPU sched_yield(); + // 再次获取当前时间(微秒) en_t = get_cur_time_us(); + // 如果当前时间与开始时间的差小于目标时间(毫秒转换为微秒),则增加循环次数并继续循环 if (en_t - st_t < target_ms * 1000) { loop_repeats++; goto repeat_loop; } - /* Let's see what percentage of this time we actually had a chance to - run, and how much time was spent in the penalty box. */ + /* 让我们看看这段时间里我们实际上有多少百分比的机会运行, + 以及在惩罚箱中花费了多少时间。 */ + // 获取当前CPU使用时间(微秒) en_c = get_cpu_usage_us(); + // 计算实际时间差(毫秒)和CPU使用时间差(毫秒) real_delta = (en_t - st_t) / 1000; slice_delta = (en_c - st_c) / 1000; + // 返回实际时间差占CPU使用时间差的百分比,即抢占率 return real_delta * 100 / slice_delta; - } - -/* Do the benchmark thing. */ +/* + 执行基准测试。 +*/ int main(int argc, char** argv) { #ifdef HAVE_AFFINITY + // 获取在线的CPU核心数 u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN), + // 初始化空闲CPU和可能可用CPU的计数器 idle_cpus = 0, maybe_cpus = 0, i; + // 打印欢迎信息和版本号 SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by \n"); + // 打印测量每个核心抢占率所需的时间 ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...", ((double)CTEST_CORE_TRG_MS) / 1000); + // 遍历每个CPU核心 for (i = 0; i < cpu_cnt; i++) { + // 创建子进程 s32 fr = fork(); + // 如果fork失败,则打印错误信息并退出 if (fr < 0) PFATAL("fork failed"); + // 如果是子进程,则执行以下操作 if (!fr) { + // 定义CPU集合 cpu_set_t c; + // 定义CPU使用率百分比 u32 util_perc; + // 初始化CPU集合 CPU_ZERO(&c); + // 将当前核心加入CPU集合 CPU_SET(i, &c); + // 如果设置CPU亲和性失败,则打印错误信息并退出 if (sched_setaffinity(0, sizeof(c), &c)) PFATAL("sched_setaffinity failed for cpu %d", i); + // 测量抢占率 util_perc = measure_preemption(CTEST_CORE_TRG_MS); + // 如果使用率低于110%,则标记为核心可用,并退出 if (util_perc < 110) { - - SAYF(" Core #%u: " cLGN "AVAILABLE " cRST "(%u%%)\n", i, util_perc); + SAYF(" Core #%u: " cLGN "AVAILABLE" cRST "(%u%%)\n", i, util_perc); exit(0); - } else if (util_perc < 250) { - - SAYF(" Core #%u: " cYEL "CAUTION " cRST "(%u%%)\n", i, util_perc); + // 如果使用率低于250%,则标记为核心需要谨慎,并退出 + SAYF(" Core #%u: " cYEL "CAUTION" cRST "(%u%%)\n", i, util_perc); exit(1); - } - SAYF(" Core #%u: " cLRD "OVERBOOKED " cRST "(%u%%)\n" cRST, i, + // 如果使用率高于250%,则标记为核心过载,并退出 + SAYF(" Core #%u: " cLRD "OVERBOOKED" cRST "(%u%%)\n" cRST, i, util_perc); exit(2); @@ -175,44 +201,35 @@ int main(int argc, char** argv) { } + // 等待子进程结束,并统计空闲和可能可用的核心数 for (i = 0; i < cpu_cnt; i++) { - int ret; if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); if (WEXITSTATUS(ret) == 0) idle_cpus++; if (WEXITSTATUS(ret) <= 1) maybe_cpus++; - } + // 根据空闲和可能可用的核心数打印结果 SAYF(cGRA "\n>>> "); if (idle_cpus) { - if (maybe_cpus == idle_cpus) { - SAYF(cLGN "PASS: " cRST "You can run more processes on %u core%s.", idle_cpus, idle_cpus > 1 ? "s" : ""); - } else { - SAYF(cLGN "PASS: " cRST "You can run more processes on %u to %u core%s.", idle_cpus, maybe_cpus, maybe_cpus > 1 ? "s" : ""); - } - SAYF(cGRA " <<<" cRST "\n\n"); return 0; - } if (maybe_cpus) { - SAYF(cYEL "CAUTION: " cRST "You may still have %u core%s available.", maybe_cpus, maybe_cpus > 1 ? "s" : ""); SAYF(cGRA " <<<" cRST "\n\n"); return 1; - } SAYF(cLRD "FAIL: " cRST "All cores are overbooked."); @@ -221,38 +238,35 @@ int main(int argc, char** argv) { #else + // 如果没有CPU亲和性支持,则执行总体抢占率的测量 u32 util_perc; SAYF(cCYA "afl-gotcpu " cBRI VERSION cRST " by \n"); - /* Run a busy loop for CTEST_TARGET_MS. */ + /* 运行一个忙循环,持续CTEST_TARGET_MS毫秒。 */ ACTF("Measuring gross preemption rate (this will take %0.02f sec)...", ((double)CTEST_TARGET_MS) / 1000); + // 测量抢占率 util_perc = measure_preemption(CTEST_TARGET_MS); - /* Deliver the final verdict. */ + /* 输出最终结果。 */ SAYF(cGRA "\n>>> "); if (util_perc < 105) { - SAYF(cLGN "PASS: " cRST "You can probably run additional processes."); - } else if (util_perc < 130) { - SAYF(cYEL "CAUTION: " cRST "Your CPU may be somewhat overbooked (%u%%).", util_perc); - } else { - SAYF(cLRD "FAIL: " cRST "Your CPU is overbooked (%u%%).", util_perc); - } SAYF(cGRA " <<<" cRST "\n\n"); + // 返回结果代码 return (util_perc > 105) + (util_perc > 130); #endif /* ^HAVE_AFFINITY */