Skip to content

ken4647/Remote-Schedule-Server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LD_PRELOAD Thread Scheduler

一个基于 LD_PRELOAD 的线程调度管理系统,支持动态管理线程调度策略和标记,适用于实时系统、性能调优和资源管理场景。

功能特性

核心功能

  • 自动线程追踪:通过 LD_PRELOAD hook 自动捕获线程创建事件,无需修改应用程序代码
  • 标记继承机制:子线程自动继承父线程的所有标记,便于线程分类和管理
  • 灵活的调度策略:支持 Linux 所有主流调度策略(SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)
  • 多语言支持:提供 C/C++、Python、Rust 三种语言的 API 绑定
  • 标记格式验证:确保标记只包含字母和下划线,保证一致性和可读性

主要 API

  • sched_client_set_policy() - 设置线程调度策略和优先级/nice 值
  • sched_client_add_tag() - 为线程添加标记
  • sched_client_remove_tag() - 删除指定标记
  • sched_client_clear_tags() - 清空所有标记
  • sched_client_get_tags() - 获取所有标记(逗号分隔)
  • sched_client_gettid() - 获取当前线程 TID

项目架构

项目采用客户端-服务器架构,包含三个主要组件:

┌─────────────┐      ┌──────────────────┐      ┌──────────────┐
│   Client    │─────▶│ Schedule Server  │◀─────│ Hook Library │
│ Application │      │  (Unix Socket)   │      │ (LD_PRELOAD) │
└─────────────┘      └──────────────────┘      └──────────────┘

组件说明

  1. Hook 库 (hook/)

    • 通过 LD_PRELOAD 拦截 pthread_create 调用
    • 自动向调度服务器发送线程创建事件
  2. 调度服务器 (schedule_server/)

    • 中央调度管理服务
    • 处理调度策略设置和标记管理
    • 实现标记继承机制
  3. 客户端 API (api/)

    • 提供统一的跨语言接口
    • 支持 C/C++、Python、Rust

编译和安装

前提条件

  • GCC 编译器
  • Make 构建工具
  • Git(用于管理 submodule)
  • Python 3.x(可选,用于 Python 绑定)
  • Rust 工具链(可选,用于 Rust 绑定)

编译步骤

# 克隆项目(包含 submodule)
git clone --recurse-submodules <repository-url>
cd ldpreload

# 如果已经克隆了项目,需要初始化 submodule
git submodule update --init --recursive

# 编译所有组件
make all

# 或者分别编译
make libsched    # 编译客户端库
make dymso       # 编译 hook 库
make sserver     # 编译调度服务器

编译产物

编译完成后,所有产物位于 build/ 目录:

  • libsched_client.so - 客户端共享库
  • libsched_client.a - 客户端静态库
  • tsched_hook.so - Hook 库
  • sserver - 调度服务器可执行文件

使用方法

1. 启动调度服务器

# 在终端中启动服务器
./build/sserver

# 或者使用 make 命令
make run_sserver

注意:调度服务器需要 CAP_SYS_NICE 权限来设置线程调度策略。如果权限不足,可以使用:

sudo setcap cap_sys_nice+ep ./build/sserver

2. 使用 Hook 库(自动追踪线程)

# 使用 LD_PRELOAD 运行应用程序
LD_PRELOAD=./build/tsched_hook.so your_application

# 示例:运行 Python 测试
make run_ros

3. 在代码中使用 API

C/C++ 示例

#include "sched_client.h"
#include <pthread.h>

void* worker_thread(void* arg) {
    // 获取当前线程 TID
    pid_t tid = sched_client_gettid();
    
    // 添加标记
    sched_client_add_tag(0, "worker_thread");
    sched_client_add_tag(0, "high_priority");
    
    // 设置调度策略为 SCHED_FIFO,优先级 50
    sched_client_set_policy(0, SCHED_FIFO, 50, 0);
    
    // 获取所有标记
    char tags[256];
    sched_client_get_tags(0, tags, sizeof(tags));
    printf("Tags: %s\n", tags);  // 输出: "worker_thread,high_priority"
    
    return NULL;
}

编译:

gcc -o program program.c -I./api/inc -L./build -lsched_client -lpthread
LD_LIBRARY_PATH=./build ./program

Python 示例

from sched_client import SchedClient, SCHED_FIFO

client = SchedClient()

# 添加标记
client.add_tag(0, "python_thread")

# 设置调度策略
client.set_policy(0, SCHED_FIFO, 50, 0)

# 获取标记
tags = client.get_tags()
print(f"Tags: {tags}")

运行:

export LD_LIBRARY_PATH=./build:$LD_LIBRARY_PATH
python3 your_script.py

Rust 示例

use sched_client::{SchedClient, SCHED_FIFO};

// 添加标记
SchedClient::add_tag(0, "rust_thread").unwrap();

