SimpleKernel 1.17.0
Loading...
Searching...
No Matches
clone.cpp
Go to the documentation of this file.
1
5#include "expected.hpp"
6#include "kernel.h"
7#include "kernel_log.hpp"
8#include "kstd_cstring"
9#include "sk_stdlib.h"
10#include "task_manager.hpp"
11#include "virtual_memory.hpp"
12
13auto TaskManager::Clone(uint64_t flags, void* user_stack, int* parent_tid,
14 int* child_tid, void* tls,
15 cpu_io::TrapContext& parent_context) -> Expected<Pid> {
16 auto* parent = GetCurrentTask();
17 if (!parent) {
18 klog::Err("Clone: No current task");
19 return std::unexpected(Error(ErrorCode::kTaskNoCurrentTask));
20 }
21
22 // 验证克隆标志的合法性
23 // 如果设置了 kCloneThread,必须同时设置 kCloneVm, kCloneFiles, kCloneSighand
24 if ((flags & clone_flag::kThread) &&
25 (!(flags & clone_flag::kVm) || !(flags & clone_flag::kFiles) ||
26 !(flags & clone_flag::kSighand))) {
28 "Clone: kCloneThread requires kCloneVm, kCloneFiles, kCloneSighand");
29 // 自动补全必需的标志
31 }
32
33 // 分配新的 PID
34 Pid new_pid = AllocatePid();
35 if (new_pid == 0) {
36 klog::Err("Clone: Failed to allocate PID");
37 return std::unexpected(Error(ErrorCode::kTaskPidAllocationFailed));
38 }
39
40 // 创建子任务控制块
41 auto child_ptr = kstd::make_unique<TaskControlBlock>();
42 if (!child_ptr) {
43 klog::Err("Clone: Failed to allocate child task");
44 return std::unexpected(Error(ErrorCode::kTaskAllocationFailed));
45 }
46 auto* child = child_ptr.get();
47 // Default ctor leaves FSM in set_states-but-not-started state.
48 // Start it so get_state_id() returns kUnInit instead of deref null.
49 child->fsm.Start();
50
51 // 基本字段设置
52 child->pid = new_pid;
53 child->name = parent->name;
54 child->policy = parent->policy;
55 child->sched_info = parent->sched_info;
56
57 // 设置父进程 ID
58 if (flags & clone_flag::kParent) {
59 // 保持与父进程相同的父进程
60 child->aux->parent_pid = parent->aux->parent_pid;
61 } else {
62 child->aux->parent_pid = parent->pid;
63 }
64
65 // 处理线程组 ID (TGID)
66 if (flags & clone_flag::kThread) {
67 // 创建线程: 共享线程组
68 child->aux->tgid = parent->aux->tgid;
69 child->aux->pgid = parent->aux->pgid;
70 child->aux->sid = parent->aux->sid;
71
72 // 将子线程加入父线程的线程组
73 if (parent->IsThreadGroupLeader()) {
74 child->JoinThreadGroup(parent);
75 } else {
76 // 找到线程组的主线程
77 TaskControlBlock* leader = FindTask(parent->aux->tgid);
78 if (leader) {
79 child->JoinThreadGroup(leader);
80 } else {
81 klog::Warn("Clone: Thread group leader not found for tgid={}",
82 parent->aux->tgid);
83 }
84 }
85 } else {
86 // 创建进程: 新的线程组
87 // 新进程的 tgid 是自己的 pid
88 child->aux->tgid = new_pid;
89 child->aux->pgid = parent->aux->pgid;
90 child->aux->sid = parent->aux->sid;
91 }
92
93 // 克隆标志位
94 child->aux->clone_flags = CloneFlags(flags);
95
96 // 处理文件描述符表 (kCloneFiles)
98 if (flags & clone_flag::kFiles) {
99 klog::Debug("Clone: sharing file descriptor table (not implemented)");
100 } else {
101 klog::Debug("Clone: copying file descriptor table (not implemented)");
102 }
103
104 // 处理信号处理器 (kCloneSighand)
106 if (flags & clone_flag::kSighand) {
107 klog::Debug("Clone: sharing signal handlers (not implemented)");
108 } else {
109 klog::Debug("Clone: copying signal handlers (not implemented)");
110 }
111
112 // 处理文件系统信息 (kCloneFs)
114 if (flags & clone_flag::kFs) {
115 klog::Debug("Clone: sharing filesystem info (not implemented)");
116 } else {
117 klog::Debug("Clone: copying filesystem info (not implemented)");
118 }
119
120 // 处理地址空间
121 if (flags & clone_flag::kVm) {
122 // 共享地址空间(线程)
123 child->page_table = parent->page_table;
124 klog::Debug("Clone: sharing page table {:#x}",
125 reinterpret_cast<uintptr_t>(child->page_table));
126 } else {
127 // 复制地址空间(进程)
128 if (parent->page_table) {
129 // copy_mappings=true 表示复制用户空间映射
130 auto result = VirtualMemorySingleton::instance().ClonePageDirectory(
131 parent->page_table, true);
132 if (!result.has_value()) {
133 klog::Err("Clone: Failed to clone page table: {}",
134 result.error().message());
135 // 独立页表已由 unique_ptr 在作用域结束时自动释放
136 // 仅需清理页表
137 if (child->page_table && !(flags & clone_flag::kVm)) {
138 VirtualMemorySingleton::instance().DestroyPageDirectory(
139 child->page_table, false);
140 child->page_table = nullptr;
141 }
142 return std::unexpected(Error(ErrorCode::kTaskAllocationFailed));
143 }
144 child->page_table = reinterpret_cast<uint64_t*>(result.value());
145 klog::Debug("Clone: cloned page table from {:#x} to {:#x}",
146 reinterpret_cast<uintptr_t>(parent->page_table),
147 reinterpret_cast<uintptr_t>(child->page_table));
148 } else {
149 // 父进程没有页表(内核线程),子进程也不需要
150 child->page_table = nullptr;
151 }
152 }
153
154 // 分配内核栈
155 child->kernel_stack = static_cast<uint8_t*>(
158 if (!child->kernel_stack) {
159 klog::Err("Clone: Failed to allocate kernel stack");
160 // 清理已分配的资源
161 if (child->page_table && !(flags & clone_flag::kVm)) {
162 VirtualMemorySingleton::instance().DestroyPageDirectory(child->page_table,
163 false);
164 child->page_table = nullptr;
165 }
166 return std::unexpected(Error(ErrorCode::kTaskKernelStackAllocationFailed));
167 }
168
169 // 初始化内核栈内容
170 kstd::memset(child->kernel_stack, 0,
172
173 // 复制 trap context
174 child->trap_context_ptr = reinterpret_cast<cpu_io::TrapContext*>(
175 child->kernel_stack + TaskControlBlock::kDefaultKernelStackSize -
176 sizeof(cpu_io::TrapContext));
177 kstd::memcpy(child->trap_context_ptr, &parent_context,
178 sizeof(cpu_io::TrapContext));
179
180 // 设置用户栈
181 if (user_stack) {
182 child->trap_context_ptr->UserStackPointer() =
183 reinterpret_cast<uint64_t>(user_stack);
184 }
185
186 // 设置 TLS (Thread Local Storage)
187 if (tls) {
188 child->trap_context_ptr->ThreadPointer() = reinterpret_cast<uint64_t>(tls);
189 }
190
191 // 父进程返回子进程 PID
192 parent_context.ReturnValue() = new_pid;
193 // 子进程返回 0
194 child->trap_context_ptr->ReturnValue() = 0;
195
196 // 写入 TID
197 if (parent_tid) {
198 *parent_tid = new_pid;
199 }
200 if (child_tid) {
201 *child_tid = new_pid;
202 }
203
204 // 将子任务添加到调度器
205 AddTask(std::move(child_ptr));
206
207 // 打印详细的 clone 信息
208 const char* clone_type = (flags & clone_flag::kThread) ? "thread" : "process";
209 const char* vm_type = (flags & clone_flag::kVm) ? "shared" : "copied";
211 "Clone: created {} - parent={}, child={}, tgid={}, vm={}, flags={:#x}",
212 clone_type, parent->pid, new_pid, child->aux->tgid, vm_type,
213 static_cast<uint64_t>(flags));
214 return new_pid;
215}
auto Clone(uint64_t flags, void *user_stack, int *parent_tid, int *child_tid, void *tls, cpu_io::TrapContext &parent_context) -> Expected< Pid >
克隆当前任务 (fork/clone 系统调用)
Definition clone.cpp:13
@ kTaskNoCurrentTask
@ kTaskAllocationFailed
@ kTaskPidAllocationFailed
@ kTaskKernelStackAllocationFailed
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
constexpr uint64_t kFiles
共享文件描述符表
constexpr uint64_t kSighand
共享信号处理器
constexpr uint64_t kParent
保持相同父进程
constexpr uint64_t kThread
同一线程组
constexpr uint64_t kFs
共享文件系统信息
constexpr uint64_t kVm
共享地址空间
static constexpr size_t kPageSize
Definition cpu_io.h:63
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
void * aligned_alloc(size_t alignment, size_t size)
Definition memory.cpp:58
错误类型,用于 std::expected
Definition expected.hpp:343
任务控制块,管理进程/线程的核心数据结构
static constexpr size_t kDefaultKernelStackSize
默认内核栈大小 (16 KB)
etl::flags< uint64_t, clone_flag::kAllMask > CloneFlags
克隆标志位
size_t Pid
进程 ID 类型