Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lab5 ckti #222

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
438 changes: 438 additions & 0 deletions Lab5_log.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie -no-pie -Wno-error
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -m32 -gdwarf-2 -Wa,-divide
# FreeBSD ld wants ``elf_i386_fbsd''
Expand Down Expand Up @@ -181,6 +181,7 @@ UPROGS=\
_usertests\
_wc\
_zombie\
_testcase\

fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS)
Expand Down Expand Up @@ -219,7 +220,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
ifndef CPUS
CPUS := 2
endif
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 $(QEMUEXTRA)
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp $(CPUS) -m 512 -nographic $(QEMUEXTRA)

qemu: fs.img xv6.img
$(QEMU) -serial mon:stdio $(QEMUOPTS)
Expand Down
54 changes: 5 additions & 49 deletions README
Original file line number Diff line number Diff line change
@@ -1,51 +1,7 @@
NOTE: we have stopped maintaining the x86 version of xv6, and switched
our efforts to the RISC-V version
(https://github.com/mit-pdos/xv6-riscv.git)
# BIT网安操作系统Lab5实验文件

xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix
Version 6 (v6). xv6 loosely follows the structure and style of v6,
but is implemented for a modern x86-based multiprocessor using ANSI C.
author: ckti

ACKNOWLEDGMENTS

xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer
to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14,
2000)). See also https://pdos.csail.mit.edu/6.828/, which
provides pointers to on-line resources for v6.

xv6 borrows code from the following sources:
JOS (asm.h, elf.h, mmu.h, bootasm.S, ide.c, console.c, and others)
Plan 9 (entryother.S, mp.h, mp.c, lapic.c)
FreeBSD (ioapic.c)
NetBSD (console.c)

