一、目的
熟悉 Minix 操作系统的进程管理
学习 Unix 风格的内存管理
二、内容与设计思想
修改Minix3.1.2a的进程管理器,改进brk系统调用的实现,使得分配给进程的数据段+栈段空间耗尽时,brk系统调用给该进程 分配一个更大的内存空间,并将原来空间中的 数据复制至新分 配的内存空间,释放原来的内存空间,并通知内核映射新分配的内存段。
三、使用环境
Minix,Moba
四、实验过程
1、完成安装minix3.1.2系统并配置相关设置。
要先编译Minix再修改内核。
2、PM是用户进程,printf结果显示在虚拟机下,可以不需要串口输出。
相关的函数
alloc_mem 分配内存
sys_abscopy 拷贝内存内容
free_mem 释放内存
sys_newmap 通知内核,注册内存段
用户调用brk函数针对的是虚拟地址,而minix最底层内存管理是物理地址,不能混淆。
需要小心处理clicks 和 bytes的单位换算和对齐。
3、修改/usr/src/servers/pm/alloc.c 中的 alloc_mem 函数,把 first-fit 修改成 best-fit,即分配 内存之前,先遍历整个空闲内存块列表,找到最小最佳匹配的空闲块。
PUBLIC phys_clicks alloc_mem(clicks)
phys_clicks clicks; /* amount of memory requested */
{
register struct hole *hp, *prev_ptr, *best, *prev_best;
phys_clicks old_base;
int flag=0;
do {
prev_ptr = NIL_HOLE;
hp = hole_head;
while (hp != NIL_HOLE && hp->h_base < swap_base) //遍历空闲链表
{
if(hp->h_len >= clicks && ((hp->h_len < best->h_len)||(flag==0)))
//当找到合适的空闲块时,先让best等于这个比他大的块,当找到更小的则替换。
{
best=hp;
prev_best=prev_ptr;
flag=1;
}
prev_ptr = hp;
hp = hp->h_next;
}
} while (swap_out()); /* try to swap some other process out */
if (flag==1) //能找到
{
old_base = best->h_base; //记录块的起始位置
best->h_base += clicks; //best起始位置发生了变化,等于其实位置加分配的clicks大小。
best->h_len -= clicks; 块的大小等于原长度-被分配的长度
/* Remember new high watermark of used memory. */
if(best->h_base > high_watermark)
high_watermark = best->h_base;
/* Delete the hole if used up completely. */
if (best->h_len == 0) del_slot(prev_best, best);
/* Return the start address of the acquired block. */
return(old_base);
}
return(NO_MEM);
}
4、修改/usr/src/servers/pm/break.c中的adjust函数,并增加了一个allocate_new_mem局部函数在adjust函数中调用。brk系统调用流程:
do_brk函数计算数据段新的边界,然后调用adjust函数,adjust函数计算程序当前的空闲空间是否足够分配:
(1)若足够,则调整数据段指针,堆栈指针;通知内核程序的映像发生了变化,返回do_brk函数。
(2)若不够,调用allocate_new_mem函数申请新的足够大的内存空间;将程序现有的数据段贺堆栈段的内容分别拷贝至新内存区域的底部(bottom)和顶部(top);通知内核程序的映像发生了变化;返回do_brk函数。
if (lower < gap_base) {/* data and stack collided */
if (allocate_new_mem(rmp,(phys_clicks)(mem_sp->mem_vir+mem_sp->mem_len-mem_dp->mem_vir)) == 0)
return(ENOMEM);
}
/*=======================================================*
* allocate_new_mem *
*=======================================================*/
PUBLIC int allocate_new_mem(rmp,clicks)
register struct mproc *rmp;
phys_clicks clicks;
{
/* local variables declarations */
register struct mem_map *mem_sp,*mem_dp; /* stack and data structs */
phys_bytes old_bytes,data_bytes,stak_bytes,old_d_abs,new_d_abs,old_s_abs,new_s_abs; /* used to transform between bytes and clicks */
phys_clicks old_clicks,old_base,new_clicks,new_base; /* used to transform the old click to a new one */
phys_clicks data_clicks,new_s_base,old_s_base,stak_clicks; /* used to transform the old stack or data to a new one */
int error; /* used to receive error code */
/* allocation of new memory */
mem_dp = &rmp->mp_seg[D]; /* get data struct */
mem_sp = &rmp->mp_seg[S]; /* get stack struct */
old_clicks = clicks; /* old size */
new_clicks = clicks*2; /* new size */
if ((new_base = alloc_mem(new_clicks))==NO_MEM) return (0); /* get new_base pointer */
/* copy data from original source */
old_base = rmp->mp_seg[D].mem_phys; /* get old_base address */
old_s_base = rmp->mp_seg[S].mem_phys; /* get old_stack_base address */
new_s_base = new_base + new_clicks - mem_sp->mem_len; /* get new_stack_base address */
new_d_abs = (phys_bytes) new_base << CLICK_SHIFT; /* new data address */
old_d_abs = (phys_bytes) old_base << CLICK_SHIFT; /* old data address */
new_s_abs = (phys_bytes) new_s_base << CLICK_SHIFT; /* new stack address */
data_bytes = (phys_bytes) rmp->mp_seg[D].mem_len << CLICK_SHIFT; /* data size (bytes) */
stak_bytes = (phys_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; /* stack size (bytes) */
if ((error=sys_memset(0,new_d_abs,(new_clicks<<CLICK_SHIFT)))!=OK){ /* get a new empty space */
panic(__FILE__,"new mem can't be zero",error);
}
error = sys_abscopy(old_d_abs,new_d_abs,data_bytes); /* copy data from old memory allocation */
if (error < 0 ) panic(__FILE__,"allocate_new_mem can't copy",error); /* error handler */
error = sys_abscopy(old_s_abs,new_s_abs,stak_bytes); /* copy stack from old memory allocation */
if (error < 0 ) panic(__FILE__,"allocate_new_mem can't copy",error); /* error handler */
/* change pointer to fit the current allocation */
rmp->mp_seg[D].mem_phys = new_base; /* change data address to new_base */
rmp->mp_seg[S].mem_phys = new_s_base; /* change data address to new stack base */
rmp->mp_seg[S].mem_vir = mem_dp->mem_vir + new_clicks - mem_sp->mem_len; /* change stack memory address to click-len */
free_mem(old_base,old_clicks); /* free old_base altogether */
return (1);
}
5、(1)进入/usr/src/servers目录,输入make image, 等编译成功之后输入make install 安装新的PM程 序。
(2)进入/usr/src/tools目录,输入make hdboot, 成功之后再键入make install命令安装新的内核程 序。
(3)键入shutdown 命令关闭虚拟机,进入boot monitor界面。设置启动新内核的选项,在提示符键入:newminix(5,start new kernel) {image=/boot/image/3.1.2ar1;boot;}
(4)然后回车,键入save命令保存设置。
(5)为启动菜单中的选择内核版本的键(数字键,可选其 他数字键),3.1.2ar1为在/usr/src/tools目录中输入make install 之后生成的内核版本号,请记 得在/usr/src/tools中执行make install命令之后记录生成的新内核版本号。 5. 输入menu命令,然后敲数字键(上一步骤中设置的数字)启动新内核,登录进minix 3中测试。
但因为我先修改了内核再编译的minix,就出现了问题:
但事已至此,我先尝试用编译好的test1和test2文件直接运行也没有成功,然后我又尝试使用chmod +x ./test1赋予权限,终于成功了。
# ./test1
incremented by 1, total 1
incremented by 2, total 3
incremented by 4, total 7
incremented by 8, total 15
incremented by 16, total 31
incremented by 32, total 63
incremented by 64, total 127
incremented by 128, total 255
incremented by 256, total 511
incremented by 512, total 1023
incremented by 1024, total 2047
incremented by 2048, total 4095
incremented by 4096, total 8191
incremented by 8192, total 16383
incremented by 16384, total 32767
incremented by 32768, total 65535
incremented by 65536, total 131071
incremented by 131072, total 262143
incremented by 262144, total 524287
incremented by 524288, total 1048575
incremented by 1048576, total 2097151
incremented by 2097152, total 4194303
incremented by 4194304, total 8388607
incremented by 8388608, total 16777215
incremented by 16777216, total 33554431
incremented by 33554432, total 67108863
# ./test2
incremented by: 1, total: 1 , result: 760
incremented by: 2, total: 3 , result: 4096
incremented by: 4, total: 7 , result: 4098
incremented by: 8, total: 15 , result: 4102
incremented by: 16, total: 31 , result: 4110
incremented by: 32, total: 63 , result: 4126
incremented by: 64, total: 127 , result: 4158
incremented by: 128, total: 255 , result: 4222
incremented by: 256, total: 511 , result: 4350
incremented by: 512, total: 1023 , result: 4606
incremented by: 1024, total: 2047 , result: 5118
incremented by: 2048, total: 4095 , result: 6142
incremented by: 4096, total: 8191 , result: 8190
incremented by: 8192, total: 16383 , result: 12286
incremented by: 16384, total: 32767 , result: 20478
incremented by: 32768, total: 65535 , result: 36862
incremented by: 65536, total: 131071 , result: 69630
incremented by: 131072, total: 262143 , result: 135166
incremented by: 262144, total: 524287 , result: 266238
incremented by: 524288, total: 1048575 , result: 528382
incremented by: 1048576, total: 2097151 , result: 1052670
incremented by: 2097152, total: 4194303 , result: 2101246
incremented by: 4194304, total: 8388607 , result: 4198398
incremented by: 8388608, total: 16777215 , result: 8392702
incremented by: 16777216, total: 33554431 , result: 16781310
incremented by: 33554432, total: 67108863 , result: 3355852