знаю, боян, но все же, почему не работает функция fork() в
руководстве по разработке ядра James Molloy?
на английском osdev есть несколько таких вопросов, но лично мне ни один из предложенных вариантов не помог
функции fork() и clone_directory (видимо, виновата именно она):
Код:
int fork()
{
// We are modifying kernel structures, and so cannot be interrupted.
asm volatile("cli");
// Take a pointer to this process' task struct for later reference.
task_t *parent_task = (task_t*)current_task;
// Clone the address space.
page_directory_t *directory = clone_directory(current_directory);
// Create a new process.
task_t *new_task = (task_t*)kmalloc(sizeof(task_t));
new_task->id = next_pid++;
new_task->esp = new_task->ebp = 0;
new_task->eip = 0;
new_task->page_directory = directory;
current_task->kernel_stack = kmalloc_a(KERNEL_STACK_SIZE);
new_task->next = 0;
// Add it to the end of the ready queue.
// Find the end of the ready queue...
task_t *tmp_task = (task_t*)ready_queue;
while (tmp_task->next)
tmp_task = tmp_task->next;
// ...And extend it.
tmp_task->next = new_task;
// This will be the entry point for the new process.
u32int eip = read_eip();
// We could be the parent or the child here - check.
if (current_task == parent_task)
{
// We are the parent, so set up the esp/ebp/eip for our child.
u32int esp; asm volatile("mov %%esp, %0" : "=r"(esp));
u32int ebp; asm volatile("mov %%ebp, %0" : "=r"(ebp));
new_task->esp = esp;
new_task->ebp = ebp;
new_task->eip = eip;
// All finished: Reenable interrupts.
asm volatile("sti");
// And by convention return the PID of the child.
return new_task->id;
}
else
{
// We are the child - by convention return 0.
return 0;
}
}
Код:
page_directory_t *clone_directory(page_directory_t *src)
{
u32int phys;
// Make a new page directory and obtain its physical address.
page_directory_t *dir = (page_directory_t*)kmalloc_ap(sizeof(page_directory_t), &phys);
// Ensure that it is blank.
memset(dir, 0, sizeof(page_directory_t));
// Get the offset of tablesPhysical from the start of the page_directory_t structure.
u32int offset = (u32int)dir->tablesPhysical - (u32int)dir;
// Then the physical address of dir->tablesPhysical is:
dir->physicalAddr = phys + offset;
// Go through each page table. If the page table is in the kernel directory, do not make a new copy.
int i;
for (i = 0; i < 1024; i++)
{
if (!src->tables[i])
continue;
if (kernel_directory->tables[i] == src->tables[i])
{
// It's in the kernel, so just use the same pointer.
dir->tables[i] = src->tables[i];
dir->tablesPhysical[i] = src->tablesPhysical[i];
}
else
{
// Copy the table.
u32int phys;
dir->tables[i] = clone_table(src->tables[i], &phys);
dir->tablesPhysical[i] = phys | 0x07;
}
}
return dir;
}