I'm implementing a 32-bit OS, but there's something wrong with fork (used to clone a process). My fork implementation just clones the address space of parent task (by clone the page directory), then set some context (ESP, EBP and EIP) for the child (when the running task is parent) or recover EBP and returns (when the running task is child).
The code below causes child process do nothing, rather than printing some characters to the screen:
Code: Select all
if (fork() != 0) {
if (fork() != 0) {
while(1) {
monitor_write("a"); // works
u32int i;
for (i = 0; i < 5000; i++);
}
} else {
if (fork() != 0) {
while(1) {
monitor_write("m"); // works
u32int i;
for (i = 0; i < 5000; i++);
}
} else {
while(1) {
monitor_write("n"); // do nothing
u32int i;
for (i = 0; i < 5000; i++);
}
}
}
} else {
if (fork() == 0) {
while(1) {
monitor_write("p"); // do nothing
u32int i;
for (i = 0; i < 5000; i++);
}
} else {
if (fork() != 0) {
while(1) {
monitor_write("b"); // works
u32int i;
for (i = 0; i < 5000; i++);
}
} else {
while(1) {
monitor_write("q"); // do nothing
u32int i;
for (i = 0; i < 5000; i++);
}
}
}
btw, each task has its 4KB kernel stack on virtual address 0xE0000000 and below is the code for task switching:
Code: Select all
[EXTERN __switch_to]
schedule:
push esi
push edi
push ebp
mov [eax+0x4], esp ; prev->esp
mov dword [eax+0xc], .bpoint ; prev->eip
mov cr3, ecx ; next->page_dir->physaddr
mov esp, [edx+0x4] ; next->esp
push dword [edx+0xc] ; next->eip
jmp __switch_to
.bpoint:
pop ebp
pop edi
pop esi
;sti
ret