The following people have made contributions: Russ Cox (context switching,
locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin
Clements.

We are also grateful for the bug reports and patches contributed by Silas
Boyd-Wickizer, Anton Burtsev, Cody Cutler, Mike CAT, Tej Chajed, eyalz800,
Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel Filardo, Peter
Froehlich, Yakir Goaron,Shivam Handa, Bryan Henry, Jim Huang, Alexander
Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller, Eddie Kohler, Austin
Liew, Imbar Marinescu, Yandong Mao, Matan Shabtay, Hitoshi Mitake, Carmi
Merimovich, Mark Morrissey, mtasm, Joel Nider, Greg Price, Ayan Shafqat,
Eldar Sehayek, Yongming Shen, Cam Tenny, tyfkda, Rafael Ubal, Warren
Toomey, Stephen Tu, Pablo Ventura, Xi Wang, Keiichi Watanabe, Nicolas
Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng, and Zou Chang Wei.

The code in the files that constitute xv6 is
Copyright 2006-2018 Frans Kaashoek, Robert Morris, and Russ Cox.

ERROR REPORTS

We don't process error reports (see note on top of this file).

BUILDING AND RUNNING XV6

To build xv6 on an x86 ELF machine (like Linux or FreeBSD), run
"make". On non-x86 or non-ELF machines (like OS X, even on x86), you
will need to install a cross-compiler gcc suite capable of producing
x86 ELF binaries (see https://pdos.csail.mit.edu/6.828/).
Then run "make TOOLPREFIX=i386-jos-elf-". Now install the QEMU PC
simulator and run "make qemu".
## Documents and links:
- [Logs](Lab5_log.md)
- [Project_main_Reposistories](https://github.com/EnjunDu/operating_system)
2 changes: 1 addition & 1 deletion defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ int deallocuvm(pde_t*, uint, uint);
void freevm(pde_t*);
void inituvm(pde_t*, char*, uint);
int loaduvm(pde_t*, char*, struct inode*, uint, uint);
pde_t* copyuvm(pde_t*, uint);
pde_t* copyuvm(pde_t*, uint, uint);
void switchuvm(struct proc*);
void switchkvm(void);
int copyout(pde_t*, uint, void*, uint);
Expand Down
20 changes: 12 additions & 8 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ exec(char *path, char **argv)
{
char *s, *last;
int i, off;
uint argc, sz, sp, ustack[3+MAXARG+1];
uint argc, sz, stackbase, sp, ustack[3+MAXARG+1];
struct elfhdr elf;
struct inode *ip;
struct proghdr ph;
Expand Down Expand Up @@ -60,19 +60,19 @@ exec(char *path, char **argv)
end_op();
ip = 0;

// Allocate two pages at the next page boundary.
// Make the first inaccessible. Use the second as the user stack.
sz = PGROUNDUP(sz);
if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
// Allocate user stack at the top of the address space.
sz = PGROUNDUP(sz); //页对齐
if((stackbase = allocuvm(pgdir, KERNBASE - 2 * PGSIZE, KERNBASE - PGSIZE)) == 0) //为用户栈分配空间,从KERNBASE-2*PGSIZE到KERNBASE-PGSIZE
goto bad;
clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
sp = sz;
// clearpteu(pgdir, (char*)(stackbase));
sp = stackbase;
stackbase -= PGSIZE;

// Push argument strings, prepare rest of stack in ustack.
for(argc = 0; argv[argc]; argc++) {
if(argc >= MAXARG)
goto bad;
sp = (sp - (strlen(argv[argc]) + 1)) & ~3;
sp = (sp - (strlen(argv[argc]) + 1)) & ~3; // 4字节对齐
if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
goto bad;
ustack[3+argc] = sp;
Expand All @@ -99,6 +99,10 @@ exec(char *path, char **argv)
curproc->sz = sz;
curproc->tf->eip = elf.entry; // main
curproc->tf->esp = sp;

// Set the stack base for the process.
curproc->stackbase = stackbase;

switchuvm(curproc);
freevm(oldpgdir);
return 0;
Expand Down
4 changes: 4 additions & 0 deletions memlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#define KERNBASE 0x80000000 // First kernel virtual address
#define KERNLINK (KERNBASE+EXTMEM) // Address where kernel is linked

// User address space layout
#define USERTOP 0x7FFFF000 // User address space top, leaving room for stack growth
#define STACKPAGES 8 // Number of pages initially allocated for stack

#define V2P(a) (((uint) (a)) - KERNBASE)
#define P2V(a) ((void *)(((char *) (a)) + KERNBASE))

Expand Down
6 changes: 3 additions & 3 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ int
growproc(int n)
{
uint sz;
struct proc *curproc = myproc();
struct proc *curproc = myproc(); //当前进程

sz = curproc->sz;
sz = curproc->sz; //当前进程的大小
if(n > 0){
if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1;
Expand Down Expand Up @@ -190,7 +190,7 @@ fork(void)
}

// Copy process state from proc.
if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz, curproc->stackbase)) == 0){
kfree(np->kstack);
np->kstack = 0;
np->state = UNUSED;
Expand Down
1 change: 1 addition & 0 deletions proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct proc {
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
uint stackbase; // Base of the stack
};

// Process memory is laid out contiguously, low addresses first:
Expand Down
18 changes: 9 additions & 9 deletions syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
int
fetchint(uint addr, int *ip)
{
struct proc *curproc = myproc();
// struct proc *curproc = myproc();

if(addr >= curproc->sz || addr+4 > curproc->sz)
return -1;
/* if(addr >= curproc->sz || addr+4 > curproc->sz)
return -1; */
*ip = *(int*)(addr);
return 0;
}
Expand All @@ -34,8 +34,8 @@ fetchstr(uint addr, char **pp)
char *s, *ep;
struct proc *curproc = myproc();

if(addr >= curproc->sz)
return -1;
/* if(addr >= curproc->sz)
return -1; */
*pp = (char*)addr;
ep = (char*)curproc->sz;
for(s = *pp; s < ep; s++){
Expand All @@ -49,7 +49,7 @@ fetchstr(uint addr, char **pp)
int
argint(int n, int *ip)
{
return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
return fetchint((myproc()->tf->esp) + 4 + 4 * n, ip);
}

// Fetch the nth word-sized system call argument as a pointer
Expand All @@ -59,12 +59,12 @@ int
argptr(int n, char **pp, int size)
{
int i;
struct proc *curproc = myproc();
// struct proc *curproc = myproc();

if(argint(n, &i) < 0)
return -1;
if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
return -1;
/*if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
return -1; */
*pp = (char*)i;
return 0;
}
Expand Down
52 changes: 52 additions & 0 deletions testcase.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "types.h"
#include "stat.h"
#include "user.h"

// 获取当前栈指针
uint get_stack_pointer() {
uint sp;
asm volatile("movl %%esp, %0" : "=r" (sp));
return sp;
}

// 深度递归调用以测试更大规模的栈增长
void recursion(int depth) {
char buffer[4096]; // 分配4KB的空间,确保每次递归占用整页
memset(buffer, 1 , 4096); // 进行操作避免被优化掉
uint sp = get_stack_pointer();
printf(1, "Recursion depth: %d, stack address: 0x%x\n", depth , sp );

// 在深度达到一定值之前递归
if (depth < 100) {
recursion(depth + 1);
}
}

// 测试深度递归引发栈增长
void test_stack_growth() {
printf(1, "\n=== Test: Stack Growth ===\n");
printf(1, "Starting recursion test...\n");

recursion(1); // 初始递归调用,测试栈增长

printf(1, "Stack recursion test completed.\n");
}

// 测试堆与栈的冲突
void test_stack_heap_collision() {
printf(1, "\n=== Test: Stack-Heap Collision ===\n");
printf(1, "Starting stack-heap collision test...\n");
printf(1, "Allocating 222MB of memory on the heap...\n");
int * p = (int *)malloc(222*1024*1024 - 512*1024);
*p = 1;

printf(1, "Making recursions .\n");
recursion(1); // 初始递归调用,测试栈增长
printf(1, "Stack recursion test completed.\n");
}

int main(int argc, char *argv[]) {
test_stack_growth();
test_stack_heap_collision();
exit();
}
31 changes: 30 additions & 1 deletion trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,36 @@ trap(struct trapframe *tf)
cpuid(), tf->cs, tf->eip);
lapiceoi();
break;


// 新增触发页错误(Page Fault)的情况
case T_PGFLT:

if (rcr2() < USERTOP)// 条件检查:确保页面错误地址在用户栈范围内。
{
cprintf("page error %x ",rcr2());
cprintf("stack pos : %x\n", myproc()->stackbase);
// 为用户栈分配新的页面
if ((myproc()->stackbase = allocuvm(myproc()->pgdir, myproc()->stackbase - 1 * PGSIZE,
myproc()->stackbase)) == 0)
{
myproc()->killed = 1;
}
myproc()->stackbase-=PGSIZE; // 更新用户栈的栈顶位置
cprintf("create a new page %x\n", myproc()->stackbase);
//clearpteu(myproc()->pgdir, (char *) (myproc()->stackbase - PGSIZE));
if (myproc()->stackbase > KERNBASE - 1)
{
myproc()->killed = 1;
cprintf("There is no space for the stack\n");
exit();
}
return;
}
else
{
myproc()->killed = 1;
break;
}
//PAGEBREAK: 13
default:
if(myproc() == 0 || (tf->cs&3) == 0){
Expand Down
34 changes: 28 additions & 6 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,21 +224,25 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
char *mem;
uint a;

//边界检查:确保新的进程大小不超过KERNBASE
if(newsz >= KERNBASE)
return 0;
if(newsz < oldsz)
return oldsz;

a = PGROUNDUP(oldsz);
for(; a < newsz; a += PGSIZE){
mem = kalloc();
a = PGROUNDUP(oldsz); // 页对齐
for(; a < newsz; a += PGSIZE) // 按页分配内存
{
mem = kalloc(); // 为每页分配物理内存
if(mem == 0){
cprintf("allocuvm out of memory\n");
cprintf("The stack have grown into the heap\n");
deallocuvm(pgdir, newsz, oldsz);
return 0;
}
memset(mem, 0, PGSIZE);
if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0){
memset(mem, 0, PGSIZE); //清空原有数据
if(mappages(pgdir, (char*)a, PGSIZE, V2P(mem), PTE_W|PTE_U) < 0) // 映射
{
cprintf("allocuvm out of memory (2)\n");
deallocuvm(pgdir, newsz, oldsz);
kfree(mem);
Expand Down Expand Up @@ -313,7 +317,7 @@ clearpteu(pde_t *pgdir, char *uva)
// Given a parent process's page table, create a copy
// of it for a child.
pde_t*
copyuvm(pde_t *pgdir, uint sz)
copyuvm(pde_t *pgdir, uint sz, uint stackbase)
{
pde_t *d;
pte_t *pte;
Expand All @@ -337,6 +341,24 @@ copyuvm(pde_t *pgdir, uint sz)
goto bad;
}
}

// Copy the stack
for(i = stackbase; i < KERNBASE - PGSIZE; i += PGSIZE){
if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
panic("copyuvm: pte should exist");
if(!(*pte & PTE_P))
panic("copyuvm: page not present");
pa = PTE_ADDR(*pte);
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
goto bad;
memmove(mem, (char*)P2V(pa), PGSIZE);
if(mappages(d, (void*)i, PGSIZE, V2P(mem), flags) < 0) {
kfree(mem);
goto bad;
}
}

return d;

bad:
Expand Down