Skip to content

Commit 51170c0

Browse files
修复 VMA 无法在 fork 同步分配数据的问题, 修复 EEVDF 中 yield 无效问题.
修复 iso9660_readfile 错误的返回长度问题. 修复 VMA 在 execve 函数中发生泄露的问题. Co-authored-by: suhuajun-github <115517663+suhuajun-github@users.noreply.github.com>
1 parent e9d5af7 commit 51170c0

File tree

10 files changed

+165
-162
lines changed

10 files changed

+165
-162
lines changed

assets/initramfs.img

512 Bytes
Binary file not shown.

src/arch/x86_64/fs/pipefs.c

Lines changed: 38 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,6 @@ vfs_node_t pipefs_root = NULL;
77
int pipefs_id = 0;
88
int pipefd_id = 0;
99

10-
void wake_blocked_tasks(task_block_list_t *head) {
11-
task_block_list_t *current = head->next;
12-
head->next = NULL;
13-
14-
while (current) {
15-
task_block_list_t *next = current->next;
16-
if (current->thread) { current->thread->status = START; }
17-
free(current);
18-
current = next;
19-
}
20-
}
21-
2210
void pipefs_open(void *parent, const char *name, vfs_node_t node) {
2311
(void)parent;
2412
(void)name;
@@ -33,124 +21,53 @@ size_t pipefs_read(void *file, void *addr, size_t offset, size_t size) {
3321
pipe_info_t *pipe = spec->info;
3422
if (!pipe) return -EINVAL;
3523

36-
spin_lock(pipe->lock);
37-
38-
uint32_t available = (pipe->write_ptr - pipe->read_ptr) % PIPE_BUFF;
39-
if (available == 0) {
40-
fd_file_handle *fd = container_of(spec->node, fd_file_handle, node);
41-
if (fd->flags & O_NONBLOCK) {
42-
spin_unlock(pipe->lock);
43-
return -EWOULDBLOCK;
44-
}
45-
46-
if (pipe->write_fds == 0) {
47-
spin_unlock(pipe->lock);
48-
return 0;
49-
}
50-
close_interrupt;
51-
task_block_list_t *new_block = malloc(sizeof(task_block_list_t));
52-
new_block->thread = get_current_task();
53-
new_block->next = NULL;
54-
55-
task_block_list_t *browse = &pipe->blocking_read;
56-
while (browse->next)
57-
browse = browse->next;
58-
browse->next = new_block;
24+
while (pipe->ptr == 0) {
25+
if (pipe->write_fds == 0) { return 0; }
5926

60-
spin_unlock(pipe->lock);
61-
62-
task_block(get_current_task(), WAIT, -1);
27+
scheduler_yield();
6328
}
64-
spin_unlock(pipe->lock);
65-
66-
available = (pipe->write_ptr - pipe->read_ptr) % PIPE_BUFF;
6729

6830
// 实际读取量
69-
uint32_t to_read = MIN(size, available);
31+
uint32_t to_read = MIN(size, pipe->ptr);
7032

71-
if (available == 0) {
72-
spin_unlock(pipe->lock);
73-
return 0;
74-
}
33+
if (to_read == 0) { return 0; }
7534

76-
// 分两种情况拷贝数据
77-
if (pipe->read_ptr + to_read <= PIPE_BUFF) {
78-
memcpy(addr, &pipe->buf[pipe->read_ptr], to_read);
79-
} else {
80-
uint32_t first_chunk = PIPE_BUFF - pipe->read_ptr;
81-
memcpy(addr, &pipe->buf[pipe->read_ptr], first_chunk);
82-
memcpy(addr + first_chunk, pipe->buf, to_read - first_chunk);
83-
}
35+
spin_lock(pipe->lock);
8436

85-
// 更新读指针
86-
pipe->read_ptr = (pipe->read_ptr + to_read) % PIPE_BUFF;
37+
memcpy(addr, pipe->buf, to_read);
38+
memmove(pipe->buf, &pipe->buf[pipe->ptr], pipe->ptr - to_read);
8739

88-
wake_blocked_tasks(&pipe->blocking_write);
40+
pipe->ptr -= to_read;
8941

9042
spin_unlock(pipe->lock);
9143

9244
return to_read;
9345
}
9446

9547
size_t pipe_write_inner(void *file, const void *addr, size_t size) {
96-
if (size > PIPE_BUFF) size = PIPE_BUFF;
97-
9848
pipe_specific_t *spec = (pipe_specific_t *)file;
9949
pipe_info_t *pipe = spec->info;
10050

101-
spin_lock(pipe->lock);
102-
103-
uint32_t free_space = PIPE_BUFF - ((pipe->write_ptr - pipe->read_ptr) % PIPE_BUFF);
104-
if (free_space < size) {
105-
if (pipe->read_fds == 0) {
106-
spin_unlock(pipe->lock);
107-
return -EPIPE;
108-
}
109-
task_block_list_t *new_block = malloc(sizeof(task_block_list_t));
110-
new_block->thread = get_current_task();
111-
new_block->next = NULL;
112-
113-
task_block_list_t *browse = &pipe->blocking_write;
114-
115-
while (browse->next)
116-
browse = browse->next;
117-
browse->next = new_block;
118-
119-
spin_unlock(pipe->lock);
120-
121-
task_block(get_current_task(), WAIT, -1);
122-
123-
while (get_current_task()->status == WAIT) {
124-
open_interrupt;
125-
__asm__("pause");
126-
}
127-
close_interrupt;
51+
while ((PIPE_BUFF - pipe->ptr) < size) {
52+
if (pipe->read_fds == 0) { return -EPIPE; }
53+
scheduler_yield();
12854
}
12955

130-
if (pipe->write_ptr + size <= PIPE_BUFF) {
131-
memcpy(&pipe->buf[pipe->write_ptr], addr, size);
132-
} else {
133-
uint32_t first_chunk = PIPE_BUFF - pipe->write_ptr;
134-
memcpy(&pipe->buf[pipe->write_ptr], addr, first_chunk);
135-
memcpy(pipe->buf, addr + first_chunk, size - first_chunk);
136-
}
137-
138-
pipe->write_ptr = (pipe->write_ptr + size) % PIPE_BUFF;
139-
140-
wake_blocked_tasks(&pipe->blocking_read);
141-
56+
spin_lock(pipe->lock);
57+
memcpy(&pipe->buf[pipe->ptr], addr, size);
58+
pipe->ptr += size;
14259
spin_unlock(pipe->lock);
14360

14461
return size;
14562
}
14663

14764
size_t pipefs_write(void *file, const void *addr, size_t offset, size_t size) {
148-
int ret = 0;
65+
size_t ret = 0;
14966
size_t chunks = size / PIPE_BUFF;
15067
size_t remainder = size % PIPE_BUFF;
15168
if (chunks)
15269
for (size_t i = 0; i < chunks; i++) {
153-
int cycle = 0;
70+
size_t cycle = 0;
15471
while (cycle != PIPE_BUFF)
15572
cycle += pipe_write_inner(file, addr + i * PIPE_BUFF + cycle, PIPE_BUFF - cycle);
15673
ret += cycle;
@@ -183,15 +100,17 @@ bool pipefs_close(void *current) {
183100
pipe->read_fds--;
184101
}
185102

186-
if (!pipe->write_fds) wake_blocked_tasks(&pipe->blocking_read);
187-
if (!pipe->read_fds) wake_blocked_tasks(&pipe->blocking_write);
188-
189-
if (pipe->write_fds == 0 && pipe->read_fds == 0) { free(pipe); }
190-
spin_unlock(pipe->lock);
103+
list_delete(pipefs_root->child, spec->node);
104+
if ((spec->write && pipe->write_fds == 0) || pipe->read_fds == 0) free(spec);
191105

192-
free(spec);
106+
if (pipe->write_fds == 0 && pipe->read_fds == 0) {
107+
spin_unlock(pipe->lock);
108+
free(pipe->buf);
109+
free(pipe);
110+
return true;
111+
}
193112

194-
list_delete(pipefs_root->child, spec->node);
113+
spin_unlock(pipe->lock);
195114

196115
return true;
197116
}
@@ -204,17 +123,13 @@ int pipefs_poll(void *file, size_t events) {
204123

205124
spin_lock(pipe->lock);
206125
if (events & EPOLLIN) {
207-
if (!pipe->write_fds)
208-
out |= EPOLLHUP;
209-
else if (pipe->write_ptr != pipe->read_ptr)
210-
out |= EPOLLIN;
126+
if (!pipe->write_fds) out |= EPOLLHUP;
127+
if (pipe->assigned > 0) out |= EPOLLIN;
211128
}
212129

213130
if (events & EPOLLOUT) {
214-
if (!pipe->read_fds)
215-
out |= EPOLLERR;
216-
else if (pipe->assigned < PIPE_BUFF)
217-
out |= EPOLLOUT;
131+
if (!pipe->read_fds) out |= EPOLLHUP;
132+
if (pipe->assigned < PIPE_BUFF) out |= EPOLLOUT;
218133
}
219134
spin_unlock(pipe->lock);
220135
return out;
@@ -231,6 +146,13 @@ static int dummy() {
231146
return -ENOSYS;
232147
}
233148

149+
errno_t pipefs_stat(void *file, vfs_node_t node) {
150+
pipe_specific_t *spec = (pipe_specific_t *)file;
151+
pipe_info_t *pipe = spec->info;
152+
node->size = pipe->ptr;
153+
return EOK;
154+
}
155+
234156
static struct vfs_callback pipefs_callbacks = {
235157
.mount = pipefs_mount,
236158
.unmount = (vfs_unmount_t)empty,
@@ -246,7 +168,7 @@ static struct vfs_callback pipefs_callbacks = {
246168
.delete = (vfs_del_t)empty,
247169
.rename = (vfs_rename_t)empty,
248170
.map = (vfs_mapfile_t)empty,
249-
.stat = (vfs_stat_t)empty,
171+
.stat = pipefs_stat,
250172
.ioctl = (vfs_ioctl_t)pipefs_ioctl,
251173
.poll = pipefs_poll,
252174
.dup = (vfs_dup_t)empty,

src/arch/x86_64/include/pipefs.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ typedef struct task_block_list {
1212
} task_block_list_t;
1313

1414
typedef struct pipe_info {
15-
uint32_t read_ptr;
16-
uint32_t write_ptr;
17-
char buf[PIPE_BUFF];
15+
uint32_t ptr;
16+
char *buf;
1817
int assigned;
1918

2019
int write_fds;

src/arch/x86_64/include/vma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,4 @@ int vma_split(vma_t *vma, unsigned long addr);
4848
int vma_merge(vma_t *vma1, vma_t *vma2);
4949
int vma_unmap_range(vma_manager_t *mgr, uintptr_t start, uintptr_t end);
5050
void vma_manager_exit_cleanup(vma_manager_t *mgr);
51+
bool vma_manager_clone(vma_manager_t *src_mgr,vma_manager_t *dst_mgr);

src/arch/x86_64/mem/vma.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,71 @@ void vma_manager_exit_cleanup(vma_manager_t *mgr) {
209209
mgr->vm_total = 0;
210210
mgr->vm_used = 0;
211211
}
212+
213+
bool vma_manager_clone(vma_manager_t *src_mgr,vma_manager_t *dst_mgr) {
214+
if (!src_mgr) {
215+
return false;
216+
}
217+
if (!dst_mgr) {
218+
return false;
219+
}
220+
221+
// 2. 复制管理器的基本信息
222+
dst_mgr->vma_list = NULL; // 链表头先设为 NULL
223+
dst_mgr->vm_total = src_mgr->vm_total;
224+
dst_mgr->vm_used = 0; // vm_used 将在插入 VMA 时更新
225+
226+
vma_t *src_vma = src_mgr->vma_list;
227+
vma_t *new_vma = NULL;
228+
229+
// 3. 遍历源 VMA 链表并深拷贝
230+
while (src_vma) {
231+
// 3.1. 分配新的 VMA 节点
232+
new_vma = vma_alloc();
233+
if (!new_vma) {
234+
// 如果分配失败,必须清理已复制的部分
235+
// vma_manager_exit_cleanup 适合清理,但需要保证它能正确处理部分构建的链表
236+
// 这里我们使用一个更轻量级的清理,因为 vma_insert 并没有完全依赖 mgr->vm_used
237+
// 但是 vma_manager_exit_cleanup 更健壮
238+
vma_manager_exit_cleanup(dst_mgr);
239+
return false;
240+
}
241+
242+
// 3.2. 复制 VMA 的基本属性
243+
// 复制除了指针以外的所有字段
244+
new_vma->vm_start = src_vma->vm_start;
245+
new_vma->vm_end = src_vma->vm_end;
246+
new_vma->vm_flags = src_vma->vm_flags;
247+
new_vma->vm_type = src_vma->vm_type;
248+
new_vma->vm_fd = src_vma->vm_fd;
249+
new_vma->vm_offset = src_vma->vm_offset;
250+
new_vma->shm_id = src_vma->shm_id;
251+
252+
// 链表指针在 vma_alloc 中初始化为 NULL,在 vma_insert 中设置
253+
254+
// 3.3. 深拷贝 vm_name
255+
if (src_vma->vm_name) {
256+
size_t name_len = strlen(src_vma->vm_name) + 1;
257+
new_vma->vm_name = (char *)malloc(name_len);
258+
if (!new_vma->vm_name) {
259+
// 如果名称分配失败,清理并退出
260+
vma_free(new_vma);
261+
vma_manager_exit_cleanup(dst_mgr);
262+
return false;
263+
}
264+
memcpy(new_vma->vm_name, src_vma->vm_name, name_len);
265+
} else {
266+
new_vma->vm_name = NULL;
267+
}
268+
269+
if (vma_insert(dst_mgr, new_vma) != 0) {
270+
// 这不应该发生,除非 vm_start/vm_end 出错
271+
vma_free(new_vma);
272+
vma_manager_exit_cleanup(dst_mgr);
273+
return false;
274+
}
275+
276+
src_vma = src_vma->vm_next;
277+
}
278+
return true;
279+
}

0 commit comments

Comments
 (0)