⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 5 forkϵͳ

📁 一个用于学习的操作系统
💻
字号:
fork系统调用是一个复杂而又重要的过程,主要涉及到进程管理和内存管理两个方面。
首先分配了一页内存作为进程控制块,然后完全把父进程的进程控制快中的内容(一整页,包括内核状态下的堆栈)全部复制给子进程,然后复制父进程的内存(这里用到了写时复制的特性,所以只复制了页目录和页表),然后在根据设置各种控制字段,最后加入到进程列表中参与调度。

父进程的内存过程是比较复杂的,主要由函数copy_page_table实现,mm/memory.c
复制了整个页目录,复制了前768项的页表的页表(如果已经映射),并把属性改为只读。而后边的256项页目录项是完全复制过来的。这样就基本上完成了fork的过程,但是这是父子进程对空间只能读而不能写,这时就形成了写时复制。因为父子进程访问的是同一块物理内存,并且属性为只读,因此当父进程或子进程对内存进行写操作时,会引起0X0E号写页面异常,这是我们可以根据页面异常的地址进行页面复制。系统异常处理的入口是_exc_handler,然后再根据异常号和错误码处理各种异常。具体由do_wp_page实现(mm/memory.c)
//取消地址addr页面的写保护,如果页面共享,则复制页面
void do_wp_page(u32 addr)
{
    addr_t *table_item;
    s32 page_index;
    u32 index;
    addr_t addr_in_page_dir;
    addr_t err_addr;
    
    
    //取消页面的写保护即
    addr_in_page_dir = paddr_to_vaddr(current->tss.cr3) + ((addr >> 20) & 0x0FFC);
    table_item = (addr_t *)(paddr_to_vaddr((*(addr_t *)(addr_in_page_dir) & 0xFFFFF000) 
                 + ((addr >> 10) & 0x0FFC)));    

    
    index = paddr_to_index(((*table_item) & 0xFFFFF000));
    
    printk("mem_map[%d]:%d\n", index, mem_map[index]);   
    if (mem_map[index] == 1) {  //如果页面引用数为1,则说明没有与之共享的页面了
        *table_item |= PAGE_RW;
        
    } else {                    //不然说明有多个进程共享页面       
        mem_map[index]--;    //减少页面引用数
        //获取空闲页面
        page_index = get_free_page();
        if (! page_index) {
            panic("do_wp_page get_free_page\n");
        }        
        
        //复制页面
        err_addr = addr & 0xFFFFF000;
        if (err_addr < PAGE_OFFSET) {  //如果在user区域,则进行地址转换     
            printk("from: %XH, to: %XH\n", paddr_to_vaddr(*table_item) & 0xFFFFF000, index_to_vaddr(page_index));
            memcpy((void *)index_to_vaddr(page_index), (void *)(paddr_to_vaddr(*table_item) & 0xFFFFF000), PAGE_SIZE);
        } else {
            //这里似乎不需要,因为内核不会发生写保护异常的
            panic("kernel do_wp_page\n");
        }
        //复制页面后,建立映射
        *table_item = index_to_paddr(page_index) | 7;               
    }

    __flush_tlb();   //刷新TLB   
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -