操作系统课程设计说明
➢ 堆栈的概念
• 传统的进程由PCB、代码段、数据段和堆栈段四部分 组成,但很多系统中把堆栈包含在数据段中。
• 引入线程后,每个线程都必须有自己的私有堆栈。 • CPU切换时,要进行堆栈的切换,从而使新进程(或
新线程)可以把信息保存在自己的堆栈中,而不是老 进程(或线程)的堆栈中。
• CPU正在使用的堆栈被称作现行堆栈,它的栈顶指针 存放在CPU的栈顶指针寄存器中(如SS:ESP)。
void f2(void) { ……
putchar(‘b’); ……. }
/* 创建1#、2#线程 */ create("f1",(codeptr)f1,1024);
create("f2 */
swtch(); printf("\n Multi_task system terminated. \n"); }
➢编程环境
• 16位的DOS模式:内存地址20位 • Turbo C 2.0
➢DOS的内存管理
• 地址线为20根,即物理地址为20位;
内存
0
• 内存空间不超过1M; • 字长为16位; • 分段存储管理方式:
code
0
代码
L1-1
每段长度不超过216B;
data
• 段表用寄存器的方式来实现:
0
数据
栈顶指针
用段地址和偏移 (即2个无符号 整数)表示
char state; /* 线程状态:执行、就绪、阻塞 */
char name[10]; /* 线程的外部标识符 */
} tcb[NTCB]; /*NTCB是系统允许的最多任务数*/
➢线程控制块
#define FINISHED 0
#define RUNNING 1
结束地址
先从对应的单元 中取出信息; 再将 esp加上2个 字节;
➢线程控制块
#define NTCB 5 struct TCB{
用C指针来表示
unsigned char *stack; /* 线程堆栈的起始地址 */
unsigned ss; /* 堆栈段址 */ unsigned sp; /* 堆栈指针 */
char c=‘A’; char *p; p=&c;
内存
①p
0X1000
0X1020 ‘A’
②0X100:0X20
0 0X20 ‘A’ c
data
➢线程的概念
▲线程是进程内一个相对独立的运行单位,一个进 程可以有一个或多个线程(至少有一个),这些 线程共享这个进程的代码、数据及大部分管理信 息,但每个线程有自己的程序计数器、堆栈和线 程控制块。
基于DOS的多任务系统的实现
➢主要任务
• 线程的创建和撤消 • FCFS调度 • 时间片轮转调度 • 同步机制的实现 • 消息缓冲队列 通信机制的实现
void f1(void) {
…… putchar(‘a’); ……. } int current;
main()
{ /* 创建0#线程 */ strcpy(tcb[0].name, "main"); tcb[0].state=RUNNING; current=0;
#define READY
2
#define BLOCKED 3
/* 表示线程处于终止态 或 TCB是空闲状态 */
/* 表示线程处于运行态 */ /* 表示线程处于就绪态 */ /* 表示线程处于阻塞态 */
➢堆栈的概念 X86中信息是从高端往低端入栈的。
堆栈
起始地址
堆栈
起始地址
堆栈
起始地址
栈顶指针
ss:esp
100
设ax=36:
压栈指令
栈顶指针
36
ss:esp
100
出栈指令
36 100
栈顶指针 ss:esp
36
bx
push ax
pop bx
结束地址
结束地址
esp先减2个字节; 再将操作数写到 对应的单元中。
void f2(void) { ……
putchar(‘b’); ……. }
/* 创建1#、2#线程 */ create("f1",(codeptr)f1,1024);
create("f2",(codeptr)f2,1024); /* 启动多个线程的并发执行 */
swtch(); printf("\n Multi_task system terminated. \n"); }
➢DOS的内存管理
• DOS系统,C语言中地址的两 种表达方式:
① 指针 :如 char *p; ② 用两个无符号整数seg:off
分别表示段内存基址的高 16位,段内偏移: 如 0X100:0X20
• Turbo C提供了宏函数,使两种 方式之间可以互相转化:
p=MK_FP(seg,off); seg=FP_SEG(p); off=FP_OFF(p).
➢进程和线程 代码段 main f1 f2
数据段 current tcb[]
线程0 tcb[0]
线程1 tcb[1]
线程2 tcb[2]
堆栈
堆栈
堆栈
… …
• 线程0是进程的首个线程,当进程首次得到CPU时,线 程0就处于执行状态。
• 线程1、线程2要通过线程调度函数,才能得到CPU。
➢ 堆栈的概念
• 拥有资源的基本单位——进程;
• 执行的基本单位(即CPU调度和分派的单位)— —线程。
void f1(void) {
…… putchar(‘a’); ……. } int current;
main()
{ /* 创建0#线程 */ strcpy(tcb[0].name, "main"); tcb[0].state=RUNNING; current=0;
• 堆栈其实是一段内存空间; • 堆栈中最后压入数据的那个单元叫栈顶,该单元的地
址就是栈顶指针; • CPU执行很多指令时都会用到堆栈,比如:
– push 指令; – pop指令; – 函数调用指令 call; – 函数返回指令ret和中断返回指令 iret; – int指令 等等。 • 函数调用的参数及返回地址,程序的局部变量等信息 通常都被保存在进程的堆栈中。
‐CS——代码段内存基址的高16位
L2-1
‐DS——数据段内存基址的高16位 stack
‐SS——堆栈段内存基址的高16位 0 堆栈 L3-1
▲ DOS规定:段在内存的起始地址的低4位必须为0。 1M-1
➢DOS的内存管理 • 二维的逻辑地址:
seg:off 逻辑地址
seg×24+off 物理地址