Nathanaël

纳塔纳埃尔,切莫再想去尝试旧日的清水

0%

lab-10-mmap

lab-mmap

分配vma

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct vma*
vma_alloc()
{
struct proc *p = myproc();
struct vma *v;
for (int i = 0; i < NVMA; i++)
{
v = &p->vma_list[i];
if (v->used == 0)
{
v->used = 1;
return v;
}
}
return 0;
}

sys_mmap系统调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
uint64
sys_mmap()
{
uint64 err_ret = 0xffffffffffffffff;
uint64 addr;
int length, prot, flag, fd, offset;
if (argaddr(0, &addr) < 0 || argint(1, &length) < 0 || argint(2, &prot) < 0 || argint(3, &flag) < 0 || argint(4, &fd) < 0 || argint(5, &offset) < 0)
return err_ret;
addr = 0;
offset = 0;
struct proc *p = myproc();
struct file *f = p->ofile[fd];
if ((prot & PROT_WRITE) && !f->writable && (flag & MAP_SHARED))
{
return 0xffffffffffffffff;
}
if ((prot & PROT_READ) && !f->readable)
{
return 0xffffffffffffffff;
}
struct vma *v = vma_alloc();
filedup(f);
v->file = f;
v->prot = prot;
v->flag = flag;
v->length = length;
v->offset = offset;
v->fd = fd;
v->addr = p->sz;
p->sz += v->length;
//printf("sys_mmap addr:%p p->sz:%p\n",v->addr,p->sz);
return v->addr;
}

sys_munmap系统调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
uint64
sys_munmap()
{
printf("sys_munmap\n");
uint64 addr;
int length;
int cnt = 0;
if (argaddr(0, &addr) < 0 || argint(1, &length) < 0)
return -1;
struct proc *p = myproc();
struct vma *v;
for (int i = 0; i < NVMA; i++)
{
v = &p->vma_list[i];
if (v->used == 0)
continue;
if (addr >= v->addr && addr < v->addr + v->length)
{
printf("addr:%p, length:%x\nv->addr:%p, v->length:%x, v->addr + v->length:%x\n", addr, length, v->addr, v->length, v->addr + v->length);
if (length >= v->length)
{
length = v->length;
}
v->addr = v->addr + length;
v->length = v->length - length;
if ((v->prot & PROT_WRITE) && (v->flag & MAP_SHARED))
{
filewrite(v->file, addr, length);
}
uvmunmap(p->pagetable, addr, length / PGSIZE, 1);
if (v->length == 0)
{
fileclose(v->file);
v->used = 0;
}
break;
}
cnt += 1;
}
if (cnt == NVMA)
return -1;
return 0;
}

处理缺页中断

1
2
3
4
5
6
7
8
//usertrap
...
else if(r_scause() == 13 || r_scause() == 15) {
uint64 pg_fault_va = r_stval();
if(mmap_alloc(pg_fault_va) != 0) {
p->killed = 1;
}
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
uint
mmap_alloc(uint64 pg_fault_va)
{
struct proc *p = myproc();
struct vma *v;
struct file* file;
int cnt = 0;
if (pg_fault_va >= p->sz)
return -1;
if (pg_fault_va < p->trapframe->sp)
return -1;
for (int i = 0; i < NVMA; i++)
{
v = &p->vma_list[i];
if (v->used == 1)
{
if (pg_fault_va >= v->addr && pg_fault_va < (v->addr + v->length))
{
//printf("i:%d, v->length:%x\n",i,v->length);
uint flags = 0;
flags |= PTE_U;
if (v->prot & PROT_READ)
flags |= PTE_R;
if (v->prot & PROT_WRITE)
flags |= PTE_W;
if (v->prot & PROT_EXEC)
flags |= PTE_X;
char *mem = kalloc();
if (mem == 0)
return -1;
memset(mem, 0, PGSIZE);
uint64 align_va = PGROUNDDOWN(pg_fault_va);
// printf("fault va:%p, align va:%p, v->addr:%p\nalign_va - v->addr: %p\n",pg_fault_va,align_va,v->addr,align_va - v->addr);
if (mappages(p->pagetable, align_va, PGSIZE, (uint64)mem, flags) != 0)
{
kfree(mem);
return -1;
}
file = v->file;
ilock(file->ip);
readi(file->ip, 0, (uint64)mem,(align_va - v->addr), PGSIZE);
// printf("\n",align_va - v->addr);
iunlock(file->ip);
break;
}
}
cnt += 1;
// printf("trap cnt:%d\n",cnt);
}
if(cnt == NVMA)
{
return -1;
}
return 0;
}

修改exit(),结束进程时清理vma,当区域被标记为MAP_SHAREDPROT_WRITE时,需要写回文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void
exit(int status)
{
struct proc *p = myproc();
struct vma* v;
if(p == initproc)
panic("init exiting");

for(int i = 0; i < NVMA; ++i)
{
v = &p->vma_list[i];
if(v->used)
{
if((v->flag & MAP_SHARED) && (v->prot & PROT_WRITE))
filewrite(v->file, v->addr, v->length);
fileclose(v->file);
uvmunmap(p->pagetable,v->addr, v->length/PGSIZE, 1);
v->used = 0;
}
}
...
}

修改fork(),给子进程复制一份相同的vma。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 ...
pid = np->pid;

for(int i = 0; i < NVMA; ++i)
{
v = &p->vma_list[i];
nv = &np->vma_list[i];
if(v->used)
{
nv->addr = v->addr;
nv->fd = v->fd;
nv->file = v->file;
nv->flag = v->flag;
nv->length = v->length;
nv->offset = v->offset;
nv->prot = v->prot;
nv->used = v->used;
filedup(nv->file);
}
}

np->state = RUNNABLE;
...