TaskScheduler 是一个Linux 环境下的高性能任务调度系统,支持资源管理、任务队列、超时控制、eBPF 性能分析和 Prometheus 监控。
核心功能:
- ✅ 多线程任务调度(生产者-消费者模型)
- ✅ CPU/内存资源配额管理(线程安全)
- ✅ 优先级队列 + FIFO 双模式
- ✅ 进程生命周期管理(fork/exec、进程组、信号)
- ✅ 优雅终止(SIGTERM → 宽限期 → SIGKILL)
- ✅ eBPF 性能分析(bpftrace + 火焰图)
- ✅ Prometheus 指标导出
- ✅ 黑白名单安全控制
- ✅ PSI 背压监控
这个项目涵盖的知识将直接应用于:
- 云原生基础设施(Kubernetes调度器)
- 大数据平台(YARN、Mesos)
- 高性能计算(作业调度系统)
- 性能工程(eBPF profiling、火焰图分析)
环境要求
| 组件 |
版本要求 |
检查命令 |
| Linux内核 |
5.4+(eBPF需要) |
uname -r |
| GCC/G++ |
11+ |
g++ --version |
| CMake |
3.14+ |
cmake --version |
| bpftrace |
0.11+(可选) |
bpftrace --version |
TaskScheduler 7天学习计划汇总表
一、7天学习计划总览
| 天数 |
模块名称 |
核心功能 |
新增代码文件 |
关键技术点 |
可运行演示内容 |
| 第1天 |
基础设施 |
日志系统、项目框架 |
logger.h/cpp
main.cpp
CMakeLists.txt |
CMake构建、单例模式、线程安全、时间格式化 |
输出带时间戳的三条日志 |
| 第2天 |
任务定义与资源管理 |
Job结构体、资源配额管理 |
job.h
resource_manager.h/cpp
scheduler_test.cpp |
enum class、std::optional、互斥锁、GoogleTest |
单元测试通过,资源预留/释放验证 |
| 第3天 |
调度器核心 |
任务队列、调度循环、指标收集 |
metrics.h/cpp
scheduler.h/cpp |
原子操作、条件变量、生产者-消费者模型 |
多任务提交、队列等待、指标输出 |
| 第4天 |
进程启动与Cgroup |
fork/exec、进程组、资源限制 |
cgroup_helper.h/cpp
ebpf_profiler.h/cpp |
进程创建、进程组、rlimit、空实现模式 |
真正执行echo和ls命令 |
| 第5天 |
任务回收与超时控制 |
进程回收、超时检测、优雅终止 |
更新scheduler.cpp |
waitpid、僵尸进程、SIGTERM/SIGKILL、宽限期 |
超时任务被SIGTERM/SIGKILL终止 |
| 第6天 |
安全与监控 |
黑白名单、优先级、PSI背压、完整指标 |
更新metrics.h/cpp 更新scheduler.h/cpp |
字符串解析、PSI文件读取、Prometheus格式 |
命令过滤、优先级调度、背压演示 |
| 第7天 |
eBPF性能分析 |
bpftrace集成、符号解析、火焰图 |
ebpf_profiler.cpp完整版
bpf/profile_task.bt
workload_*.cpp |
eBPF、bpftrace、addr2line、c++filt |
生成性能报告和火焰图SVG |
二、每日学习内容详细表
第1天:基础设施
| 类别 |
内容 |
| 技术点 |
CMake构建、单例模式、RAII、线程安全、时间格式化 |
| 核心代码 |
Logger::instance()单例、std::scoped_lock自动加锁、std::chrono时间处理 |
| 重点概念 |
静态局部变量线程安全、localtime_r vs localtime、#pragma once |
| 运行验证 |
./scheduler 输出3条带时间戳的日志 |
| 面试题 |
静态局部变量为什么线程安全?RAII是什么?system_clock vs steady_clock? |
第2天:任务定义与资源管理
| 类别 |
内容 |
| 技术点 |
enum class、std::optional、默认成员初始化、互斥锁、GoogleTest |
| 核心代码 |
JobSpec/Job结构体、ResourceManager::reserve()原子操作、TEST宏 |
| 重点概念 |
强类型枚举、聚合初始化、check-then-act模式、结构化绑定 |
| 运行验证 |
./tests/scheduler_tests 2个测试全部通过 |
| 面试题 |
enum class vs enum?std::optional使用场景?析构函数应该抛异常吗? |
第3天:调度器核心
| 类别 |
内容 |
| 技术点 |
std::atomic、内存序、条件变量、生产者-消费者模型、快照模式 |
| 核心代码 |
Metrics::add_queue_wait() CAS更新最大值、dispatcher_loop()调度循环、pick_next_job()优先级选择 |
| 重点概念 |
relaxed内存序、伪唤醒、资源预留失败重试 |
| 运行验证 |
提交3个任务,看到队列等待和指标输出 |
| 面试题 |
memory_order_relaxed含义?为什么需要条件变量?如何避免伪唤醒? |
第4天:进程启动与Cgroup
| 类别 |
内容 |
| 技术点 |
fork/exec、写时复制、进程组、rlimit、空实现模式 |
| 核心代码 |
launch_job() fork+exec、setpgid(0,0)创建进程组、setrlimit()资源限制 |
| 重点概念 |
僵尸进程、孤儿进程、信号、SIGSTOP/SIGCONT |
| 运行验证 |
./scheduler --cmd "echo hello" 看到命令输出 |
| 面试题 |
fork() vs vfork()?写时复制如何实现?进程组作用? |
第5天:任务回收与超时控制
| 类别 |
内容 |
| 技术点 |
waitpid、退出状态解析、两阶段终止、宽限期管理 |
| 核心代码 |
reaper_loop()非阻塞回收、kill(-pgid, SIGTERM)、WIFEXITED/WIFSIGNALED宏 |
| 重点概念 |
僵尸进程避免、优雅终止、超时 vs 普通失败区分 |
| 运行验证 |
./scheduler --cmd "sleep 10" --timeout 3 3秒后被终止 |
| 面试题 |
SIGTERM vs SIGKILL?WNOHANG作用?如何判断进程被信号杀死? |
第6天:安全与监控
| 类别 |
内容 |
| 技术点 |
字符串解析、PSI压力监控、Prometheus指标格式、背压控制 |
| 核心代码 |
黑白名单检查、read_pressure_avg10()解析PSI、to_prometheus()指标导出 |
| 重点概念 |
默认拒绝安全模型、系统压力阈值、Counter vs Gauge |
| 运行验证 |
白名单拒绝cat命令、优先级调度、背压日志 |
| 面试题 |
白名单 vs 黑名单?PSI是什么?如何用于负载感知调度? |
第7天:eBPF性能分析
| 类别 |
内容 |
| 技术点 |
eBPF/bpftrace、探针类型、符号解析、火焰图生成 |
| 核心代码 |
profile_task.bt脚本、resolve_symbols() addr2line集成、generate_flamegraphs() SVG生成 |
| 重点概念 |
on-CPU vs off-CPU分析、用户态栈回溯、DWARF调试信息 |
| 运行验证 |
sudo ./scheduler --cmd "./workload_cpu" --enable-ebpf 生成火焰图 |
| 面试题 |
eBPF vs 内核模块?如何获取用户态调用栈?off-CPU分析重要性? |
三、你能学到什么?
3.1 C++核心技术
| 技术类别 |
具体知识点 |
在项目中的应用 |
| C++11/14/17/20 |
自动类型推导(auto)、范围for、lambda表达式 |
遍历容器、谓词函数 |
|
右值引用、移动语义 |
std::move(opts)、std::unique_ptr |
|
变参模板 |
GoogleTest的EXPECT_*宏 |
|
结构化绑定(C++17) |
auto [cpu, mem] = used() |
|
if constexpr(C++17) |
编译期条件判断 |
|
std::optional(C++17) |
end_time可选值 |
| 并发编程 |
std::thread |
dispatcher、reaper、psi三个线程 |
|
std::mutex / std::scoped_lock |
保护pending_、running_ |
|
std::condition_variable |
生产者-消费者同步 |
|
std::atomic |
指标计数器、shutting_down_标志 |
|
内存序(memory_order) |
relaxed用于计数器 |
| RAII与智能指针 |
std::unique_ptr |
profilers_映射管理 |
|
std::lock_guard / scoped_lock |
自动加锁解锁 |
|
构造函数/析构函数 |
资源获取与释放 |
| 设计模式 |
单例模式(Singleton) |
Logger::instance() |
|
工厂模式 |
Job对象创建 |
|
观察者模式 |
Metrics收集指标 |
|
策略模式 |
优先级调度策略 |
3.2 Linux系统编程
| 技术类别 |
具体知识点 |
在项目中的应用 |
| 进程管理 |
fork() |
创建子进程执行任务 |
|
exec族函数 |
替换进程映像执行命令 |
|
waitpid() |
回收子进程,防止僵尸 |
|
进程组(setpgid) |
统一管理任务的所有子进程 |
| 信号处理 |
SIGTERM/SIGKILL |
优雅终止超时任务 |
|
SIGSTOP/SIGCONT |
暂停/恢复进程用于eBPF追踪 |
|
raise() |
子进程暂停自己 |
| 资源限制 |
setrlimit() |
限制文件描述符、禁用core dump |
|
getrlimit() |
获取当前限制 |
| 文件系统 |
chdir() |
切换工作目录 |
|
/proc文件系统 |
读取进程maps、内存信息 |
| cgroup v2 |
cpu.max / memory.max |
限制CPU和内存(第7天) |
|
cgroup.procs |
将进程加入cgroup |
|
memory.pressure / cpu.pressure |
PSI压力监控 |
3.3 性能分析工具
| 工具/技术 |
用途 |
在项目中的应用 |
| eBPF/bpftrace |
动态内核追踪 |
CPU采样、系统调用追踪、off-CPU分析 |
| addr2line |
地址转函数名 |
解析用户态调用栈 |
| c++filt |
C++符号反修饰 |
还原可读的函数名 |
| perf |
性能采样 |
替代方案(未直接使用) |
| FlameGraph |
火焰图生成 |
可视化性能瓶颈 |
| Prometheus |
指标导出 |
暴露/metrics端点 |
3.4 构建与测试
| 技术 |
用途 |
| CMake |
跨平台构建、依赖管理 |
| FetchContent |
自动下载GoogleTest |
| GoogleTest |
单元测试框架 |
| address sanitizer |
内存错误检测(可选) |




4.3 线程模型
| 线程名称 |
职责 |
同步机制 |
与主线程关系 |
| 主线程 |
接收任务提交、解析命令行 |
互斥锁 |
创建其他线程 |
| dispatcher |
从队列取任务、启动子进程 |
条件变量 + 互斥锁 |
独立运行 |
| reaper |
回收子进程、超时检测 |
互斥锁 |
独立运行 |
| psi_monitor |
读取PSI文件、更新背压标志 |
原子变量 |
可选,cgroup启用时运行 |
五、技术栈总结表
| 层次 |
技术 |
用途 |
| 语言 |
C++17/C++20 |
主开发语言 |
| 构建 |
CMake 3.14+ |
跨平台构建 |
| 测试 |
GoogleTest |
单元测试 |
| 并发 |
std::thread, std::mutex, std::atomic, std::condition_variable |
多线程调度 |
| 进程 |
fork, exec, waitpid, kill, setpgid |
进程管理 |
| 信号 |
SIGTERM, SIGKILL, SIGSTOP, SIGCONT, SIGCHLD |
进程控制 |
| 资源 |
setrlimit, cgroup v2 |
资源限制 |
| 监控 |
PSI (pressure stall information) |
系统压力监控 |
| 性能 |
eBPF, bpftrace, addr2line, c++filt |
性能分析 |
| 可视化 |
FlameGraph (flamegraph.pl) |
火焰图生成 |
| 指标 |
Prometheus文本格式 |
指标导出 |
| 日志 |
自定义Logger |
运行时日志 |
六、学习成果验证表
| 天数 |
验证命令 |
预期结果 |
| 第1天 |
./scheduler |
输出3条带时间戳的日志 |
| 第2天 |
./tests/scheduler_tests |
2个测试全部PASSED |
| 第3天 |
./scheduler |
提交3个任务,看到队列等待和指标输出 |
| 第4天 |
./scheduler --cmd "echo hello" |
输出 "hello" |
| 第5天 |
./scheduler --cmd "sleep 10" --timeout 3 |
3秒后任务被终止 |
| 第6天 |
./scheduler --cmd "cat /etc/passwd" --whitelist "echo,ls" |
任务被拒绝(不在白名单) |
| 第7天 |
sudo ./scheduler --cmd "./workload_cpu" --enable-ebpf |
生成taskscheduler_ebpf/*.svg火焰图 |
部分技术点展示:
一、C++语言特性
1.1 枚举类(enum class)
enum class JobStatus {
Pending, Running, Succeeded, Failed, Timeout, Cancelled
};
| 特性 |
传统enum |
enum class |
| 作用域 |
全局作用域 |
强作用域(需JobStatus::Pending) |
| 隐式转换 |
可转int |
不可隐式转换 |
| 底层类型 |
不固定 |
可指定(如: uint8_t) |
| 类型安全 |
低 |
高 |
1.2 std::optional
std::optional<std::chrono::steady_clock::time_point> end_time{};
// 检查是否有值
if (job.end_time.has_value()) {
auto t = job.end_time.value();
}
// 或使用指针风格
if (auto& t = job.end_time) {
// t 是有效引用
}
使用场景:表示"可能有值,也可能没有"的状态,避免使用特殊值(如-1)或额外bool标志。
1.3 默认成员初始化
struct JobSpec {
std::string cmd;
int cpu_cores{1}; // C++11起支持
size_t memory_mb{256};
};
// 使用
JobSpec spec{"ls"}; // cpu_cores=1, memory_mb=256
1.4 结构化绑定(C++17)
// 返回pair
std::pair<int, size_t> used() const;
// 解包
auto [cpu, mem] = rm.used(); // cpu = int, mem = size_t
1.5 RAII与智能指针
// std::unique_ptr - 独占所有权
std::unique_ptr<EbpfProfiler> profiler = std::make_unique<EbpfProfiler>();
profilers_.emplace(job.id, std::move(profiler)); // 转移所有权
// 自动析构:离开作用域自动delete
RAII核心原则:资源获取即初始化,析构函数自动释放资源。
部分面试题展示
一、C++语言基础题(10题)
Q1:enum class 和传统 enum 有什么区别?
参考答案:
| 特性 |
传统enum |
enum class |
| 作用域 |
全局作用域(容易冲突) |
强作用域(需JobStatus::Pending) |
| 隐式转换 |
可隐式转换为int |
不可隐式转换,需static_cast |
| 底层类型 |
不固定,编译器决定 |
可指定(如: uint8_t) |
| 类型安全 |
低 |
高 |
// 传统enum - 有问题
enum Color { Red, Green, Blue };
enum Status { Red, Yellow, Green }; // 编译错误!Red/Green重复
// enum class - 正确
enum class Color { Red, Green, Blue };
enum class Status { Red, Yellow, Green }; // OK
Q2:std::optional 是什么?什么时候用?
参考答案:
std::optional 表示"可能有值,也可能没有值",用于替代特殊值模式(如用-1表示不存在)。
本项目应用:
std::optional<std::chrono::steady_clock::time_point> end_time{};
// 任务运行时没有end_time,结束后才有
对比传统方式:
// 传统方式 - 需要额外标志
time_point end_time;
bool has_end_time; // 容易忘记维护
// 现代方式 - 自文档化
std::optional<time_point> end_time;
if (end_time.has_value()) { ... }
Q3:std::unique_ptr 和 std::shared_ptr 的区别?
参考答案:
| 特性 |
unique_ptr |
shared_ptr |
| 所有权 |
独占 |
共享(引用计数) |
| 拷贝 |
不可拷贝,可移动 |
可拷贝 |
| 开销 |
零开销 |
引用计数开销 |
| 使用场景 |
明确唯一所有者 |
多个对象共享 |
本项目应用:
std::unordered_map<int, std::unique_ptr<EbpfProfiler>> profilers_;
// 每个任务只有一个profiler,用unique_ptr
Q4:什么是RAII?本项目哪里用到了?
参考答案:
RAII(Resource Acquisition Is Initialization)是将资源生命周期与对象生命周期绑定的编程范式。
本项目应用:
- 互斥锁:
std::scoped_lock lk(mu_),离开作用域自动解锁
- 智能指针:
std::unique_ptr自动释放内存
- 文件流:
std::ifstream离开作用域自动关闭文件
void log(const std::string& msg) {
std::scoped_lock lk(mu_); // 构造时加锁
std::cout << msg << std::endl;
// 析构时自动解锁,即使抛异常也会解锁
}
部分简历展示
模板1:C++后端开发工程师
个人信息
张三 | 185-XXXX-XXXX | ********** | GitHub: github.com/zhangsan
教育背景
专业技能
- 熟练掌握C++11/14/17/20,理解RAII、智能指针、移动语义等现代C++特性
- 熟悉Linux环境下的多线程编程,掌握互斥锁、条件变量、原子操作等同步机制
- 熟悉进程管理、信号处理、IPC通信等Linux系统编程
- 掌握CMake构建系统,GoogleTest单元测试框架
项目经验
TaskScheduler - 高性能任务调度系统 | C++ | 2025.03 - 2025.04
项目描述:开发了一个Linux环境下的多线程任务调度器,支持资源管理、任务队列、超时控制和性能分析。
技术栈:C++17/20、pthread、Linux系统调用、eBPF、Prometheus
核心职责:
- 设计并实现了线程安全的资源管理器(ResourceManager),支持CPU/内存配额的动态预留和释放
- 实现基于条件变量的生产者-消费者调度模型,支持优先级队列和任务排队机制
- 开发进程回收模块(Reaper),通过waitpid非阻塞回收子进程,实现超时任务的SIGTERM→SIGKILL优雅终止
- 集成eBPF/bpftrace性能分析器,通过addr2line和c++filt实现符号解析,自动生成On-CPU/Off-CPU火焰图
- 实现Prometheus格式的指标导出,包含任务计数、排队延迟、PSI背压等20+监控指标
项目成果:
- 支持同时管理1000+任务队列,任务调度延迟平均<1ms
- 通过eBPF分析定位IO瓶颈,优化fsync调用,性能提升30%
#简历中的项目经历要怎么写#