1. 宏总结:
?
/threads/thread.h
#define MachineStateSize 18 #define StackSize (4 * 1024) ? ? ?
/userprog/addrspace.h #define UserStackSize /userprog/bitmap.h #define BitsInByte 8 #define BitsInWord 32 ?
/userprog/syscall.h #define SC_Halt #define SC_Exit #define SC_Exec #define SC_Join #define SC_Create #define SC_Open #define SC_Read #define SC_Write #define SC_Close #define SC_Fork #define SC_Yield 10
#define ConsoleInput 0 #define ConsoleOutput 1 ?
/machine/disk.h #define SectorSize #define NumTracks per disk ?
/machine/disk.cc
#define MagicNumber 0x456789ab #define MagicSize ?
/machine/machine.h
#define PageSize SectorSize // set the page size equal to the disk sector size, for simplicity
#define NumPhysPages 32
#define MemorySize (NumPhysPages * PageSize)
sizeof(int)
#define DiskSize (MagicSize + (NumSectors * SectorSize))
128 // number of bytes per disk sector 32 // number of tracks per disk
(SectorsPerTrack * NumTracks) // total # of sectors
#define SectorsPerTrack 32 // number of sectors per disk track #define NumSectors
0 1 2 3 4 5 6 7 8 9
1024
/threads/thread.cc
#define STACK_FENCEPOST 0xdeadbeef
#define StackReg 29 // User's stack pointer #define RetAddrReg #define HiReg #define LoReg #define PCReg
31 // Holds return address for procedure calls
#define NumGPRegs 32 // 32 general purpose registers on MIPS
32 // Double register to hold multiply result 33
34 // Current program counter
#define NextPCReg 35 // Next program counter (for branch delay) #define PrevPCReg 36 // Previous program counter (for debugging) #define LoadReg
37 // The register target of a delayed load.
#define LoadValueReg 38 // The value to be loaded by a delayed load. #define BadVAddrReg 39 // The failing virtual address on an exception #define NumTotalRegs 40 ?
/machine/mipssim.h #define OP_???? ?
/filesys/directory.h #define FileNameMaxLen <= 9 characters long ?
/filesys/filehdr.h #define NumDirect ?
/filesys/filesys.cc #define FreeMapSector
0
#define DirectorySector 1
#define FreeMapFileSize (NumSectors / BitsInByte) #define NumDirEntries
10
(sizeof(DirectoryEntry) * NumDirEntries)
#define DirectoryFileSize ?
2. /nachos-3.4/code/
A. Makefile.dep:
GNU-Makefile的一部分,指定了Makefile系统环境中相互依赖的部分,还指定了平台,此处为Linux; # also, Linux HOST = -DHOST_i386 LDFLAGS =
B. Makefile.common:
1) 包含了nachos提供的所有的基本程序(baseline code),无论何时需要添加 .h
和 .cc 文件,都需要在相应的_H、_C和_O列表中修改; 2) 任务的依赖关系有: /filesys/fstest.cc
#define TransferSize 10 // make it small, just to be difficult
((SectorSize - 2 * sizeof(int)) / sizeof(int))
#define MaxFileSize (NumDirect * SectorSize)
9
// for simplicity, we assume file names are
#define TransferSize 10 // make it small, just to be difficult
a) threads在所有程序之前; b) userprog在vm之前运行;
c) userprog可在filesys之前或之后运行,但是如果先运行userprog,必须定
义filesys_stub;
3) 当修改程序的架构时,应该在相应的子文件夹下执行make depend,程序会自动
修改Makefile并更新依赖性;
4) CFLAGS = -g -Wall -Wshadow $(INCPATH) $(DEFINES) $(HOST) –DCHANGED:
-g:在可执行程序中包含标准调试信息;
-Wall:允许发出Gcc提供的所有有用的报警信息;
-Wshadow:当局部变量遮蔽(shadow)了参数、全局变量或其他局部变量时,该选项会给我们警告信息; -DCHANGED:
5) Depend函数:
6) –DTHREADS:Dthreads is an efficient deterministic multithreading system for unmodified
C/C++ applications that replaces the pthreads library.
C. Makefile:
1) Lpr:将档案或是由标准输入送进来的资料送到打印机贮列之中,打印机管理程序
lpd 会在稍后将这个档案送给适当的程序或装置处理。lpr 可以用来将料资送给本地或是远端的主机来处理。; 2) Make nachos: D.
3. /nachos-3.4/code/threads/
A. Makefile:
和线程任务有关的Makefile,首先必须完成线程任务。 B. Utility.cc:
调试代码,通过命令行参数允许用户控制是否打印调试信息;
1) DebugInit():只能打印flaglist的调试信息,即确定打印调试信息的部分; 2) Debug():打印调试信息; C. Main.cc:
初始化操作系统内核的引导程序代码。允许直接调用内部的操作系统函数来简化调试和测试。实际上,这些引导程序代码只是初始化数据结构,然后开启一个用户线程来打印注册提示。 1) 相关编译选项:
nachos -d
-s -x
-p
-n
-d causes certain debugging messages to be printed (cf. utility.h) -rs causes Yield to occur at random (but repeatable) spots -z prints the copyright message
USER_PROGRAM
-s causes user programs to be executed in single-step mode -x runs a user program -c tests the console
FILESYS
-f causes the physical disk to be formatted -cp copies a file from UNIX to Nachos -p prints a Nachos file to stdout
-r removes a Nachos file from the file system -l lists the contents of the Nachos directory -D prints the contents of the entire file system -t tests the performance of the Nachos file system
NETWORK
-n sets the network reliability
-m sets this machine's host id (needed for the network)
-o runs a simple test of the Nachos network software
备注:直到完成相关任务时这些选项才会起作用
2) Main():操作系统内核的启动代码,工作有检查命令行参数,初始化数据结构,以
及选择性地调用测试程序;
3) Main()函数最后调用CurrentThread->Finish()函数,是因为nachos相对于
宿主机来说只是一个程序,直接exit(0)会导致nachos退出,但是nachos系统中可能有等待线程,所以我们切换到这些线程告诉它们主线程已经结束,防止它们返回。
D. system.h:
定义了nachos所用的全局变量; E. system.cc:
1) 定义了所有的全局数据结构,并进行初始化和分配空间;
Thread *currentThread; Scheduler *scheduler; Interrupt *interrupt; Statistics *stats; Timer *timer;
// the thread we are running now // the ready list // interrupt status // performance metrics // the hardware timer device, // for invoking context switches
Thread *threadToBeDestroyed; // the thread that just finished
2) 定义了Nachos两个函数:Initialize()和Cleanup();
a) Initialize():初始化nachos的全局数据结构,诠释命令行参数; b) Cleanup():终止nachos,释放全局数据结构;
3) TimerInterruptHandler():Timer device周期性(每个TimerTicks一次)中
断CPU,然后每次会调用此函数,同时关闭中断。直接调用Yield()会挂起interrupt handler,而不是被中断的线程。不同的是,我们设置一个flag,所以当完成interrupt handler时,看起来就像是被中断的线程在中断时刻调用了
Yield()。参数Int dummy(虚拟/假的)是因为interrupt handler都需要一个参数,无论是否需要;
F. thread.cc(h):
1) 管理线程的数据结构,一个现场的状态包括pc、寄存器和执行栈;
a) 为每个栈分配固定的空间,所以要防止栈溢出,动态分配数据结构空间; b) 调试是否是栈空间太小导致segmentation fault,可以增加占空间
ThreadStackSize;
c) Fork一个线程包括:先分配一个数据结构空间,然后调用fork()函数; 2) 线程状态(ThreadStatus)包括:刚创建、运行中、准备好、阻塞; 3) 线程控制块(class Thread):表示一个线程的执行状况,包括:
a) 一个执行栈,用来保存活跃记录,以及不运行的时候保存CPU寄存器; b) 某些用户线程包括一个用户地址空间,内核线程的地址空间为NULL; c) 基本操作包括:Fork(调用内置函数stackAllocate())、Yield、Sleep、
Finish、CheckOverflow、setStatus、getName、Print;
d) 用户线程包括两套CPU寄存器,分别保存执行用户和内核代码的状态; 4) Thread():初始化一个线程控制块,之后就可以调用Fork函数,参数为线程名
字,是一个任意字符串,用来调试;
5) ~Thread():释放一个线程空间,参数是线程名字。但是current线程不能直接
删除自己,因为它运行在我们将要删除的栈空间。同时主线程不能删除栈空间,因为主线程空间是我们自动获取的,它是启动nachos的一部分;
6) Fork():调用(*func)(arg),使得caller和callee可以并发执行。虽然arg
只是一个int型变量,但是可以把想要传递的参数打包成一个数据结构,然后把它的指针作为int参数。执行步骤包括: a) 分配栈空间;
b) 初始化栈使得switch函数可以运行此程序; c) 将线程放入就绪队列;
7) CheckOverflow():nachos不会捕获所有的溢出情况,所以程序仍然可能因为溢
出挂掉。
8) Finish():当一个fork线程执行完毕被ThreadRoot调用。但是我们没有立即释
放线程数据结构空间,因为该线程仍在运行切还在其栈空间。相反,我们设置“threadToBeDestroyed”,使得我们在不同的线程上下文环境时,调度器可以调用析构函数。我们关闭中断,使得设置“threToBeDestroyed”和sleep之间没有时间片;
9) Yield():当有其它就绪线程时刻放弃CPU资源,并把当前线程放入就绪队列队
首使得可以被再次调度。如果没有就绪队列则立即返回。关闭中断,使得检查就绪线程队列和切换上下文可以原子操作完成。返回之后,立即设置中断到之前状态,以免被其他中断操作影响;
10) Sleep():等待一个同步变量而挂起并让出CPU。最后,某个线程会唤醒此线程,
并放入就绪队列可以被再次调度。没有就绪线程则调用Interrupt::Idle函数,表明CPU空闲,直到IO中断使得某个线程再次运行。关闭中断保证取出就绪队列线程和切换上下文是原子操作;
11) ThreadFinish、InterruptEnable和ThreadPrint函数都是伪函数,因为C++不允
许指针指向成员函数。所以,创建伪C函数可以使用指针调用成员函数; 12) StackAllocate():分配和初始化执行栈,为ThreadRoot函数的栈框架,使得可
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库nachos代码阅读--xq在线全文阅读。
相关推荐: