vpp初始化过程之主线程工作机制

博客内容待写,目前仅知标签为vpp,后续将围绕其展开信息技术相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主线程其实就是 VPP 运行时中第一个调度线程,它是线程 0(vlib_worker_threads[0]),它的职责是:

  • 完成所有 VPP 框架初始化工作;

  • 加载并解析配置;

  • 创建和初始化子系统(如 buffer pool、interface、plugin、graph、nodes);

  • 启动 worker threads;

  • 开始 graph node 调度循环。


🔧 初始化主线流程(以 vpp_main() 为起点)

0. 启动点 main()vpp/vpp.c

int main(int argc, char *argv[]) { return vpp_main(argc, argv); }


1. vpp_main() 入口(vpp/vpp.c)

📌 核心职责:
  • 初始化 VPP 核心模块

  • 调用 VLIB/VNET 各子系统初始化

  • 启动插件

  • 进入调度循环

int vpp_main(int argc, char *argv[]) { unformat_input_t input; clib_mem_init_thread_safe(0, 128 << 20); // 初始化 thread-safe 内存 vlib_main_init(&vm); // 初始化主 vlib_main_t 对象 vlib_plugin_early_init(); // 早期插件初始化(加载配置、注册信息) unformat_init_command_line(&input, argv); vlib_main(argv, &input); // 真正进入 vlib 框架入口 }


2. vlib_main() 框架初始化(vlib/main.c)

这是 VPP 主流程的中枢,它完成了绝大部分系统初始化操作。

🧩 关键模块初始化顺序:
步骤模块描述
1vlib_worker_thread_init()分配线程结构,初始化线程池(main thread + worker threads)
2vlib_physmem_init()初始化物理内存池,用于 buffer 分配
3vlib_frame_queue_init()初始化 inter-thread frame 队列(用于 handoff)
4vlib_buffer_main_init()初始化 buffer 系统(创建 freelist、预分配)
5vlib_register_all_static_nodes()注册所有静态 node(如 device-input, ip4-lookup)
6vlib_node_main_init()初始化 node 主结构(创建调度器、记录 node ID)
7vlib_call_all_main_loop_enter_funcs()调用所有 main_loop_enter 回调(用于注册模块事件)
8vlib_plugin_config()加载插件配置,调用 plugin 注册函数
9vlib_thread_init()启动子线程(worker threads),阻塞直到子线程 ready
10vlib_main_loop()启动主线程的调度循环

3. Node 注册阶段

节点通过 VLIB_REGISTER_NODE() 宏注册,系统在 vlib_register_all_static_nodes() 时收集所有 .node 段内容。

VLIB_REGISTER_NODE (device_input_node, static) = { .function = device_input, .name = "device-input", ... };

每个节点被赋予唯一 node_index,其对应的 function 在调度器中被调用。


4. Graph 构建

VPP 使用 graph engine 进行 packet processing,这里构建 DAG(有向无环图),包括:

  • 节点之间的 next 配置

  • 建立调度路径

  • 每个节点维护自己的 runtime state(frame pool、next frame 指针等)

完成后,每个线程将拥有一份独立的 vlib_node_runtime_t[]


5. Buffer 初始化(vlib_buffer_main_init()

主线程初始化:

  • buffer freelist

  • default buffer pool

  • 缓存 preallocated buffers 到每个线程中(避免竞争)

  • 配置 I/O buffer sizes,支持多种 payload size


6. Thread 初始化与同步(vlib_thread_init()

  • 创建 worker 线程数由 workers {} 配置段决定

  • 线程创建后进入 vlib_worker_thread_bootstrap_fn()

  • 每个线程注册 signal,设置 thread-local storage(TLS)

  • 所有线程 ready 后,主线程继续执行


7. Plugin 加载(vlib_plugin_config()

  • 加载 plugin_path 目录下的所有 .so 插件

  • 每个插件调用 vlib_register_all_static_nodes() 注册自己的节点

  • 调用插件的 vlib_plugin_register() 初始化逻辑


8. Main Loop 启动(vlib_main_loop()

主线程开始进入主循环,实际就是图调度器在不断调用每个 active node:

while (1) { dispatch_nodes(); // 选择 active 节点调度执行 process_timers(); // 执行定时任务 handle_signals(); // 接收外部信号 }


🖼️ 总体流程图

+------------------+ | main() | +--------+---------+ | v +------------------+ | vpp_main() | +--------+---------+ | v +---------------------------+ | vlib_main() | +---------------------------+ | init threads | | init buffers | | register nodes | | init plugins | | build graph | | launch workers | | enter dispatch loop | +---------------------------+


✅ 总结:主线程启动顺序一览

阶段说明
Step 1入口函数 vpp_main() 启动 VLIB
Step 2初始化内存系统、线程、frame、buffer
Step 3注册节点、构建 graph、创建调度结构
Step 4加载并初始化插件
Step 5启动 worker threads 并同步
Step 6启动主线程调度循环,等待事件包处理
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值