// 设置调度策略
SchedClient::set_policy(0, SCHED_FIFO, 50, 0).unwrap();

// 获取标记
let tags = SchedClient::get_tags(0, 1024).unwrap();
println!("Tags: {}", tags);

API 文档

调度策略设置

int sched_client_set_policy(pid_t tid, int policy, int priority, int nice);
  • 参数
    • tid: 线程 ID(0 表示当前线程)
    • policy: 调度策略(SCHED_OTHER、SCHED_FIFO、SCHED_RR、SCHED_DEADLINE)
    • priority: 优先级(用于 FIFO/RR/DEADLINE,范围通常 1-99)
    • nice: nice 值(用于 SCHED_OTHER,范围 -20 到 19)
  • 返回值:0 成功,-1 失败

标记管理

// 添加标记(只允许字母和下划线)
int sched_client_add_tag(pid_t tid, const char *tag);

// 删除标记
int sched_client_remove_tag(pid_t tid, const char *tag);

// 清空所有标记
int sched_client_clear_tags(pid_t tid);

// 获取所有标记(逗号分隔)
int sched_client_get_tags(pid_t tid, char *buffer, size_t buffer_size);

工具函数

// 获取当前线程 TID
pid_t sched_client_gettid(void);

示例程序

项目提供了完整的示例程序,位于 demo/ 目录:

  • C 示例 (demo/c/) - 使用 pthread
  • C++ 示例 (demo/cpp/) - 使用 std::thread
  • Python 示例 (demo/python/) - 使用 threading
  • Rust 示例 (demo/rust/) - 使用 std::thread

运行示例:

# 编译所有 demo
make demo-all

# 运行 C demo
LD_LIBRARY_PATH=./build ./build/demo_c

# 运行 Python demo
cd demo/python
export LD_LIBRARY_PATH=../../build:$LD_LIBRARY_PATH
python3 demo.py

详细说明请参考 demo/README.md

项目结构

ldpreload/
├── api/                    # 客户端 API
│   ├── inc/                # C 头文件
│   ├── src/                # C 实现
│   ├── python/              # Python 绑定
│   └── rust/               # Rust 绑定
├── hook/                    # LD_PRELOAD hook 库
├── schedule_server/         # 调度服务器
├── share/                   # 共享资源
│   ├── inc/                 # 公共头文件
│   ├── src/                 # 公共源文件
│   └── third_party/         # 第三方库(cJSON)
├── demo/                    # 示例程序
│   ├── c/                   # C 示例
│   ├── cpp/                 # C++ 示例
│   ├── python/              # Python 示例
│   └── rust/                # Rust 示例
├── test/                    # 测试代码
├── build/                   # 构建输出目录
├── Makefile                 # 主 Makefile
└── README.md               # 本文档

Makefile 目标

make all          # 编译所有组件(默认)
make libsched     # 编译客户端库
make dymso        # 编译 hook 库
make sserver      # 编译调度服务器
make demo-c       # 编译 C demo
make demo-cpp     # 编译 C++ demo
make demo-rust    # 编译 Rust demo
make demo-all     # 编译所有 demo
make clean        # 清理所有构建产物
make help         # 显示帮助信息

工作原理

线程创建追踪

  1. 应用程序通过 LD_PRELOAD 加载 tsched_hook.so
  2. Hook 库拦截 pthread_create 调用
  3. 创建新线程时,hook 库向调度服务器发送 parent_relation 消息
  4. 调度服务器自动将父线程的标记继承给子线程

标记继承流程

父线程 (TID: 1000)
  ├─ 标记: ["worker", "high_priority"]
  └─ 创建子线程 (TID: 1001)
      └─ 自动继承: ["worker", "high_priority"]

调度策略设置

客户端通过 Unix Domain Socket 向调度服务器发送请求,服务器执行实际的调度策略设置操作。

注意事项

  1. 权限要求:设置实时调度策略(SCHED_FIFO/RR)需要 root 权限或 CAP_SYS_NICE 能力
  2. 标记格式:标记只能包含大小写英文字母和下划线(a-z, A-Z, _)
  3. 服务器运行:使用 API 前必须确保调度服务器正在运行
  4. 线程安全:API 函数是线程安全的,可以在多线程环境中使用
  5. 性能影响:Hook 库会略微增加线程创建的开销,但影响很小

故障排除

问题:无法加载共享库

# 确保库文件在 LD_LIBRARY_PATH 中
export LD_LIBRARY_PATH=./build:$LD_LIBRARY_PATH

问题:调度策略设置失败

  • 检查是否有足够的权限(需要 root 或 CAP_SYS_NICE)
  • 确认调度服务器正在运行
  • 检查线程 ID 是否正确

问题:标记格式验证失败

  • 确保标记只包含字母和下划线
  • 不能包含数字、空格或特殊字符

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published