操作系统第二十六章作业
1.开始,我们来看一个简单的程序,“loop.s”。首先,阅读这个程序,看看你是否能理解它:cat loop.s。然后,用这些参数运行它:
./x86.py -p loop.s -t 1 -i 100 -R dx
这指定了一个单线程,每 100条指令产生一个中断,并且追踪寄存器%dx。你能弄清楚 %dx在运行过程中的值吗?你有答案之后,运行上面的代码并使用-c 标志来检查你的答案。注意答案的左边显示了右侧指令运行后寄存器的值(或内存的值)。
先看一下loop.s的代码:
.main
.top
sub $1,%dx
test $0,%dx
jgte .top
halt
这个代码是将%dx的值减1,与0作比较,若大于等于零就重复以上操作,否则就跳出循环并结束。
dx初值为0,执行第一条指令后变为-1,执行第二条指令后不变,执行第三条指令后也不变,但是因为-1 < 0,所以不会跳转到.top,而是继续向下执行halt结束。
-c 标志查看答案:
结果正确。
2.现在运行相同的代码,但使用这些标志:
./x86.py -p loop.s -t 2 -i 100 -a dx=3,dx=3 -R dx
这指定了两个线程,并将每个%dx 寄存器初始化为 3。%dx 会看到什么值?使用-c 标志运行以查看答案。多个线程的存在是否会影响计算?这段代码有竞态条件吗?
- 线程0和线程1的dx初值都为x,线程0先运行;
- 执行完sub指令后dx变为2,之后执行test指令与jgte指令,这里dx不发生变化,但是因为2>=0,满足跳转条件,所以会跳转到.top;
- 第二次执行完上述三条指令后dx变为1,仍大于等于0,满足跳转条件,所以会跳转到.top;
- 第三次执行完上述三条指令后dx变为0,仍大于等于0,满足跳转条件,所以还会跳转到.top;
- 第四次执行完上述三条指令后dxi变为-1,小于0,不满足跳转条件,继续执行halt指令后结束;
- 由于线程之间是独立的,所以线程1中dx初值也是3,之后的情况与线程0一样,不再赘述。
-c 标志查看答案:
结果正确。
- 多个线程的存在会影响计算,因为可能在不期望中断的地方发生线程切换,造成意想不到的后果
- 这段代码没有竞态条件(计算的正确性取决于多个线程的交替执行时序/ 程序运行顺序的改变会影响最终结果)。因为 -i 参数为100,就是每执行100条指令才中断一次。而线程0和线程1运行完毕所执行的指令条数少于100,不论哪个线程先运行,在运行完之前都不会被打断,不会影响最终结果,所以没有竞态条件。
3.现在运行以下命令:
./x86.py -p loop.s -t 2 -i 3 -r -a dx=3,dx=3 -R dx
这使得中断间隔非常小且随机。使用不同的种子(-s) 来查看不同的交替。中断频率是否会改变这个程序的行为?
有 -r 说明中断频率是随机的,但是 -i 3则表示,最多3条指令就会发生线程切换。也就是说,同时使用 -i 3与 -r 参数,执行完1、2、3条指令后都可能发生线程切换。这个虽然没有在README文件中说明,但是通过换用不同的-i参数观察程序输出结果,可以验证以上说法。
-
-s 0
-
-s 1
-
-s 2
-
-s 3
-
-s 4
换用不同的 -s 程序行为各不相同,说明中断频率的改变的确会影响这个程序的行为。
4.接下来我们将研究一个不同的程序(looping-race-nolock.s)。该程序访问位于内存地址 2000 的共享变量。简单起见,我们称这个变量为 x。使用单线程运行它,并确保你了解它的功能,如下所示:
./x86.py -p looping-race-nolock.s -t 1 -M 2000
在整个运行过程中,x(即内存地址为 2000)的值是多少?使用-c来检查你的答案。
先看一下looping-race-nolock.s
的内容:
# assumes %bx has loop count in it
.main
.top
# critical section (临界区)
mov 2000, %ax # get 'value' at address 2000
add $1, %ax # increment it
mov %ax, 2000 # store it back
# see if we're still looping
sub $1, %bx
test $0, %bx
jgt .top
halt
此程序是将地址2000内的值自加1后再存回地址2000处,之后将寄存器bx的值减1并和0作比较,如果大于0,就跳转到.top(循环),否则执行halt线程结束运行。
- 地址2000处初值为0,执行完第一条指令后,寄存器ax值为为0;
- 执行add指令,寄存器ax值自加1,变为1;
- 执行mov指令,将寄存器ax值存回地址2000,所以执行完这条指令后,地址2000处的值为1;
- 寄存器bx初值为0,执行完sub指令,寄存器bx值自减1,变为-1;
- 执行test指令,将寄存器bx值与0作比较;
- -1<0,不满足跳转条件大于0,所以不会跳转到.top处;
- 执行halt指令,线程结束运行。
-R标志追踪寄存器ax和bx,并使用 -c 标志查看答案: