├── .gitignore ├── Chapter-14 ├── 14.1.c ├── 14.4.c ├── 14.5.c ├── 14.6.c ├── 14.7.c └── Chapter-14-Homework-Answers.md ├── Chapter-15 └── Chapter-15-Homework-Answers.md ├── Chapter-16 └── Chapter-16-Homework-Answers.md ├── Chapter-17 └── Chapter-17-Homework-Answers.md ├── Chapter-18 └── Chapter-18-Homework-Answers.md ├── Chapter-19 ├── 1.png ├── 19.2.c ├── 19.3.py ├── 19.7.c └── Chapter-19-Homework-Answers.md ├── Chapter-20 └── Chapter-20-Homework-Answers.md ├── Chapter-22 ├── Chapter-22-Homework-Answers.md ├── genLocalRandom.py └── genRandom.py ├── Chapter-26 └── Chapter-26-Homework-Answers.md ├── Chapter-28 └── Chapter-28-Homework-Answers.md ├── Chapter-37 ├── 1.png └── Chapter-37-Homework-Answers.md ├── Chapter-38 └── Chapter-38-Homework-Answers.md ├── Chapter-39 ├── 39.1.c ├── 39.2.c ├── 39.3.c ├── 39.4.c └── Chapter-39-Homework-Answers.md ├── Chapter-4 └── Chapter-4-Homework-Answers.md ├── Chapter-40 └── Chapter-40-Homework-Answers.md ├── Chapter-49 └── Chapter-49-Homework-Answers.md ├── Chapter-5 ├── 5.1.c ├── 5.2.c ├── 5.3.c ├── 5.4.c ├── 5.5.c ├── 5.6.c ├── 5.7.c ├── 5.8.c └── Chapter-5-Homework-Answers.md ├── Chapter-6 ├── 6.1.c ├── 6.2.c ├── 6.3.c └── Chapter-6-Homework-Answers.md ├── Chapter-7 ├── 1.gif └── Chapter-7-Homework-Answers.md ├── Chapter-8 └── Chapter-8-Homework-Answers.md ├── Chapter-9 └── Chapter-9-Homework-Answers.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /Chapter-14/14.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | int * p = NULL; 5 | free(p); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /Chapter-14/14.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | int * p = (int *)malloc(sizeof(int)); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /Chapter-14/14.5.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | int * data = (int *)malloc(100*sizeof(int)); 5 | data[100] = 0; 6 | free(data); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /Chapter-14/14.6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main() 4 | { 5 | int * p = (int *)malloc(100*sizeof(int)); 6 | p[1] = 10; 7 | p[90] = 20; 8 | free(p); 9 | printf("%d %d\n", p[1],p[90]); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter-14/14.7.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | int * p = (int *)malloc(100*sizeof(int)); 5 | free(p+50); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /Chapter-14/Chapter-14-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | [答案代码](14.1.c) 3 | ```C 4 | #include 5 | int main() 6 | { 7 | int * p = NULL; 8 | free(p); 9 | return 0; 10 | } 11 | ``` 12 | 执行结果 13 | ``` 14 | [testjz@localhost OS_test]$ ./14.1 15 | ``` 16 | 无任何输出或者错误提示 17 | 18 | * **问题 2 答案** 19 | 执行结果 20 | ``` 21 | (gdb) run 22 | Starting program: /home/testjz/OS_test/./14.1 23 | [Inferior 1 (process 28177) exited normally] 24 | ``` 25 | 26 | * **问题 3 答案** 27 | 执行结果 28 | ``` 29 | [testjz@localhost OS_test]$ valgrind --leak-check=yes ./14.1 30 | ==28207== Memcheck, a memory error detector 31 | ==28207== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 32 | ==28207== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info 33 | ==28207== Command: ./14.1 34 | ==28207== 35 | ==28207== 36 | ==28207== HEAP SUMMARY: 37 | ==28207== in use at exit: 0 bytes in 0 blocks 38 | ==28207== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 39 | ==28207== 40 | ==28207== All heap blocks were freed -- no leaks are possible 41 | ==28207== 42 | ==28207== For lists of detected and suppressed errors, rerun with: -s 43 | ==28207== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 44 | ``` 45 | 看起来什么都没发生。可能我目前的系统可以较好应对释放空指针的情况,所以不会报错。 46 | 47 | * **问题 4 答案** 48 | [答案代码](14.4.c) 49 | ```C 50 | #include 51 | int main() 52 | { 53 | int * p = (int *)malloc(sizeof(int)); 54 | return 0; 55 | } 56 | ``` 57 | gdb执行结果 58 | ``` 59 | (gdb) run 60 | Starting program: /home/testjz/OS_test/./14.2 61 | [Inferior 1 (process 28324) exited normally] 62 | ``` 63 | 看不出问题。 64 | valgrind执行结果 65 | ``` 66 | [testjz@localhost OS_test]$ valgrind --leak-check=yes ./14.2 67 | ==28342== Memcheck, a memory error detector 68 | ==28342== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 69 | ==28342== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info 70 | ==28342== Command: ./14.2 71 | ==28342== 72 | ==28342== 73 | ==28342== HEAP SUMMARY: 74 | ==28342== in use at exit: 4 bytes in 1 blocks 75 | ==28342== total heap usage: 1 allocs, 0 frees, 4 bytes allocated 76 | ==28342== 77 | ==28342== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1 78 | ==28342== at 0x4C29F73: malloc (vg_replace_malloc.c:307) 79 | ==28342== by 0x40053E: main (14.2.c:4) 80 | ==28342== 81 | ==28342== LEAK SUMMARY: 82 | ==28342== definitely lost: 4 bytes in 1 blocks 83 | ==28342== indirectly lost: 0 bytes in 0 blocks 84 | ==28342== possibly lost: 0 bytes in 0 blocks 85 | ==28342== still reachable: 0 bytes in 0 blocks 86 | ==28342== suppressed: 0 bytes in 0 blocks 87 | ==28342== 88 | ==28342== For lists of detected and suppressed errors, rerun with: -s 89 | ==28342== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 90 | ``` 91 | 检测出了内存泄漏问题。 92 | 93 | * **问题 5 答案** 94 | [答案代码](14.5.c) 95 | ```C 96 | #include 97 | int main() 98 | { 99 | int * data = (int *)malloc(100*sizeof(int)); 100 | data[100] = 0; 101 | free(data); 102 | return 0; 103 | } 104 | ``` 105 | gdb执行结果 106 | ``` 107 | (gdb) run 108 | Starting program: /home/testjz/OS_test/./14.5 109 | [Inferior 1 (process 28575) exited normally] 110 | ``` 111 | 看不出问题。 112 | valgrind执行结果 113 | ``` 114 | [testjz@localhost OS_test]$ valgrind --leak-check=yes ./14.5 115 | ==28593== Memcheck, a memory error detector 116 | ==28593== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 117 | ==28593== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info 118 | ==28593== Command: ./14.5 119 | ==28593== 120 | ==28593== Invalid write of size 4 121 | ==28593== at 0x40059D: main (14.5.c:5) 122 | ==28593== Address 0x52051d0 is 0 bytes after a block of size 400 alloc'd 123 | ==28593== at 0x4C29F73: malloc (vg_replace_malloc.c:307) 124 | ==28593== by 0x40058E: main (14.5.c:4) 125 | ==28593== 126 | ==28593== 127 | ==28593== HEAP SUMMARY: 128 | ==28593== in use at exit: 0 bytes in 0 blocks 129 | ==28593== total heap usage: 1 allocs, 1 frees, 400 bytes allocated 130 | ==28593== 131 | ==28593== All heap blocks were freed -- no leaks are possible 132 | ==28593== 133 | ==28593== For lists of detected and suppressed errors, rerun with: -s 134 | ==28593== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 135 | ``` 136 | 检测到无效写入错误。 137 | 138 | * **问题 6 答案** 139 | [答案代码](14.6.c) 140 | ```C 141 | #include 142 | #include 143 | int main() 144 | { 145 | int * p = (int *)malloc(100*sizeof(int)); 146 | p[1] = 10; 147 | p[90] = 20; 148 | free(p); 149 | printf("%d %d\n", p[1],p[90]); 150 | return 0; 151 | } 152 | ``` 153 | 执行结果 154 | ``` 155 | [testjz@localhost OS_test]$ ./14.6 156 | 10 20 157 | ``` 158 | 结果输出了数字的值。 159 | valgrind执行结果 160 | ``` 161 | [testjz@localhost OS_test]$ valgrind --leak-check=yes ./14.6 162 | ==28718== Memcheck, a memory error detector 163 | ==28718== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 164 | ==28718== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info 165 | ==28718== Command: ./14.6 166 | ==28718== 167 | ==28718== Invalid read of size 4 168 | ==28718== at 0x400607: main (14.6.c:9) 169 | ==28718== Address 0x52051a8 is 360 bytes inside a block of size 400 free'd 170 | ==28718== at 0x4C2B06D: free (vg_replace_malloc.c:538) 171 | ==28718== by 0x4005FC: main (14.6.c:8) 172 | ==28718== Block was alloc'd at 173 | ==28718== at 0x4C29F73: malloc (vg_replace_malloc.c:307) 174 | ==28718== by 0x4005CE: main (14.6.c:5) 175 | ==28718== 176 | ==28718== Invalid read of size 4 177 | ==28718== at 0x400611: main (14.6.c:9) 178 | ==28718== Address 0x5205044 is 4 bytes inside a block of size 400 free'd 179 | ==28718== at 0x4C2B06D: free (vg_replace_malloc.c:538) 180 | ==28718== by 0x4005FC: main (14.6.c:8) 181 | ==28718== Block was alloc'd at 182 | ==28718== at 0x4C29F73: malloc (vg_replace_malloc.c:307) 183 | ==28718== by 0x4005CE: main (14.6.c:5) 184 | ==28718== 185 | 10 20 186 | ==28718== 187 | ==28718== HEAP SUMMARY: 188 | ==28718== in use at exit: 0 bytes in 0 blocks 189 | ==28718== total heap usage: 1 allocs, 1 frees, 400 bytes allocated 190 | ==28718== 191 | ==28718== All heap blocks were freed -- no leaks are possible 192 | ==28718== 193 | ==28718== For lists of detected and suppressed errors, rerun with: -s 194 | ==28718== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) 195 | ``` 196 | 检测到了两个无效读取。 197 | 198 | * **问题 7 答案** 199 | [答案代码](14.7.c) 200 | ```C 201 | #include 202 | int main() 203 | { 204 | int * p = (int *)malloc(100*sizeof(int)); 205 | free(p+50); 206 | return 0; 207 | } 208 | ``` 209 | 执行结果 210 | ``` 211 | [testjz@localhost OS_test]$ ./14.7 212 | *** Error in `./14.7': free(): invalid pointer: 0x000000000094a0d8 *** 213 | ======= Backtrace: ========= 214 | /lib64/libc.so.6(+0x81679)[0x7fe6ce387679] 215 | ./14.7[0x4005a5] 216 | /lib64/libc.so.6(__libc_start_main+0xf5)[0x7fe6ce328505] 217 | ./14.7[0x4004b9] 218 | ======= Memory map: ======== 219 | 00400000-00401000 r-xp 00000000 fd:03 4535 /home/testjz/OS_test/14.7 220 | 00600000-00601000 r--p 00000000 fd:03 4535 /home/testjz/OS_test/14.7 221 | 00601000-00602000 rw-p 00001000 fd:03 4535 /home/testjz/OS_test/14.7 222 | 0094a000-0096b000 rw-p 00000000 00:00 0 [heap] 223 | 7fe6c8000000-7fe6c8021000 rw-p 00000000 00:00 0 224 | 7fe6c8021000-7fe6cc000000 ---p 00000000 00:00 0 225 | 7fe6ce0f0000-7fe6ce105000 r-xp 00000000 fd:00 78 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 226 | 7fe6ce105000-7fe6ce304000 ---p 00015000 fd:00 78 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 227 | 7fe6ce304000-7fe6ce305000 r--p 00014000 fd:00 78 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 228 | 7fe6ce305000-7fe6ce306000 rw-p 00015000 fd:00 78 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 229 | 7fe6ce306000-7fe6ce4c9000 r-xp 00000000 fd:00 144179 /usr/lib64/libc-2.17.so 230 | 7fe6ce4c9000-7fe6ce6c9000 ---p 001c3000 fd:00 144179 /usr/lib64/libc-2.17.so 231 | 7fe6ce6c9000-7fe6ce6cd000 r--p 001c3000 fd:00 144179 /usr/lib64/libc-2.17.so 232 | 7fe6ce6cd000-7fe6ce6cf000 rw-p 001c7000 fd:00 144179 /usr/lib64/libc-2.17.so 233 | 7fe6ce6cf000-7fe6ce6d4000 rw-p 00000000 00:00 0 234 | 7fe6ce6d4000-7fe6ce6f6000 r-xp 00000000 fd:00 144172 /usr/lib64/ld-2.17.so 235 | 7fe6ce8dc000-7fe6ce8df000 rw-p 00000000 00:00 0 236 | 7fe6ce8f3000-7fe6ce8f5000 rw-p 00000000 00:00 0 237 | 7fe6ce8f5000-7fe6ce8f6000 r--p 00021000 fd:00 144172 /usr/lib64/ld-2.17.so 238 | 7fe6ce8f6000-7fe6ce8f7000 rw-p 00022000 fd:00 144172 /usr/lib64/ld-2.17.so 239 | 7fe6ce8f7000-7fe6ce8f8000 rw-p 00000000 00:00 0 240 | 7fffb1d06000-7fffb1d27000 rw-p 00000000 00:00 0 [stack] 241 | 7fffb1dc1000-7fffb1dc3000 r-xp 00000000 00:00 0 [vdso] 242 | ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 243 | 已放弃(吐核) 244 | ``` 245 | 直接报错。不需要工具就能找到这个问题。 246 | 247 | * **问题 8 答案** 248 | 这就是类似C++中vector的数据结构。 249 | 特性类似数组,可以实现O(1)的访问或者尾部新增,但是如果空间满了需要realloc的时候需要O(n)的时间。 250 | 251 | * **问题 9 答案** 252 | 无答案。 253 | -------------------------------------------------------------------------------- /Chapter-15/Chapter-15-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 1 -c 4 | 5 | ARG seed 1 6 | ARG address space size 1k 7 | ARG phys mem size 16k 8 | 9 | Base-and-Bounds register information: 10 | 11 | Base : 0x0000363c (decimal 13884) 12 | Limit : 290 13 | 14 | Virtual Address Trace 15 | VA 0: 0x0000030e (decimal: 782) --> SEGMENTATION VIOLATION 16 | VA 1: 0x00000105 (decimal: 261) --> VALID: 0x00003741 (decimal: 14145) 17 | VA 2: 0x000001fb (decimal: 507) --> SEGMENTATION VIOLATION 18 | VA 3: 0x000001cc (decimal: 460) --> SEGMENTATION VIOLATION 19 | VA 4: 0x0000029b (decimal: 667) --> SEGMENTATION VIOLATION 20 | ``` 21 | ``` 22 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 2 -c 23 | 24 | ARG seed 2 25 | ARG address space size 1k 26 | ARG phys mem size 16k 27 | 28 | Base-and-Bounds register information: 29 | 30 | Base : 0x00003ca9 (decimal 15529) 31 | Limit : 500 32 | 33 | Virtual Address Trace 34 | VA 0: 0x00000039 (decimal: 57) --> VALID: 0x00003ce2 (decimal: 15586) 35 | VA 1: 0x00000056 (decimal: 86) --> VALID: 0x00003cff (decimal: 15615) 36 | VA 2: 0x00000357 (decimal: 855) --> SEGMENTATION VIOLATION 37 | VA 3: 0x000002f1 (decimal: 753) --> SEGMENTATION VIOLATION 38 | VA 4: 0x000002ad (decimal: 685) --> SEGMENTATION VIOLATION 39 | ``` 40 | ``` 41 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 3 -c 42 | 43 | ARG seed 3 44 | ARG address space size 1k 45 | ARG phys mem size 16k 46 | 47 | Base-and-Bounds register information: 48 | 49 | Base : 0x000022d4 (decimal 8916) 50 | Limit : 316 51 | 52 | Virtual Address Trace 53 | VA 0: 0x0000017a (decimal: 378) --> SEGMENTATION VIOLATION 54 | VA 1: 0x0000026a (decimal: 618) --> SEGMENTATION VIOLATION 55 | VA 2: 0x00000280 (decimal: 640) --> SEGMENTATION VIOLATION 56 | VA 3: 0x00000043 (decimal: 67) --> VALID: 0x00002317 (decimal: 8983) 57 | VA 4: 0x0000000d (decimal: 13) --> VALID: 0x000022e1 (decimal: 8929) 58 | ``` 59 | 60 | * **问题 2 答案** 61 | ``` 62 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 0 -n 10 -l 930 -c 63 | 64 | ARG seed 0 65 | ARG address space size 1k 66 | ARG phys mem size 16k 67 | 68 | Base-and-Bounds register information: 69 | 70 | Base : 0x0000360b (decimal 13835) 71 | Limit : 930 72 | 73 | Virtual Address Trace 74 | VA 0: 0x00000308 (decimal: 776) --> VALID: 0x00003913 (decimal: 14611) 75 | VA 1: 0x000001ae (decimal: 430) --> VALID: 0x000037b9 (decimal: 14265) 76 | VA 2: 0x00000109 (decimal: 265) --> VALID: 0x00003714 (decimal: 14100) 77 | VA 3: 0x0000020b (decimal: 523) --> VALID: 0x00003816 (decimal: 14358) 78 | VA 4: 0x0000019e (decimal: 414) --> VALID: 0x000037a9 (decimal: 14249) 79 | VA 5: 0x00000322 (decimal: 802) --> VALID: 0x0000392d (decimal: 14637) 80 | VA 6: 0x00000136 (decimal: 310) --> VALID: 0x00003741 (decimal: 14145) 81 | VA 7: 0x000001e8 (decimal: 488) --> VALID: 0x000037f3 (decimal: 14323) 82 | VA 8: 0x00000255 (decimal: 597) --> VALID: 0x00003860 (decimal: 14432) 83 | VA 9: 0x000003a1 (decimal: 929) --> VALID: 0x000039ac (decimal: 14764) 84 | ``` 85 | 界限寄存器的值最小设置为930. 86 | 87 | * **问题 3 答案** 88 | 题目翻译错误,问题应该是问基址寄存器base的最大值。 89 | ``` 90 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 1 -n 10 -l 100 -b 16284 -c 91 | 92 | ARG seed 1 93 | ARG address space size 1k 94 | ARG phys mem size 16k 95 | 96 | Base-and-Bounds register information: 97 | 98 | Base : 0x00003f9c (decimal 16284) 99 | Limit : 100 100 | 101 | Virtual Address Trace 102 | VA 0: 0x00000089 (decimal: 137) --> SEGMENTATION VIOLATION 103 | VA 1: 0x00000363 (decimal: 867) --> SEGMENTATION VIOLATION 104 | VA 2: 0x0000030e (decimal: 782) --> SEGMENTATION VIOLATION 105 | VA 3: 0x00000105 (decimal: 261) --> SEGMENTATION VIOLATION 106 | VA 4: 0x000001fb (decimal: 507) --> SEGMENTATION VIOLATION 107 | VA 5: 0x000001cc (decimal: 460) --> SEGMENTATION VIOLATION 108 | VA 6: 0x0000029b (decimal: 667) --> SEGMENTATION VIOLATION 109 | VA 7: 0x00000327 (decimal: 807) --> SEGMENTATION VIOLATION 110 | VA 8: 0x00000060 (decimal: 96) --> VALID: 0x00003ffc (decimal: 16380) 111 | VA 9: 0x0000001d (decimal: 29) --> VALID: 0x00003fb9 (decimal: 16313) 112 | ``` 113 | 16k-100=16284. 114 | 115 | * **问题 4 答案** 116 | ``` 117 | [testjz@localhost vm-mechanism]$ ./relocation.py -s 1 -n 10 -l 100 -b 499900 -a 500000 -p 500001 -c 118 | 119 | ARG seed 1 120 | ARG address space size 500000 121 | ARG phys mem size 500001 122 | 123 | Base-and-Bounds register information: 124 | 125 | Base : 0x0007a0bc (decimal 499900) 126 | Limit : 100 127 | 128 | Virtual Address Trace 129 | VA 0: 0x0001066e (decimal: 67182) --> SEGMENTATION VIOLATION 130 | VA 1: 0x00067724 (decimal: 423716) --> SEGMENTATION VIOLATION 131 | VA 2: 0x0005d3bf (decimal: 381887) --> SEGMENTATION VIOLATION 132 | VA 3: 0x0001f22e (decimal: 127534) --> SEGMENTATION VIOLATION 133 | VA 4: 0x0003c7a5 (decimal: 247717) --> SEGMENTATION VIOLATION 134 | VA 5: 0x00036de9 (decimal: 224745) --> SEGMENTATION VIOLATION 135 | VA 6: 0x0004f8a4 (decimal: 325796) --> SEGMENTATION VIOLATION 136 | VA 7: 0x00060479 (decimal: 394361) --> SEGMENTATION VIOLATION 137 | VA 8: 0x0000b751 (decimal: 46929) --> SEGMENTATION VIOLATION 138 | VA 9: 0x0000375d (decimal: 14173) --> SEGMENTATION VIOLATION 139 | ``` 140 | 这个数字太随机了,看不出效果。 141 | 142 | * **问题 5 答案** 143 | ``` 144 | 虚拟地址必须小于界限寄存器,值才是有效的。 145 | -------------------------------------------------------------------------------- /Chapter-16/Chapter-16-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 128 -p 512 -b 0 -l 20 -B 512 -L 20 -s 0 -c 4 | ARG seed 0 5 | ARG address space size 128 6 | ARG phys mem size 512 7 | 8 | Segment register information: 9 | 10 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 11 | Segment 0 limit : 20 12 | 13 | Segment 1 base (grows negative) : 0x00000200 (decimal 512) 14 | Segment 1 limit : 20 15 | 16 | Virtual Address Trace 17 | VA 0: 0x0000006c (decimal: 108) --> VALID in SEG1: 0x000001ec (decimal: 492) 18 | VA 1: 0x00000061 (decimal: 97) --> SEGMENTATION VIOLATION (SEG1) 19 | VA 2: 0x00000035 (decimal: 53) --> SEGMENTATION VIOLATION (SEG0) 20 | VA 3: 0x00000021 (decimal: 33) --> SEGMENTATION VIOLATION (SEG0) 21 | VA 4: 0x00000041 (decimal: 65) --> SEGMENTATION VIOLATION (SEG1) 22 | ``` 23 | ``` 24 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 128 -p 512 -b 0 -l 20 -B 512 -L 20 -s 1 -c 25 | ARG seed 1 26 | ARG address space size 128 27 | ARG phys mem size 512 28 | 29 | Segment register information: 30 | 31 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 32 | Segment 0 limit : 20 33 | 34 | Segment 1 base (grows negative) : 0x00000200 (decimal 512) 35 | Segment 1 limit : 20 36 | 37 | Virtual Address Trace 38 | VA 0: 0x00000011 (decimal: 17) --> VALID in SEG0: 0x00000011 (decimal: 17) 39 | VA 1: 0x0000006c (decimal: 108) --> VALID in SEG1: 0x000001ec (decimal: 492) 40 | VA 2: 0x00000061 (decimal: 97) --> SEGMENTATION VIOLATION (SEG1) 41 | VA 3: 0x00000020 (decimal: 32) --> SEGMENTATION VIOLATION (SEG0) 42 | VA 4: 0x0000003f (decimal: 63) --> SEGMENTATION VIOLATION (SEG0) 43 | ``` 44 | ``` 45 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 128 -p 512 -b 0 -l 20 -B 512 -L 20 -s 2 -c 46 | ARG seed 2 47 | ARG address space size 128 48 | ARG phys mem size 512 49 | 50 | Segment register information: 51 | 52 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 53 | Segment 0 limit : 20 54 | 55 | Segment 1 base (grows negative) : 0x00000200 (decimal 512) 56 | Segment 1 limit : 20 57 | 58 | Virtual Address Trace 59 | VA 0: 0x0000007a (decimal: 122) --> VALID in SEG1: 0x000001fa (decimal: 506) 60 | VA 1: 0x00000079 (decimal: 121) --> VALID in SEG1: 0x000001f9 (decimal: 505) 61 | VA 2: 0x00000007 (decimal: 7) --> VALID in SEG0: 0x00000007 (decimal: 7) 62 | VA 3: 0x0000000a (decimal: 10) --> VALID in SEG0: 0x0000000a (decimal: 10) 63 | VA 4: 0x0000006a (decimal: 106) --> SEGMENTATION VIOLATION (SEG1) 64 | ``` 65 | 66 | * **问题 2 答案** 67 | 段0最高的合法虚拟地址是19。 68 | 段1最低的合法虚拟地址是108。 69 | 整个地址空间中对子和最高的合法地址是0和127。 70 | ``` 71 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 128 -p 512 -b 0 -l 20 -B 512 -L 20 -s 2 -c -A 19,20,107,108,0,127,128 72 | ARG seed 2 73 | ARG address space size 128 74 | ARG phys mem size 512 75 | 76 | Segment register information: 77 | 78 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 79 | Segment 0 limit : 20 80 | 81 | Segment 1 base (grows negative) : 0x00000200 (decimal 512) 82 | Segment 1 limit : 20 83 | 84 | Virtual Address Trace 85 | VA 0: 0x00000013 (decimal: 19) --> VALID in SEG0: 0x00000013 (decimal: 19) 86 | VA 1: 0x00000014 (decimal: 20) --> SEGMENTATION VIOLATION (SEG0) 87 | VA 2: 0x0000006b (decimal: 107) --> SEGMENTATION VIOLATION (SEG1) 88 | VA 3: 0x0000006c (decimal: 108) --> VALID in SEG1: 0x000001ec (decimal: 492) 89 | VA 4: 0x00000000 (decimal: 0) --> VALID in SEG0: 0x00000000 (decimal: 0) 90 | VA 5: 0x0000007f (decimal: 127) --> VALID in SEG1: 0x000001ff (decimal: 511) 91 | Error: virtual address 128 cannot be generated in an address space of size 128 92 | ``` 93 | 94 | * **问题 3 答案** 95 | 中间的省略号表示的应该都是无效,我们按这个来计算。 96 | 只有前两个和最后两个是有效的,那么界限寄存器肯定是2。 97 | 基址寄存器的选择范围很大, b0可以从0到124,b1可以从4到128。 98 | ``` 99 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 16 -p 128 -A 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 --b0 0 --l0 2 --b1 4 --l1 2 -c 100 | ARG seed 0 101 | ARG address space size 16 102 | ARG phys mem size 128 103 | 104 | Segment register information: 105 | 106 | Segment 0 base (grows positive) : 0x00000000 (decimal 0) 107 | Segment 0 limit : 2 108 | 109 | Segment 1 base (grows negative) : 0x00000004 (decimal 4) 110 | Segment 1 limit : 2 111 | 112 | Virtual Address Trace 113 | VA 0: 0x00000000 (decimal: 0) --> VALID in SEG0: 0x00000000 (decimal: 0) 114 | VA 1: 0x00000001 (decimal: 1) --> VALID in SEG0: 0x00000001 (decimal: 1) 115 | VA 2: 0x00000002 (decimal: 2) --> SEGMENTATION VIOLATION (SEG0) 116 | VA 3: 0x00000003 (decimal: 3) --> SEGMENTATION VIOLATION (SEG0) 117 | VA 4: 0x00000004 (decimal: 4) --> SEGMENTATION VIOLATION (SEG0) 118 | VA 5: 0x00000005 (decimal: 5) --> SEGMENTATION VIOLATION (SEG0) 119 | VA 6: 0x00000006 (decimal: 6) --> SEGMENTATION VIOLATION (SEG0) 120 | VA 7: 0x00000007 (decimal: 7) --> SEGMENTATION VIOLATION (SEG0) 121 | VA 8: 0x00000008 (decimal: 8) --> SEGMENTATION VIOLATION (SEG1) 122 | VA 9: 0x00000009 (decimal: 9) --> SEGMENTATION VIOLATION (SEG1) 123 | VA 10: 0x0000000a (decimal: 10) --> SEGMENTATION VIOLATION (SEG1) 124 | VA 11: 0x0000000b (decimal: 11) --> SEGMENTATION VIOLATION (SEG1) 125 | VA 12: 0x0000000c (decimal: 12) --> SEGMENTATION VIOLATION (SEG1) 126 | VA 13: 0x0000000d (decimal: 13) --> SEGMENTATION VIOLATION (SEG1) 127 | VA 14: 0x0000000e (decimal: 14) --> VALID in SEG1: 0x00000002 (decimal: 2) 128 | VA 15: 0x0000000f (decimal: 15) --> VALID in SEG1: 0x00000003 (decimal: 3) 129 | ``` 130 | 131 | * **问题 4 答案** 132 | 两个界限寄存器的和占有效地址空间的90%即可。而且随机生成的虚拟地址数量要大,不然样本太小。 133 | 结果太长,这里仅仅给出命令。 134 | ``` 135 | ./segmentation.py -a 1k -n 100 --l0 460 --l1 461 -c 136 | ``` 137 | 138 | * **问题 5 答案** 139 | 让两个界限寄存器的值为0即可。 140 | ``` 141 | [testjz@localhost vm-segmentation]$ ./segmentation.py -a 1k -n 10 --l0 0 --l1 0 -c 142 | ARG seed 0 143 | ARG address space size 1k 144 | ARG phys mem size 16k 145 | 146 | Segment register information: 147 | 148 | Segment 0 base (grows positive) : 0x0000360b (decimal 13835) 149 | Segment 0 limit : 0 150 | 151 | Segment 1 base (grows negative) : 0x00003082 (decimal 12418) 152 | Segment 1 limit : 0 153 | 154 | Virtual Address Trace 155 | VA 0: 0x000001ae (decimal: 430) --> SEGMENTATION VIOLATION (SEG0) 156 | VA 1: 0x00000109 (decimal: 265) --> SEGMENTATION VIOLATION (SEG0) 157 | VA 2: 0x0000020b (decimal: 523) --> SEGMENTATION VIOLATION (SEG1) 158 | VA 3: 0x0000019e (decimal: 414) --> SEGMENTATION VIOLATION (SEG0) 159 | VA 4: 0x00000322 (decimal: 802) --> SEGMENTATION VIOLATION (SEG1) 160 | VA 5: 0x00000136 (decimal: 310) --> SEGMENTATION VIOLATION (SEG0) 161 | VA 6: 0x000001e8 (decimal: 488) --> SEGMENTATION VIOLATION (SEG0) 162 | VA 7: 0x00000255 (decimal: 597) --> SEGMENTATION VIOLATION (SEG1) 163 | VA 8: 0x000003a1 (decimal: 929) --> SEGMENTATION VIOLATION (SEG1) 164 | VA 9: 0x00000204 (decimal: 516) --> SEGMENTATION VIOLATION (SEG1) 165 | ``` 166 | -------------------------------------------------------------------------------- /Chapter-17/Chapter-17-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost vm-freespace]$ ./malloc.py -n 10 -H 0 -p BEST -s 0 -c 4 | seed 0 5 | size 100 6 | baseAddr 1000 7 | headerSize 0 8 | alignment -1 9 | policy BEST 10 | listOrder ADDRSORT 11 | coalesce False 12 | numOps 10 13 | range 10 14 | percentAlloc 50 15 | allocList 16 | compute True 17 | 18 | ptr[0] = Alloc(3) returned 1000 (searched 1 elements) 19 | Free List [ Size 1 ]: [ addr:1003 sz:97 ] 20 | 21 | Free(ptr[0]) 22 | returned 0 23 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1003 sz:97 ] 24 | 25 | ptr[1] = Alloc(5) returned 1003 (searched 2 elements) 26 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1008 sz:92 ] 27 | 28 | Free(ptr[1]) 29 | returned 0 30 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:92 ] 31 | 32 | ptr[2] = Alloc(8) returned 1008 (searched 3 elements) 33 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1016 sz:84 ] 34 | 35 | Free(ptr[2]) 36 | returned 0 37 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 38 | 39 | ptr[3] = Alloc(8) returned 1008 (searched 4 elements) 40 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1016 sz:84 ] 41 | 42 | Free(ptr[3]) 43 | returned 0 44 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 45 | 46 | ptr[4] = Alloc(2) returned 1000 (searched 4 elements) 47 | Free List [ Size 4 ]: [ addr:1002 sz:1 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 48 | 49 | ptr[5] = Alloc(7) returned 1008 (searched 4 elements) 50 | Free List [ Size 4 ]: [ addr:1002 sz:1 ][ addr:1003 sz:5 ][ addr:1015 sz:1 ][ addr:1016 sz:84 ] 51 | ``` 52 | 空间列表不会合并,导致碎片越来越多。 53 | 54 | * **问题 2 答案** 55 | ``` 56 | [testjz@localhost vm-freespace]$ ./malloc.py -n 10 -H 0 -p WORST -s 0 -c 57 | seed 0 58 | size 100 59 | baseAddr 1000 60 | headerSize 0 61 | alignment -1 62 | policy WORST 63 | listOrder ADDRSORT 64 | coalesce False 65 | numOps 10 66 | range 10 67 | percentAlloc 50 68 | allocList 69 | compute True 70 | 71 | ptr[0] = Alloc(3) returned 1000 (searched 1 elements) 72 | Free List [ Size 1 ]: [ addr:1003 sz:97 ] 73 | 74 | Free(ptr[0]) 75 | returned 0 76 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1003 sz:97 ] 77 | 78 | ptr[1] = Alloc(5) returned 1003 (searched 2 elements) 79 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1008 sz:92 ] 80 | 81 | Free(ptr[1]) 82 | returned 0 83 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:92 ] 84 | 85 | ptr[2] = Alloc(8) returned 1008 (searched 3 elements) 86 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1016 sz:84 ] 87 | 88 | Free(ptr[2]) 89 | returned 0 90 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 91 | 92 | ptr[3] = Alloc(8) returned 1016 (searched 4 elements) 93 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1024 sz:76 ] 94 | 95 | Free(ptr[3]) 96 | returned 0 97 | Free List [ Size 5 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:8 ][ addr:1024 sz:76 ] 98 | 99 | ptr[4] = Alloc(2) returned 1024 (searched 5 elements) 100 | Free List [ Size 5 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:8 ][ addr:1026 sz:74 ] 101 | 102 | ptr[5] = Alloc(7) returned 1026 (searched 5 elements) 103 | Free List [ Size 5 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:8 ][ addr:1033 sz:67 ] 104 | ``` 105 | 因为每次找最大的匹配,又不会合并,所以容易产生更多的碎片。 106 | 107 | * **问题 3 答案** 108 | ``` 109 | [testjz@localhost vm-freespace]$ ./malloc.py -n 10 -H 0 -p FIRST -s 0 -c 110 | seed 0 111 | size 100 112 | baseAddr 1000 113 | headerSize 0 114 | alignment -1 115 | policy FIRST 116 | listOrder ADDRSORT 117 | coalesce False 118 | numOps 10 119 | range 10 120 | percentAlloc 50 121 | allocList 122 | compute True 123 | 124 | ptr[0] = Alloc(3) returned 1000 (searched 1 elements) 125 | Free List [ Size 1 ]: [ addr:1003 sz:97 ] 126 | 127 | Free(ptr[0]) 128 | returned 0 129 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1003 sz:97 ] 130 | 131 | ptr[1] = Alloc(5) returned 1003 (searched 2 elements) 132 | Free List [ Size 2 ]: [ addr:1000 sz:3 ][ addr:1008 sz:92 ] 133 | 134 | Free(ptr[1]) 135 | returned 0 136 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:92 ] 137 | 138 | ptr[2] = Alloc(8) returned 1008 (searched 3 elements) 139 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1016 sz:84 ] 140 | 141 | Free(ptr[2]) 142 | returned 0 143 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 144 | 145 | ptr[3] = Alloc(8) returned 1008 (searched 3 elements) 146 | Free List [ Size 3 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1016 sz:84 ] 147 | 148 | Free(ptr[3]) 149 | returned 0 150 | Free List [ Size 4 ]: [ addr:1000 sz:3 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 151 | 152 | ptr[4] = Alloc(2) returned 1000 (searched 1 elements) 153 | Free List [ Size 4 ]: [ addr:1002 sz:1 ][ addr:1003 sz:5 ][ addr:1008 sz:8 ][ addr:1016 sz:84 ] 154 | 155 | ptr[5] = Alloc(7) returned 1008 (searched 3 elements) 156 | Free List [ Size 4 ]: [ addr:1002 sz:1 ][ addr:1003 sz:5 ][ addr:1015 sz:1 ][ addr:1016 sz:84 ] 157 | ``` 158 | 159 | 搜索空闲列表的时间变少了。 160 | 161 | * **问题 4 答案** 162 | 对于最优匹配和最差匹配,如果不调整算法,时间不会有影响。(但是一般应该对应调整算法) 163 | 测试内容较多,这里省略。 164 | 165 | * **问题 5 答案** 166 | 测试结果太长这里省略。 167 | 如果没有合并,那么空闲列表全是小碎片,可能没有办法使用大型分配请求。 168 | 有合并则正常使用。 169 | 170 | * **问题 6 答案** 171 | P越高,分配操作越多,剩余空间越少呀。 172 | 173 | * **问题 7 答案** 174 | 进行很多很多分配操作,且不free即可。 175 | -------------------------------------------------------------------------------- /Chapter-18/Chapter-18-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 答案太长不完整列出了,仅列出页表的项目数。 3 | ``` 4 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 1k -a 1m -p 512m -v -n 0 5 | 1024项 6 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 1k -a 2m -p 512m -v -n 0 7 | 2048项 8 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 1k -a 4m -p 512m -v -n 0 9 | 4096项 10 | 11 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 1k -a 1m -p 512m -v -n 0 12 | 1024项 13 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 2k -a 1m -p 512m -v -n 0 14 | 512项 15 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 4k -a 1m -p 512m -v -n 0 16 | 256项 17 | ``` 18 | 页表大小随着地址空间的增大而增大,随着页大小的增大而减小。 19 | 如果使用很大的页,会产生很多内部碎片,空间同样被浪费了。 20 | 21 | * **问题 2 答案** 22 | 答案太长省略了,执行程序即可看到结果。 23 | 增加百分比,更多的地址转换成功。 24 | 25 | * **问题 3 答案** 26 | 这三个都存在正确的转换,因此都不能算“错误”。但是三个的组合都不太合理。 27 | 1和2:地址空间太小,只能容下4个页。 28 | 3:页大小有点大了。 29 | 30 | * **问题 4 答案** 31 | ``` 32 | [testjz@localhost vm-paging]$ ./paging-linear-translate.py -P 1k -a 16k -p 8k -v -c 33 | ARG seed 0 34 | ARG address space size 16k 35 | ARG phys mem size 8k 36 | ARG page size 1k 37 | ARG verbose True 38 | ARG addresses -1 39 | 40 | Error: physical memory size must be GREATER than address space size (for this simulation) 41 | ``` 42 | 会报错,提示物理内存大小应该大于地址空间大小。 43 | -------------------------------------------------------------------------------- /Chapter-19/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jzplp/OSTEP-Answers/7533b9ff75fd221a79d4137c4834cf75701f974f/Chapter-19/1.png -------------------------------------------------------------------------------- /Chapter-19/19.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define PAGESIZE 4096 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | if(argc != 3) { 10 | fprintf(stderr, "error parameters!"); 11 | exit(0); 12 | } 13 | struct timeval start, end; 14 | int pageNum = atoi(argv[1]); 15 | int i,j, num = atoi(argv[2]); 16 | char arr[PAGESIZE * pageNum]; 17 | 18 | gettimeofday(&start, NULL); 19 | for(j=0; j 2 | #include 3 | #include 4 | 5 | #define PAGESIZE 4096 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | if(argc != 3) { 10 | fprintf(stderr, "error parameters!"); 11 | exit(0); 12 | } 13 | struct timeval start, end; 14 | int pageNum = atoi(argv[1]); 15 | int i,j, num = atoi(argv[2]); 16 | char arr[PAGESIZE * pageNum]; 17 | for(i=0; i 16 | #include 17 | #include 18 | 19 | #define PAGESIZE 4096 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | if(argc != 3) { 24 | fprintf(stderr, "error parameters!"); 25 | exit(0); 26 | } 27 | struct timeval start, end; 28 | int pageNum = atoi(argv[1]); 29 | int i,j, num = atoi(argv[2]); 30 | char arr[PAGESIZE * pageNum]; 31 | 32 | gettimeofday(&start, NULL); 33 | for(j=0; j 110 | #include 111 | #include 112 | 113 | #define PAGESIZE 4096 114 | 115 | int main(int argc, char *argv[]) 116 | { 117 | if(argc != 3) { 118 | fprintf(stderr, "error parameters!"); 119 | exit(0); 120 | } 121 | struct timeval start, end; 122 | int pageNum = atoi(argv[1]); 123 | int i,j, num = atoi(argv[2]); 124 | char arr[PAGESIZE * pageNum]; 125 | for(i=0; i randCite): 77 | t = random.choice(coldPage) 78 | else: 79 | t = random.choice(hotPage) 80 | arr.append(t) 81 | print(arr) 82 | 83 | file = open('./1.txt', 'w') 84 | 85 | for i in arr: 86 | file.write(str(i) + '\n') 87 | 88 | file.close() 89 | ``` 90 | 测试命令: 91 | ``` 92 | ./paging-policy.py -f 1.txt -p LRU -c 93 | ./paging-policy.py -f 1.txt -p RAND -c 94 | ./paging-policy.py -f 1.txt -p CLOCK -c 95 | ``` 96 | 类似于图22.3,LRU的表现略好于RAND。 97 | 经过不完全测试,CLOCK bit为1时表现差于LRU,提高bit时出现好于LRU的情况,且在一定数值内bit越高表现越好。 98 | 99 | * **问题 5 答案** 100 | 命令执行结果:(省略上面的大量内存记录) 101 | ``` 102 | ==5192== 103 | ==5192== Counted 0 calls to main() 104 | ==5192== 105 | ==5192== Jccs: 106 | ==5192== total: 96,040 107 | ==5192== taken: 47,991 (50%) 108 | ==5192== 109 | ==5192== Executed: 110 | ==5192== SBs entered: 92,692 111 | ==5192== SBs completed: 62,247 112 | ==5192== guest instrs: 468,723 113 | ==5192== IRStmts: 2,930,905 114 | ==5192== 115 | ==5192== Ratios: 116 | ==5192== guest instrs : SB entered = 50 : 10 117 | ==5192== IRStmts : SB entered = 316 : 10 118 | ==5192== IRStmts : guest instr = 62 : 10 119 | ==5192== 120 | ==5192== Exit code: 0 121 | ``` 122 | 上面的内存记录的说明可以看Valgrind源代码中lackey/lk_main.c文件最上面的注释。但是这个最后的总结我没找到说明,因此没看懂。 123 | 测试缓存过程省略。 124 | -------------------------------------------------------------------------------- /Chapter-22/genLocalRandom.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | import random 3 | Max = 10 4 | num = 10 5 | randCite = 0.8 6 | randomHotPage = 0.2 7 | 8 | arr = [] 9 | 10 | numlist = set(range(0, Max)) 11 | hotPage = set() 12 | coldPage = set() 13 | 14 | while len(hotPage) < int(Max * randomHotPage): 15 | i = random.choice(list(numlist)) 16 | hotPage.add(i) 17 | coldPage = numlist - hotPage 18 | print(hotPage) 19 | print(coldPage) 20 | hotPage = list(hotPage) 21 | coldPage = list(coldPage) 22 | 23 | for i in range(0, num): 24 | if(random.random() > randCite): 25 | t = random.choice(coldPage) 26 | else: 27 | t = random.choice(hotPage) 28 | arr.append(t) 29 | print(arr) 30 | 31 | file = open('./1.txt', 'w') 32 | 33 | for i in arr: 34 | file.write(str(i) + '\n') 35 | 36 | file.close() 37 | -------------------------------------------------------------------------------- /Chapter-22/genRandom.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | import random 3 | Max = 10 4 | num = 10 5 | 6 | arr = [] 7 | for i in range(0, num): 8 | t = random.randint(0, Max - 1) 9 | arr.append(t) 10 | print(arr) 11 | 12 | file = open('./1.txt', 'w') 13 | 14 | for i in arr: 15 | file.write(str(i) + '\n') 16 | 17 | file.close() 18 | -------------------------------------------------------------------------------- /Chapter-26/Chapter-26-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost threads-intro]$ ./x86.py -p loop.s -t 1 -i 100 -R dx -c 4 | ARG seed 0 5 | ARG numthreads 1 6 | ARG program loop.s 7 | ARG interrupt frequency 100 8 | ARG interrupt randomness False 9 | ARG argv 10 | ARG load address 1000 11 | ARG memsize 128 12 | ARG memtrace 13 | ARG regtrace dx 14 | ARG cctrace False 15 | ARG printstats False 16 | ARG verbose False 17 | 18 | dx Thread 0 19 | 0 20 | -1 1000 sub $1,%dx 21 | -1 1001 test $0,%dx 22 | -1 1002 jgte .top 23 | -1 1003 halt 24 | ``` 25 | dx一开始是0,后来变为-1。 26 | 27 | * **问题 2 答案** 28 | ``` 29 | [testjz@localhost threads-intro]$ ./x86.py -p loop.s -t 2 -i 100 -R dx -a dx=3,dx=3 -c 30 | ARG seed 0 31 | ARG numthreads 2 32 | ARG program loop.s 33 | ARG interrupt frequency 100 34 | ARG interrupt randomness False 35 | ARG argv dx=3,dx=3 36 | ARG load address 1000 37 | ARG memsize 128 38 | ARG memtrace 39 | ARG regtrace dx 40 | ARG cctrace False 41 | ARG printstats False 42 | ARG verbose False 43 | 44 | dx Thread 0 Thread 1 45 | 3 46 | 2 1000 sub $1,%dx 47 | 2 1001 test $0,%dx 48 | 2 1002 jgte .top 49 | 1 1000 sub $1,%dx 50 | 1 1001 test $0,%dx 51 | 1 1002 jgte .top 52 | 0 1000 sub $1,%dx 53 | 0 1001 test $0,%dx 54 | 0 1002 jgte .top 55 | -1 1000 sub $1,%dx 56 | -1 1001 test $0,%dx 57 | -1 1002 jgte .top 58 | -1 1003 halt 59 | 3 ----- Halt;Switch ----- ----- Halt;Switch ----- 60 | 2 1000 sub $1,%dx 61 | 2 1001 test $0,%dx 62 | 2 1002 jgte .top 63 | 1 1000 sub $1,%dx 64 | 1 1001 test $0,%dx 65 | 1 1002 jgte .top 66 | 0 1000 sub $1,%dx 67 | 0 1001 test $0,%dx 68 | 0 1002 jgte .top 69 | -1 1000 sub $1,%dx 70 | -1 1001 test $0,%dx 71 | -1 1002 jgte .top 72 | -1 1003 halt 73 | ``` 74 | dx在每个线程从3到-1。由于100条指令中断一次,因此多线程的存在不影响计算。这段代码没有竞态条件。 75 | 76 | * **问题 3 答案** 77 | 结果太长,这里仅仅给出命令。 78 | ``` 79 | ./x86.py -p loop.s -t 2 -i 3 -R dx -a dx=3,dx=3 -r -c -s 1 80 | ./x86.py -p loop.s -t 2 -i 3 -R dx -a dx=3,dx=3 -r -c -s 2 81 | ./x86.py -p loop.s -t 2 -i 3 -R dx -a dx=3,dx=3 -r -c -s 3 82 | ``` 83 | 中断频率会改变这个程序的行为。 84 | 85 | * **问题 4 答案** 86 | ``` 87 | [testjz@localhost threads-intro]$ ./x86.py -p looping-race-nolock.s -t 1 -M 2000 -c 88 | ARG seed 0 89 | ARG numthreads 1 90 | ARG program looping-race-nolock.s 91 | ARG interrupt frequency 50 92 | ARG interrupt randomness False 93 | ARG argv 94 | ARG load address 1000 95 | ARG memsize 128 96 | ARG memtrace 2000 97 | ARG regtrace 98 | ARG cctrace False 99 | ARG printstats False 100 | ARG verbose False 101 | 102 | 2000 Thread 0 103 | 0 104 | 0 1000 mov 2000, %ax 105 | 0 1001 add $1, %ax 106 | 1 1002 mov %ax, 2000 107 | 1 1003 sub $1, %bx 108 | 1 1004 test $0, %bx 109 | 1 1005 jgt .top 110 | 1 1006 halt 111 | ``` 112 | 从0变为1 113 | 114 | * **问题 5 答案** 115 | ``` 116 | [testjz@localhost threads-intro]$ ./x86.py -p looping-race-nolock.s -t 2 -a bx=3 -M 2000 -c 117 | ARG seed 0 118 | ARG numthreads 2 119 | ARG program looping-race-nolock.s 120 | ARG interrupt frequency 50 121 | ARG interrupt randomness False 122 | ARG argv bx=3 123 | ARG load address 1000 124 | ARG memsize 128 125 | ARG memtrace 2000 126 | ARG regtrace 127 | ARG cctrace False 128 | ARG printstats False 129 | ARG verbose False 130 | 131 | 2000 Thread 0 Thread 1 132 | 0 133 | 0 1000 mov 2000, %ax 134 | 0 1001 add $1, %ax 135 | 1 1002 mov %ax, 2000 136 | 1 1003 sub $1, %bx 137 | 1 1004 test $0, %bx 138 | 1 1005 jgt .top 139 | 1 1000 mov 2000, %ax 140 | 1 1001 add $1, %ax 141 | 2 1002 mov %ax, 2000 142 | 2 1003 sub $1, %bx 143 | 2 1004 test $0, %bx 144 | 2 1005 jgt .top 145 | 2 1000 mov 2000, %ax 146 | 2 1001 add $1, %ax 147 | 3 1002 mov %ax, 2000 148 | 3 1003 sub $1, %bx 149 | 3 1004 test $0, %bx 150 | 3 1005 jgt .top 151 | 3 1006 halt 152 | 3 ----- Halt;Switch ----- ----- Halt;Switch ----- 153 | 3 1000 mov 2000, %ax 154 | 3 1001 add $1, %ax 155 | 4 1002 mov %ax, 2000 156 | 4 1003 sub $1, %bx 157 | 4 1004 test $0, %bx 158 | 4 1005 jgt .top 159 | 4 1000 mov 2000, %ax 160 | 4 1001 add $1, %ax 161 | 5 1002 mov %ax, 2000 162 | 5 1003 sub $1, %bx 163 | 5 1004 test $0, %bx 164 | 5 1005 jgt .top 165 | 5 1000 mov 2000, %ax 166 | 5 1001 add $1, %ax 167 | 6 1002 mov %ax, 2000 168 | 6 1003 sub $1, %bx 169 | 6 1004 test $0, %bx 170 | 6 1005 jgt .top 171 | 6 1006 halt 172 | ``` 173 | 每个线程循环3次是因为dx的值从3到0,然后停止了。 174 | x的最终值为6。 175 | 176 | * **问题 6 答案** 177 | 结果太长,这里仅仅给出命令。 178 | ``` 179 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -i 4 -r -s 1 -c 180 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -i 4 -r -s 2 -c 181 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -i 4 -r -s 3 -c 182 | ``` 183 | 只看线程交替,是可以分析出x的最终值的。中断的确切位置很重要。 184 | 中断发生在两个mov之间就可能引起麻烦,其余的地方是安全的。 185 | 186 | * **问题 7 答案** 187 | 结果太长,这里仅仅给出命令。 188 | ``` 189 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=1 -i 1 -c 190 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=1 -i 2 -c 191 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=1 -i 3 -c 192 | ``` 193 | i为1时,x的最终值为1。 194 | i为2时,x的最终值为1。 195 | i为3时,x的最终值为2,为“正确答案”。 196 | 197 | * **问题 8 答案** 198 | 结果太长,这里仅仅给出命令。 199 | ``` 200 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=100 -i 1 -c 201 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=100 -i 2 -c 202 | ./x86.py -p looping-race-nolock.s -t 2 -M 2000 -a bx=100 -i 3 -c 203 | ... 204 | ``` 205 | 我发现,3的倍数的间隔会导致正确的答案。原因是指令的前三条必须在一起执行。 206 | 令人惊讶的间隔,实话说都不让我惊讶。 207 | 208 | * **问题 9 答案** 209 | ``` 210 | [testjz@localhost threads-intro]$ ./x86.py -p wait-for-me.s -a ax=1,ax=0 -R ax -M 2000 -c 211 | ARG seed 0 212 | ARG numthreads 2 213 | ARG program wait-for-me.s 214 | ARG interrupt frequency 50 215 | ARG interrupt randomness False 216 | ARG argv ax=1,ax=0 217 | ARG load address 1000 218 | ARG memsize 128 219 | ARG memtrace 2000 220 | ARG regtrace ax 221 | ARG cctrace False 222 | ARG printstats False 223 | ARG verbose False 224 | 225 | 2000 ax Thread 0 Thread 1 226 | 0 1 227 | 0 1 1000 test $1, %ax 228 | 0 1 1001 je .signaller 229 | 1 1 1006 mov $1, 2000 230 | 1 1 1007 halt 231 | 1 0 ----- Halt;Switch ----- ----- Halt;Switch ----- 232 | 1 0 1000 test $1, %ax 233 | 1 0 1001 je .signaller 234 | 1 0 1002 mov 2000, %cx 235 | 1 0 1003 test $1, %cx 236 | 1 0 1004 jne .waiter 237 | 1 0 1005 halt 238 | ``` 239 | 代码的行为如上。2000处的值从0变为1。 240 | 241 | * **问题 10 答案** 242 | ``` 243 | [testjz@localhost threads-intro]$ ./x86.py -p wait-for-me.s -a ax=0,ax=1 -R ax -M 2000 244 | ARG seed 0 245 | ARG numthreads 2 246 | ARG program wait-for-me.s 247 | ARG interrupt frequency 50 248 | ARG interrupt randomness False 249 | ARG argv ax=0,ax=1 250 | ARG load address 1000 251 | ARG memsize 128 252 | ARG memtrace 2000 253 | ARG regtrace ax 254 | ARG cctrace False 255 | ARG printstats False 256 | ARG verbose False 257 | 258 | 2000 ax Thread 0 Thread 1 259 | ? ? 260 | ? ? 1000 test $1, %ax 261 | ? ? 1001 je .signaller 262 | ? ? 1002 mov 2000, %cx 263 | ? ? 1003 test $1, %cx 264 | ? ? 1004 jne .waiter 265 | ? ? 1002 mov 2000, %cx 266 | ? ? 1003 test $1, %cx 267 | ? ? 1004 jne .waiter 268 | ? ? 1002 mov 2000, %cx 269 | ? ? 1003 test $1, %cx 270 | ? ? 1004 jne .waiter 271 | ? ? 1002 mov 2000, %cx 272 | ? ? 1003 test $1, %cx 273 | ? ? 1004 jne .waiter 274 | ? ? 1002 mov 2000, %cx 275 | ? ? 1003 test $1, %cx 276 | ? ? 1004 jne .waiter 277 | ? ? 1002 mov 2000, %cx 278 | ? ? 1003 test $1, %cx 279 | ? ? 1004 jne .waiter 280 | ? ? 1002 mov 2000, %cx 281 | ? ? 1003 test $1, %cx 282 | ? ? 1004 jne .waiter 283 | ? ? 1002 mov 2000, %cx 284 | ? ? 1003 test $1, %cx 285 | ? ? 1004 jne .waiter 286 | ? ? 1002 mov 2000, %cx 287 | ? ? 1003 test $1, %cx 288 | ? ? 1004 jne .waiter 289 | ? ? 1002 mov 2000, %cx 290 | ? ? 1003 test $1, %cx 291 | ? ? 1004 jne .waiter 292 | ? ? 1002 mov 2000, %cx 293 | ? ? 1003 test $1, %cx 294 | ? ? 1004 jne .waiter 295 | ? ? 1002 mov 2000, %cx 296 | ? ? 1003 test $1, %cx 297 | ? ? 1004 jne .waiter 298 | ? ? 1002 mov 2000, %cx 299 | ? ? 1003 test $1, %cx 300 | ? ? 1004 jne .waiter 301 | ? ? 1002 mov 2000, %cx 302 | ? ? 1003 test $1, %cx 303 | ? ? 1004 jne .waiter 304 | ? ? 1002 mov 2000, %cx 305 | ? ? 1003 test $1, %cx 306 | ? ? 1004 jne .waiter 307 | ? ? 1002 mov 2000, %cx 308 | ? ? 1003 test $1, %cx 309 | ? ? 1004 jne .waiter 310 | ? ? ------ Interrupt ------ ------ Interrupt ------ 311 | ? ? 1000 test $1, %ax 312 | ? ? 1001 je .signaller 313 | ? ? 1006 mov $1, 2000 314 | ? ? 1007 halt 315 | ? ? ----- Halt;Switch ----- ----- Halt;Switch ----- 316 | ? ? 1002 mov 2000, %cx 317 | ? ? 1003 test $1, %cx 318 | ? ? 1004 jne .waiter 319 | ? ? 1005 halt 320 | ``` 321 | 线程行为如上,线程0一直在循环检测2000处的值,直到中断发生。改变时间间隔,循环的次数也会改变,由于循环的代码并不修改数据,因此中断间隔越长,循环越多,CPU的利用效率越低。 322 | -------------------------------------------------------------------------------- /Chapter-28/Chapter-28-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 汇编代码尝试使用书类似中图28.1代码的方式来设置锁。 3 | 4 | * **问题 2 答案** 5 | ``` 6 | [testjz@localhost threads-locks]$ ./x86.py -p flag.s -R ax,bx -M flag,count -c 7 | ARG seed 0 8 | ARG numthreads 2 9 | ARG program flag.s 10 | ARG interrupt frequency 50 11 | ARG interrupt randomness False 12 | ARG procsched 13 | ARG argv 14 | ARG load address 1000 15 | ARG memsize 128 16 | ARG memtrace flag,count 17 | ARG regtrace ax,bx 18 | ARG cctrace False 19 | ARG printstats False 20 | ARG verbose False 21 | 22 | 23 | flag count ax bx Thread 0 Thread 1 24 | 25 | 0 0 0 0 26 | 0 0 0 0 1000 mov flag, %ax 27 | 0 0 0 0 1001 test $0, %ax 28 | 0 0 0 0 1002 jne .acquire 29 | 1 0 0 0 1003 mov $1, flag 30 | 1 0 0 0 1004 mov count, %ax 31 | 1 0 1 0 1005 add $1, %ax 32 | 1 1 1 0 1006 mov %ax, count 33 | 0 1 1 0 1007 mov $0, flag 34 | 0 1 1 -1 1008 sub $1, %bx 35 | 0 1 1 -1 1009 test $0, %bx 36 | 0 1 1 -1 1010 jgt .top 37 | 0 1 1 -1 1011 halt 38 | 0 1 0 0 ----- Halt;Switch ----- ----- Halt;Switch ----- 39 | 0 1 0 0 1000 mov flag, %ax 40 | 0 1 0 0 1001 test $0, %ax 41 | 0 1 0 0 1002 jne .acquire 42 | 1 1 0 0 1003 mov $1, flag 43 | 1 1 1 0 1004 mov count, %ax 44 | 1 1 2 0 1005 add $1, %ax 45 | 1 2 2 0 1006 mov %ax, count 46 | 0 2 2 0 1007 mov $0, flag 47 | 0 2 2 -1 1008 sub $1, %bx 48 | 0 2 2 -1 1009 test $0, %bx 49 | 0 2 2 -1 1010 jgt .top 50 | 0 2 2 -1 1011 halt 51 | ``` 52 | 可以按预期工作。 53 | 54 | * **问题 3 答案** 55 | ``` 56 | [testjz@localhost threads-locks]$ ./x86.py -p flag.s -R ax,bx -M flag,count -a bx=2,bx=2 -c 57 | ARG seed 0 58 | ARG numthreads 2 59 | ARG program flag.s 60 | ARG interrupt frequency 50 61 | ARG interrupt randomness False 62 | ARG procsched 63 | ARG argv bx=2,bx=2 64 | ARG load address 1000 65 | ARG memsize 128 66 | ARG memtrace flag,count 67 | ARG regtrace ax,bx 68 | ARG cctrace False 69 | ARG printstats False 70 | ARG verbose False 71 | 72 | 73 | flag count ax bx Thread 0 Thread 1 74 | 75 | 0 0 0 2 76 | 0 0 0 2 1000 mov flag, %ax 77 | 0 0 0 2 1001 test $0, %ax 78 | 0 0 0 2 1002 jne .acquire 79 | 1 0 0 2 1003 mov $1, flag 80 | 1 0 0 2 1004 mov count, %ax 81 | 1 0 1 2 1005 add $1, %ax 82 | 1 1 1 2 1006 mov %ax, count 83 | 0 1 1 2 1007 mov $0, flag 84 | 0 1 1 1 1008 sub $1, %bx 85 | 0 1 1 1 1009 test $0, %bx 86 | 0 1 1 1 1010 jgt .top 87 | 0 1 0 1 1000 mov flag, %ax 88 | 0 1 0 1 1001 test $0, %ax 89 | 0 1 0 1 1002 jne .acquire 90 | 1 1 0 1 1003 mov $1, flag 91 | 1 1 1 1 1004 mov count, %ax 92 | 1 1 2 1 1005 add $1, %ax 93 | 1 2 2 1 1006 mov %ax, count 94 | 0 2 2 1 1007 mov $0, flag 95 | 0 2 2 0 1008 sub $1, %bx 96 | 0 2 2 0 1009 test $0, %bx 97 | 0 2 2 0 1010 jgt .top 98 | 0 2 2 0 1011 halt 99 | 0 2 0 2 ----- Halt;Switch ----- ----- Halt;Switch ----- 100 | 0 2 0 2 1000 mov flag, %ax 101 | 0 2 0 2 1001 test $0, %ax 102 | 0 2 0 2 1002 jne .acquire 103 | 1 2 0 2 1003 mov $1, flag 104 | 1 2 2 2 1004 mov count, %ax 105 | 1 2 3 2 1005 add $1, %ax 106 | 1 3 3 2 1006 mov %ax, count 107 | 0 3 3 2 1007 mov $0, flag 108 | 0 3 3 1 1008 sub $1, %bx 109 | 0 3 3 1 1009 test $0, %bx 110 | 0 3 3 1 1010 jgt .top 111 | 0 3 0 1 1000 mov flag, %ax 112 | 0 3 0 1 1001 test $0, %ax 113 | 0 3 0 1 1002 jne .acquire 114 | 1 3 0 1 1003 mov $1, flag 115 | 1 3 3 1 1004 mov count, %ax 116 | 1 3 4 1 1005 add $1, %ax 117 | 1 4 4 1 1006 mov %ax, count 118 | 0 4 4 1 1007 mov $0, flag 119 | 0 4 4 0 1008 sub $1, %bx 120 | 0 4 4 0 1009 test $0, %bx 121 | 0 4 4 0 1010 jgt .top 122 | 0 4 4 0 1011 halt 123 | ``` 124 | 循环次数变为两次,还是可以按预期工作。 125 | 126 | * **问题 4 答案** 127 | 结果太长,这里仅仅给出命令。 128 | ``` 129 | ./x86.py -p flag.s -R ax,bx -M flag,count -a bx=5,bx=5 -i 4 -c 130 | ``` 131 | 中断频率越高(i值越低),bx越大,越容易产生不好的结果。 132 | 133 | * **问题 5 答案** 134 | 获取锁 135 | ``` 136 | mov $1, %ax 137 | xchg %ax, mutex # atomic swap of 1 and mutex 138 | test $0, %ax # if we get 0 back: lock is free! 139 | jne .acquire # if not, try again 140 | ``` 141 | 释放锁 142 | ``` 143 | mov $0, mutex 144 | ``` 145 | 146 | * **问题 6 答案** 147 | ``` 148 | ./x86.py -p test-and-set.s -i 10 -R ax,bx -M mutex,count -a bx=5 -c 149 | ``` 150 | 代码一直可以按预期工作,有时会导致CPU使用率高,看代码是否在获取锁的时候重复循环即可。 151 | 152 | * **问题 7 答案** 153 | 结果太长,这里仅仅给出命令。 154 | ``` 155 | ./x86.py -p test-and-set.s -i 10 -R ax,bx -M mutex,count -a bx=5 -P 1100111000111000111000 -c 156 | ``` 157 | 正确的事情发生了。 158 | 159 | * **问题 8 答案** 160 | 可以理解,这就是Peterson算法的汇编伪代码。 161 | 162 | * **问题 9 答案** 163 | ``` 164 | [testjz@localhost threads-locks]$ ./x86.py -p peterson.s -M turn,count -R bx -i 5 -a bx=0,bx=1 -c 165 | ARG seed 0 166 | ARG numthreads 2 167 | ARG program peterson.s 168 | ARG interrupt frequency 5 169 | ARG interrupt randomness False 170 | ARG procsched 171 | ARG argv bx=0,bx=1 172 | ARG load address 1000 173 | ARG memsize 128 174 | ARG memtrace turn,count 175 | ARG regtrace bx 176 | ARG cctrace False 177 | ARG printstats False 178 | ARG verbose False 179 | 180 | 181 | turn count bx Thread 0 Thread 1 182 | 183 | 0 0 0 184 | 0 0 0 1000 lea flag, %fx 185 | 0 0 0 1001 mov %bx, %cx 186 | 0 0 0 1002 neg %cx 187 | 0 0 0 1003 add $1, %cx 188 | 0 0 0 1004 mov $1, 0(%fx,%bx,4) 189 | 0 0 1 ------ Interrupt ------ ------ Interrupt ------ 190 | 0 0 1 1000 lea flag, %fx 191 | 0 0 1 1001 mov %bx, %cx 192 | 0 0 1 1002 neg %cx 193 | 0 0 1 1003 add $1, %cx 194 | 0 0 1 1004 mov $1, 0(%fx,%bx,4) 195 | 0 0 0 ------ Interrupt ------ ------ Interrupt ------ 196 | 1 0 0 1005 mov %cx, turn 197 | 1 0 0 1006 mov 0(%fx,%cx,4), %ax 198 | 1 0 0 1007 test $1, %ax 199 | 1 0 0 1008 jne .fini 200 | 1 0 0 1009 mov turn, %ax 201 | 1 0 1 ------ Interrupt ------ ------ Interrupt ------ 202 | 0 0 1 1005 mov %cx, turn 203 | 0 0 1 1006 mov 0(%fx,%cx,4), %ax 204 | 0 0 1 1007 test $1, %ax 205 | 0 0 1 1008 jne .fini 206 | 0 0 1 1009 mov turn, %ax 207 | 0 0 0 ------ Interrupt ------ ------ Interrupt ------ 208 | 0 0 0 1010 test %cx, %ax 209 | 0 0 0 1011 je .spin1 210 | 0 0 0 1006 mov 0(%fx,%cx,4), %ax 211 | 0 0 0 1007 test $1, %ax 212 | 0 0 0 1008 jne .fini 213 | 0 0 1 ------ Interrupt ------ ------ Interrupt ------ 214 | 0 0 1 1010 test %cx, %ax 215 | 0 0 1 1011 je .spin1 216 | 0 0 1 1006 mov 0(%fx,%cx,4), %ax 217 | 0 0 1 1007 test $1, %ax 218 | 0 0 1 1008 jne .fini 219 | 0 0 0 ------ Interrupt ------ ------ Interrupt ------ 220 | 0 0 0 1009 mov turn, %ax 221 | 0 0 0 1010 test %cx, %ax 222 | 0 0 0 1011 je .spin1 223 | 0 0 0 1012 mov count, %ax 224 | 0 0 0 1013 add $1, %ax 225 | 0 0 1 ------ Interrupt ------ ------ Interrupt ------ 226 | 0 0 1 1009 mov turn, %ax 227 | 0 0 1 1010 test %cx, %ax 228 | 0 0 1 1011 je .spin1 229 | 0 0 1 1006 mov 0(%fx,%cx,4), %ax 230 | 0 0 1 1007 test $1, %ax 231 | 0 0 0 ------ Interrupt ------ ------ Interrupt ------ 232 | 0 1 0 1014 mov %ax, count 233 | 0 1 0 1015 mov $0, 0(%fx,%bx,4) 234 | 1 1 0 1016 mov %cx, turn 235 | 1 1 0 1017 halt 236 | 1 1 1 ----- Halt;Switch ----- ----- Halt;Switch ----- 237 | 1 1 1 1008 jne .fini 238 | 1 1 1 ------ Interrupt ------ ------ Interrupt ------ 239 | 1 1 1 1009 mov turn, %ax 240 | 1 1 1 1010 test %cx, %ax 241 | 1 1 1 1011 je .spin1 242 | 1 1 1 1012 mov count, %ax 243 | 1 1 1 1013 add $1, %ax 244 | 1 1 1 ------ Interrupt ------ ------ Interrupt ------ 245 | 1 2 1 1014 mov %ax, count 246 | 1 2 1 1015 mov $0, 0(%fx,%bx,4) 247 | 0 2 1 1016 mov %cx, turn 248 | 0 2 1 1017 halt 249 | ``` 250 | 我看不同i值的运行情况都挺好的,没有出现不是预期的结果。不过一定要给两个线程的bx初值肤质,否则锁不起效果。 251 | 252 | * **问题 10 答案** 253 | 结果太长,这里仅仅给出命令。 254 | ``` 255 | ./x86.py -p peterson.s -M turn,count -R bx -a bx=0,bx=1 -P 0000011111 -c 256 | ./x86.py -p peterson.s -M turn,count -R bx -a bx=0,bx=1 -P 00000011111 -c 257 | ``` 258 | 这两个是分别是线程0和线程1循环等待的例子,可以自行修改P试试其它情况。 259 | 260 | * **问题 11 答案** 261 | 相符的。 262 | 263 | * **问题 12 答案** 264 | 结果太长,这里仅仅给出命令。 265 | ``` 266 | ./x86.py -p ticket.s -a bx=1000,bx=1000 -i 5 -M count,ticket,turn -c 267 | ``` 268 | 线程没出现花很长时间自旋等待锁的情况。 269 | 270 | * **问题 13 答案** 271 | 结果太长,这里仅仅给出命令。 272 | ``` 273 | ./x86.py -p ticket.s -t 3 -a bx=100,bx=100,bx=100 -i 5 -M count,ticket,turn -c 274 | ``` 275 | 并未发现。(太长了看的眼疼) 276 | 277 | * **问题 14 答案** 278 | 结果太长,这里仅仅给出命令。 279 | ``` 280 | ./x86.py -p yield.s -M count,mutex -a bx=10,bx=10 -i 5 -c 281 | ``` 282 | 经常看到锁被占用时,调用yield主动放弃CPU的情况。 283 | 284 | * **问题 15 答案** 285 | 相比于test-and-set.s,多了上面的不用xchg的测试锁的步骤,这样实际上对mutex测试了两次。我猜测xchg指令对资源消费更多(时间更长)。虽然第一次没有提供测试不能提供完整的测试,但是可以排除大部分情况了,因此大部分时间都是在第一个测试处自旋,相比于xchg自旋对资源的消耗更小。 286 | (我的猜测不一定正确) 287 | 288 | -------------------------------------------------------------------------------- /Chapter-37/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jzplp/OSTEP-Answers/7533b9ff75fd221a79d4137c4834cf75701f974f/Chapter-37/1.png -------------------------------------------------------------------------------- /Chapter-37/Chapter-37-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | 由于我用的Linux没安装tk,这里使用windows系统来模拟。仅写出命令和最后的统计结果。 2 | * **问题 1 答案** 3 | ``` 4 | ostep-homework-master\file-disks> python disk.py -a 0 -G 5 | 6 | REQUESTS ['0'] 7 | 8 | Block: 0 Seek: 0 Rotate:165 Transfer: 30 Total: 195 9 | 10 | TOTALS Seek: 0 Rotate:165 Transfer: 30 Total: 195 11 | 12 | ostep-homework-master\file-disks> python disk.py -a 6 -G 13 | 14 | REQUESTS ['6'] 15 | 16 | Block: 6 Seek: 0 Rotate:345 Transfer: 30 Total: 375 17 | 18 | TOTALS Seek: 0 Rotate:345 Transfer: 30 Total: 375 19 | 20 | ostep-homework-master\file-disks> python disk.py -a 30 -G 21 | 22 | REQUESTS ['30'] 23 | 24 | Block: 30 Seek: 80 Rotate:265 Transfer: 30 Total: 375 25 | 26 | TOTALS Seek: 80 Rotate:265 Transfer: 30 Total: 375 27 | 28 | ostep-homework-master\file-disks> python disk.py -a 7,30,8 -G 29 | 30 | REQUESTS ['7', '30', '8'] 31 | 32 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 33 | Block: 30 Seek: 80 Rotate:220 Transfer: 30 Total: 330 34 | Block: 8 Seek: 80 Rotate:310 Transfer: 30 Total: 420 35 | 36 | TOTALS Seek:160 Rotate:545 Transfer: 90 Total: 795 37 | 38 | ostep-homework-master\file-disks> python disk.py -a 10,11,12,13 -G 39 | 40 | REQUESTS ['10', '11', '12', '13'] 41 | 42 | Block: 10 Seek: 0 Rotate:105 Transfer: 30 Total: 135 43 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 44 | Block: 12 Seek: 40 Rotate:320 Transfer: 30 Total: 390 45 | Block: 13 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 46 | 47 | TOTALS Seek: 40 Rotate:425 Transfer:120 Total: 585 48 | ``` 49 | 50 | * **问题 2 答案** 51 | 组合太多,这里就不给结果了。 52 | 对于没有寻道的请求无变化,有寻道的请求有时间变化。 53 | 54 | * **问题 3 答案** 55 | 组合太多,这里就不给结果了。 56 | 所有的请求的旋转时间都变慢了。 57 | 58 | * **问题 4 答案** 59 | FIFO就是顺序执行。 60 | ``` 61 | ostep-homework-master\file-disks> python disk.py -a 7,30,8 -p SSTF -G 62 | 63 | REQUESTS ['7', '30', '8'] 64 | 65 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 66 | Block: 8 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 67 | Block: 30 Seek: 80 Rotate:190 Transfer: 30 Total: 300 68 | 69 | TOTALS Seek: 80 Rotate:205 Transfer: 90 Total: 375 70 | ``` 71 | 72 | 73 | * **问题 5 答案** 74 | ``` 75 | ostep-homework-master\file-disks> python disk.py -a 7,30,8 -p SATF -G 76 | 77 | REQUESTS ['7', '30', '8'] 78 | 79 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 80 | Block: 8 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 81 | Block: 30 Seek: 80 Rotate:190 Transfer: 30 Total: 300 82 | 83 | TOTALS Seek: 80 Rotate:205 Transfer: 90 Total: 375 84 | ``` 85 | 对7,30,8的请求与SSTF方法结果相同。 86 | SATF明显优于SSTF的请求:7,6,24 87 | ``` 88 | ostep-homework-master\file-disks> python disk.py -a 7,6,24 -p SATF -G 89 | 90 | REQUESTS ['7', '6', '24'] 91 | 92 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 93 | Block: 24 Seek: 80 Rotate: 40 Transfer: 30 Total: 150 94 | Block: 6 Seek: 80 Rotate: 70 Transfer: 30 Total: 180 95 | 96 | TOTALS Seek:160 Rotate:125 Transfer: 90 Total: 375 97 | 98 | ostep-homework-master\file-disks> python disk.py -a 7,6,24 -p SSTF -G 99 | 100 | REQUESTS ['7', '6', '24'] 101 | 102 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 103 | Block: 6 Seek: 0 Rotate:300 Transfer: 30 Total: 330 104 | Block: 24 Seek: 80 Rotate: 70 Transfer: 30 Total: 180 105 | 106 | TOTALS Seek: 80 Rotate:385 Transfer: 90 Total: 555 107 | ``` 108 | 出现差异的原因是同一磁道的旋转时间太长,大于先去其它磁道读取再回来的时间。 109 | 110 | * **问题 6 答案** 111 | 因为磁盘寻道的同时也在旋转,因此到了下一个磁道时已经超过应该读取的位置了,只能额外转一圈。 112 | ``` 113 | ostep-homework-master\file-disks> python disk.py -a 10,11,12,13 -o 2 -G 114 | 115 | REQUESTS ['10', '11', '12', '13'] 116 | 117 | Block: 10 Seek: 0 Rotate:105 Transfer: 30 Total: 135 118 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 119 | Block: 12 Seek: 40 Rotate: 20 Transfer: 30 Total: 90 120 | Block: 13 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 121 | 122 | TOTALS Seek: 40 Rotate:125 Transfer:120 Total: 285 123 | 124 | ostep-homework-master\file-disks> python disk.py -a 10,11,12,13 -S 2 -o 1 -G 125 | 126 | REQUESTS ['10', '11', '12', '13'] 127 | 128 | Block: 10 Seek: 0 Rotate:105 Transfer: 30 Total: 135 129 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 130 | Block: 12 Seek: 20 Rotate: 10 Transfer: 30 Total: 60 131 | Block: 13 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 132 | 133 | TOTALS Seek: 20 Rotate:115 Transfer:120 Total: 255 134 | 135 | ostep-homework-master\file-disks> python disk.py -a 10,11,12,13 -S 4 -o 1 -G 136 | 137 | REQUESTS ['10', '11', '12', '13'] 138 | 139 | Block: 10 Seek: 0 Rotate:105 Transfer: 30 Total: 135 140 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 141 | Block: 12 Seek: 10 Rotate: 20 Transfer: 30 Total: 60 142 | Block: 13 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 143 | 144 | TOTALS Seek: 10 Rotate:125 Transfer:120 Total: 255 145 | ``` 146 | 实际的偏斜距离要大于单个寻道时间磁盘旋转的距离。 147 | 148 | * **问题 7 答案** 149 | ``` 150 | ostep-homework-master\file-disks> python disk.py -z 10,20,30 -a -1 -A 5,-1,0 -s 1 -G 151 | 152 | REQUESTS [7, 45, 41, 13, 26] 153 | 154 | Block: 7 Seek: 0 Rotate:245 Transfer: 10 Total: 255 155 | Block: 45 Seek: 40 Rotate: 55 Transfer: 20 Total: 115 156 | Block: 41 Seek: 0 Rotate:260 Transfer: 20 Total: 280 157 | Block: 13 Seek: 40 Rotate:335 Transfer: 10 Total: 385 158 | Block: 26 Seek: 0 Rotate:120 Transfer: 10 Total: 130 159 | 160 | TOTALS Seek: 80 Rotate:1015 Transfer: 70 Total:1165 161 | 162 | ostep-homework-master\file-disks> python disk.py -z 10,20,30 -a -1 -A 5,-1,0 -s 2 -G 163 | 164 | REQUESTS [51, 51, 3, 4, 45] 165 | 166 | Block: 51 Seek: 40 Rotate: 70 Transfer: 20 Total: 130 167 | Block: 51 Seek: 0 Rotate:340 Transfer: 20 Total: 360 168 | Block: 3 Seek: 40 Rotate: 35 Transfer: 10 Total: 85 169 | Block: 4 Seek: 0 Rotate: 0 Transfer: 10 Total: 10 170 | Block: 45 Seek: 40 Rotate: 85 Transfer: 20 Total: 145 171 | 172 | TOTALS Seek:120 Rotate:530 Transfer: 80 Total: 730 173 | ``` 174 | 单位时间扇区数: 175 | 内圈1/30,中圈1/20,外圈1/10. 176 | 177 | * **问题 8 答案** 178 | ``` 179 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 1 -c 180 | TOTALS Seek:20960 Rotate:169165 Transfer:30000 Total:220125 181 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 5 -c 182 | TOTALS Seek:11280 Rotate:44955 Transfer:30000 Total:86235 183 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 10 -c 184 | TOTALS Seek:8080 Rotate:26555 Transfer:30000 Total:64635 185 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 25 -c 186 | TOTALS Seek:3440 Rotate:11395 Transfer:30000 Total:44835 187 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 50 -c 188 | TOTALS Seek:1680 Rotate:7035 Transfer:30000 Total:38715 189 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 75 -c 190 | TOTALS Seek:1760 Rotate:6595 Transfer:30000 Total:38355 191 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 100 -c 192 | TOTALS Seek:1440 Rotate:5835 Transfer:30000 Total:37275 193 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 200 -c 194 | TOTALS Seek:960 Rotate:4515 Transfer:30000 Total:35475 195 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 300 -c 196 | TOTALS Seek:1120 Rotate:4355 Transfer:30000 Total:35475 197 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 500 -c 198 | TOTALS Seek:1280 Rotate:4195 Transfer:30000 Total:35475 199 | ostep-homework-master\file-disks> python disk.py -A 1000,-1,0 -p SATF -w 1000 -c 200 | TOTALS Seek:1520 Rotate:3955 Transfer:30000 Total:35475 201 | ``` 202 | ![所需时间](1.png) 203 | 204 | * **问题 9 答案** 205 | 导致第一个请求的扇区饥饿的序列: 206 | ``` 207 | ostep-homework-master\file-disks> python disk.py -a 24,7,8,9,10,11,0,1,2,3,4,5,6 -p SATF -G 208 | 209 | REQUESTS ['24', '7', '8', '9', '10', '11', '0', '1', '2', '3', '4', '5', '6'] 210 | 211 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 212 | Block: 8 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 213 | Block: 9 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 214 | Block: 10 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 215 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 216 | Block: 0 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 217 | Block: 1 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 218 | Block: 2 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 219 | Block: 3 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 220 | Block: 4 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 221 | Block: 5 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 222 | Block: 6 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 223 | Block: 24 Seek: 80 Rotate: 70 Transfer: 30 Total: 180 224 | 225 | TOTALS Seek: 80 Rotate: 85 Transfer:390 Total: 555 226 | ``` 227 | 使用有界的SATF方法: 228 | ``` 229 | ostep-homework-master\file-disks> python disk.py -a 24,7,8,9,10,11,0,1,2,3,4,5,6 -p BSATF -w 4 -G 230 | 231 | REQUESTS ['24', '7', '8', '9', '10', '11', '0', '1', '2', '3', '4', '5', '6'] 232 | 233 | Block: 7 Seek: 0 Rotate: 15 Transfer: 30 Total: 45 234 | Block: 8 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 235 | Block: 9 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 236 | Block: 24 Seek: 80 Rotate:340 Transfer: 30 Total: 450 237 | Block: 10 Seek: 80 Rotate:190 Transfer: 30 Total: 300 238 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 239 | Block: 0 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 240 | Block: 1 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 241 | Block: 2 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 242 | Block: 3 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 243 | Block: 4 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 244 | Block: 5 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 245 | Block: 6 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 246 | 247 | TOTALS Seek:160 Rotate:545 Transfer:390 Total:1095 248 | ``` 249 | 可以解决饥饿问题,但是IO时间增加了。 250 | 应该设置合适的窗口大小,在性能和避免饥饿之间平衡。 251 | 252 | * **问题 10 答案** 253 | 全局最优的调度比贪婪方法好的例子 10,11,0,21,1,2,3,4,5,6 254 | 全局最优由FIFO方法,手动指定全局调度结果。 255 | ``` 256 | ostep-homework-master\file-disks> python disk.py -a 10,11,0,21,1,2,3,4,5,6 -p SATF -G 257 | 258 | REQUESTS ['10', '11', '0', '21', '1', '2', '3', '4', '5', '6'] 259 | 260 | Block: 21 Seek: 40 Rotate: 35 Transfer: 30 Total: 105 261 | Block: 0 Seek: 40 Rotate: 20 Transfer: 30 Total: 90 262 | Block: 1 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 263 | Block: 2 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 264 | Block: 3 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 265 | Block: 4 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 266 | Block: 5 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 267 | Block: 6 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 268 | Block: 10 Seek: 0 Rotate: 90 Transfer: 30 Total: 120 269 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 270 | 271 | TOTALS Seek: 80 Rotate:145 Transfer:300 Total: 525 272 | 273 | ostep-homework-master\file-disks> python disk.py -a 10,11,0,1,2,3,4,5,6,21 -G 274 | 275 | REQUESTS ['10', '11', '0', '1', '2', '3', '4', '5', '6', '21'] 276 | 277 | Block: 10 Seek: 0 Rotate:105 Transfer: 30 Total: 135 278 | Block: 11 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 279 | Block: 0 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 280 | Block: 1 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 281 | Block: 2 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 282 | Block: 3 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 283 | Block: 4 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 284 | Block: 5 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 285 | Block: 6 Seek: 0 Rotate: 0 Transfer: 30 Total: 30 286 | Block: 21 Seek: 40 Rotate: 20 Transfer: 30 Total: 90 287 | 288 | TOTALS Seek: 40 Rotate:125 Transfer:300 Total: 465 289 | ``` 290 | -------------------------------------------------------------------------------- /Chapter-38/Chapter-38-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 5 -R 20 -5 LS -c 4 | ARG blockSize 4096 5 | ARG seed 0 6 | ARG numDisks 4 7 | ARG chunkSize 4k 8 | ARG numRequests 5 9 | ARG reqSize 4k 10 | ARG workload rand 11 | ARG writeFrac 0 12 | ARG randRange 20 13 | ARG level 5 14 | ARG raid5 LS 15 | ARG reverse False 16 | ARG timing False 17 | 18 | 16 1 19 | LOGICAL READ from addr:16 size:4096 20 | read [disk 0, offset 5] 21 | 8 1 22 | LOGICAL READ from addr:8 size:4096 23 | read [disk 0, offset 2] 24 | 10 1 25 | LOGICAL READ from addr:10 size:4096 26 | read [disk 2, offset 3] 27 | 15 1 28 | LOGICAL READ from addr:15 size:4096 29 | read [disk 3, offset 5] 30 | 9 1 31 | LOGICAL READ from addr:9 size:4096 32 | read [disk 1, offset 3] 33 | 34 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 5 -R 20 -5 LA -c 35 | ARG blockSize 4096 36 | ARG seed 0 37 | ARG numDisks 4 38 | ARG chunkSize 4k 39 | ARG numRequests 5 40 | ARG reqSize 4k 41 | ARG workload rand 42 | ARG writeFrac 0 43 | ARG randRange 20 44 | ARG level 5 45 | ARG raid5 LA 46 | ARG reverse False 47 | ARG timing False 48 | 49 | 16 1 50 | LOGICAL READ from addr:16 size:4096 51 | read [disk 1, offset 5] 52 | 8 1 53 | LOGICAL READ from addr:8 size:4096 54 | read [disk 3, offset 2] 55 | 10 1 56 | LOGICAL READ from addr:10 size:4096 57 | read [disk 2, offset 3] 58 | 15 1 59 | LOGICAL READ from addr:15 size:4096 60 | read [disk 0, offset 5] 61 | 9 1 62 | LOGICAL READ from addr:9 size:4096 63 | read [disk 1, offset 3] 64 | ``` 65 | RAID5的左对称和左不对称布局有较大区别,详情上网搜索一下即可。 66 | 67 | * **问题 2 答案** 68 | ``` 69 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 0 -C 8192 -R 20 -c 70 | ARG blockSize 4096 71 | ARG seed 0 72 | ARG numDisks 4 73 | ARG chunkSize 8192 74 | ARG numRequests 5 75 | ARG reqSize 4k 76 | ARG workload rand 77 | ARG writeFrac 0 78 | ARG randRange 20 79 | ARG level 0 80 | ARG raid5 LS 81 | ARG reverse False 82 | ARG timing False 83 | 84 | 16 1 85 | LOGICAL READ from addr:16 size:4096 86 | read [disk 0, offset 4] 87 | 88 | 8 1 89 | LOGICAL READ from addr:8 size:4096 90 | read [disk 0, offset 2] 91 | 92 | 10 1 93 | LOGICAL READ from addr:10 size:4096 94 | read [disk 1, offset 2] 95 | 96 | 15 1 97 | LOGICAL READ from addr:15 size:4096 98 | read [disk 3, offset 3] 99 | 100 | 9 1 101 | LOGICAL READ from addr:9 size:4096 102 | read [disk 0, offset 3] 103 | 104 | 105 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 0 -C 16384 -R 20 -c 106 | ARG blockSize 4096 107 | ARG seed 0 108 | ARG numDisks 4 109 | ARG chunkSize 16384 110 | ARG numRequests 5 111 | ARG reqSize 4k 112 | ARG workload rand 113 | ARG writeFrac 0 114 | ARG randRange 20 115 | ARG level 0 116 | ARG raid5 LS 117 | ARG reverse False 118 | ARG timing False 119 | 120 | 16 1 121 | LOGICAL READ from addr:16 size:4096 122 | read [disk 0, offset 4] 123 | 124 | 8 1 125 | LOGICAL READ from addr:8 size:4096 126 | read [disk 2, offset 0] 127 | 128 | 10 1 129 | LOGICAL READ from addr:10 size:4096 130 | read [disk 2, offset 2] 131 | 132 | 15 1 133 | LOGICAL READ from addr:15 size:4096 134 | read [disk 3, offset 3] 135 | 136 | 9 1 137 | LOGICAL READ from addr:9 size:4096 138 | read [disk 2, offset 1] 139 | ``` 140 | 141 | * **问题 3 答案** 142 | ``` 143 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 0 -R 20 -r -c 144 | ARG blockSize 4096 145 | ARG seed 0 146 | ARG numDisks 4 147 | ARG chunkSize 4k 148 | ARG numRequests 5 149 | ARG reqSize 4k 150 | ARG workload rand 151 | ARG writeFrac 0 152 | ARG randRange 20 153 | ARG level 0 154 | ARG raid5 LS 155 | ARG reverse True 156 | ARG timing False 157 | 158 | 16 1 159 | LOGICAL READ from addr:16 size:4096 160 | read [disk 0, offset 4] 161 | 162 | 8 1 163 | LOGICAL READ from addr:8 size:4096 164 | read [disk 0, offset 2] 165 | 166 | 10 1 167 | LOGICAL READ from addr:10 size:4096 168 | read [disk 2, offset 2] 169 | 170 | 15 1 171 | LOGICAL READ from addr:15 size:4096 172 | read [disk 3, offset 3] 173 | 174 | 9 1 175 | LOGICAL READ from addr:9 size:4096 176 | read [disk 1, offset 2] 177 | ``` 178 | 179 | * **问题 4 答案** 180 | ``` 181 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 4 -R 20 -r -S 8k -W seq -c 182 | ARG blockSize 4096 183 | ARG seed 0 184 | ARG numDisks 4 185 | ARG chunkSize 4k 186 | ARG numRequests 5 187 | ARG reqSize 8k 188 | ARG workload seq 189 | ARG writeFrac 0 190 | ARG randRange 20 191 | ARG level 4 192 | ARG raid5 LS 193 | ARG reverse True 194 | ARG timing False 195 | 196 | 0 2 197 | LOGICAL READ from addr:0 size:8192 198 | read [disk 0, offset 0] read [disk 1, offset 0] 199 | 2 2 200 | LOGICAL READ from addr:2 size:8192 201 | read [disk 2, offset 0] read [disk 0, offset 1] 202 | 4 2 203 | LOGICAL READ from addr:4 size:8192 204 | read [disk 1, offset 1] read [disk 2, offset 1] 205 | 6 2 206 | LOGICAL READ from addr:6 size:8192 207 | read [disk 0, offset 2] read [disk 1, offset 2] 208 | 8 2 209 | LOGICAL READ from addr:8 size:8192 210 | read [disk 2, offset 2] read [disk 0, offset 3] 211 | 212 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 4 -R 20 -r -S 12k -W seq -c 213 | ARG blockSize 4096 214 | ARG seed 0 215 | ARG numDisks 4 216 | ARG chunkSize 4k 217 | ARG numRequests 5 218 | ARG reqSize 12k 219 | ARG workload seq 220 | ARG writeFrac 0 221 | ARG randRange 20 222 | ARG level 4 223 | ARG raid5 LS 224 | ARG reverse True 225 | ARG timing False 226 | 227 | 0 3 228 | LOGICAL READ from addr:0 size:12288 229 | read [disk 0, offset 0] read [disk 1, offset 0] read [disk 2, offset 0] 230 | 3 3 231 | LOGICAL READ from addr:3 size:12288 232 | read [disk 0, offset 1] read [disk 1, offset 1] read [disk 2, offset 1] 233 | 6 3 234 | LOGICAL READ from addr:6 size:12288 235 | read [disk 0, offset 2] read [disk 1, offset 2] read [disk 2, offset 2] 236 | 9 3 237 | LOGICAL READ from addr:9 size:12288 238 | read [disk 0, offset 3] read [disk 1, offset 3] read [disk 2, offset 3] 239 | 12 3 240 | LOGICAL READ from addr:12 size:12288 241 | read [disk 0, offset 4] read [disk 1, offset 4] read [disk 2, offset 4] 242 | 243 | [testjz@localhost file-raid]$ ./raid.py -n 5 -L 4 -R 20 -r -S 16k -W seq -c 244 | ARG blockSize 4096 245 | ARG seed 0 246 | ARG numDisks 4 247 | ARG chunkSize 4k 248 | ARG numRequests 5 249 | ARG reqSize 16k 250 | ARG workload seq 251 | ARG writeFrac 0 252 | ARG randRange 20 253 | ARG level 4 254 | ARG raid5 LS 255 | ARG reverse True 256 | ARG timing False 257 | 258 | 0 4 259 | LOGICAL READ from addr:0 size:16384 260 | read [disk 0, offset 0] read [disk 1, offset 0] read [disk 2, offset 0] read [disk 0, offset 1] 261 | 4 4 262 | LOGICAL READ from addr:4 size:16384 263 | read [disk 1, offset 1] read [disk 2, offset 1] read [disk 0, offset 2] read [disk 1, offset 2] 264 | 8 4 265 | LOGICAL READ from addr:8 size:16384 266 | read [disk 2, offset 2] read [disk 0, offset 3] read [disk 1, offset 3] read [disk 2, offset 3] 267 | 12 4 268 | LOGICAL READ from addr:12 size:16384 269 | read [disk 0, offset 4] read [disk 1, offset 4] read [disk 2, offset 4] read [disk 0, offset 5] 270 | 16 4 271 | LOGICAL READ from addr:16 size:16384 272 | read [disk 1, offset 5] read [disk 2, offset 5] read [disk 0, offset 6] read [disk 1, offset 6] 273 | ``` 274 | 相比于RAID1,RAID4/5在更大的请求中工作效率更高,一般超过N/2个磁盘。 275 | 276 | * **问题 5 答案** 277 | ``` 278 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 0 -R 1000 -W rand -t -c 279 | ARG blockSize 4096 280 | ARG seed 0 281 | ARG numDisks 4 282 | ARG chunkSize 4k 283 | ARG numRequests 100 284 | ARG reqSize 4k 285 | ARG workload rand 286 | ARG writeFrac 0 287 | ARG randRange 1000 288 | ARG level 0 289 | ARG raid5 LS 290 | ARG reverse False 291 | ARG timing True 292 | 293 | 294 | disk:0 busy: 93.02 I/Os: 24 (sequential:0 nearly:13 random:11) 295 | disk:1 busy: 100.00 I/Os: 25 (sequential:1 nearly:11 random:13) 296 | disk:2 busy: 98.54 I/Os: 26 (sequential:0 nearly:16 random:10) 297 | disk:3 busy: 96.45 I/Os: 25 (sequential:0 nearly:17 random:8) 298 | 299 | STAT totalTime 177.6 300 | 301 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 1 -R 1000 -W rand -t -c 302 | ARG blockSize 4096 303 | ARG seed 0 304 | ARG numDisks 4 305 | ARG chunkSize 4k 306 | ARG numRequests 100 307 | ARG reqSize 4k 308 | ARG workload rand 309 | ARG writeFrac 0 310 | ARG randRange 1000 311 | ARG level 1 312 | ARG raid5 LS 313 | ARG reverse False 314 | ARG timing True 315 | 316 | disk:0 busy: 86.52 I/Os: 24 (sequential:0 nearly:8 random:16) 317 | disk:1 busy: 100.00 I/Os: 26 (sequential:0 nearly:11 random:15) 318 | disk:2 busy: 91.91 I/Os: 25 (sequential:0 nearly:7 random:18) 319 | disk:3 busy: 93.28 I/Os: 25 (sequential:0 nearly:8 random:17) 320 | 321 | STAT totalTime 226.3 322 | 323 | 324 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 4 -R 1000 -W rand -t -c 325 | ARG blockSize 4096 326 | ARG seed 0 327 | ARG numDisks 4 328 | ARG chunkSize 4k 329 | ARG numRequests 100 330 | ARG reqSize 4k 331 | ARG workload rand 332 | ARG writeFrac 0 333 | ARG randRange 1000 334 | ARG level 4 335 | ARG raid5 LS 336 | ARG reverse False 337 | ARG timing True 338 | 339 | disk:0 busy: 96.95 I/Os: 32 (sequential:0 nearly:17 random:15) 340 | disk:1 busy: 99.41 I/Os: 34 (sequential:0 nearly:20 random:14) 341 | disk:2 busy: 100.00 I/Os: 34 (sequential:0 nearly:22 random:12) 342 | disk:3 busy: 0.00 I/Os: 0 (sequential:0 nearly:0 random:0) 343 | 344 | STAT totalTime 235.9 345 | 346 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 5 -R 1000 -W rand -t -c 347 | ARG blockSize 4096 348 | ARG seed 0 349 | ARG numDisks 4 350 | ARG chunkSize 4k 351 | ARG numRequests 100 352 | ARG reqSize 4k 353 | ARG workload rand 354 | ARG writeFrac 0 355 | ARG randRange 1000 356 | ARG level 5 357 | ARG raid5 LS 358 | ARG reverse False 359 | ARG timing True 360 | 361 | disk:0 busy: 91.33 I/Os: 24 (sequential:0 nearly:11 random:13) 362 | disk:1 busy: 97.52 I/Os: 25 (sequential:1 nearly:10 random:14) 363 | disk:2 busy: 100.00 I/Os: 26 (sequential:0 nearly:14 random:12) 364 | disk:3 busy: 97.97 I/Os: 25 (sequential:0 nearly:12 random:13) 365 | 366 | STAT totalTime 197.2 367 | ``` 368 | 369 | * **问题 6 答案** 370 | ``` 371 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 5 -R 5000 -W rand -t -c 372 | ARG blockSize 4096 373 | ARG seed 0 374 | ARG numDisks 4 375 | ARG chunkSize 4k 376 | ARG numRequests 100 377 | ARG reqSize 4k 378 | ARG workload rand 379 | ARG writeFrac 0 380 | ARG randRange 5000 381 | ARG level 5 382 | ARG raid5 LS 383 | ARG reverse False 384 | ARG timing True 385 | 386 | disk:0 busy: 73.09 I/Os: 24 (sequential:0 nearly:3 random:21) 387 | disk:1 busy: 60.92 I/Os: 19 (sequential:0 nearly:1 random:18) 388 | disk:2 busy: 100.00 I/Os: 33 (sequential:0 nearly:4 random:29) 389 | disk:3 busy: 78.29 I/Os: 24 (sequential:0 nearly:0 random:24) 390 | 391 | STAT totalTime 309.6 392 | ``` 393 | 增加磁盘数量后,邻近的频率变少,因此速度变慢。 394 | 395 | * **问题 7 答案** 396 | ``` 397 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 0 -R 1000 -W rand -t -w 100 -c 398 | ARG blockSize 4096 399 | ARG seed 0 400 | ARG numDisks 4 401 | ARG chunkSize 4k 402 | ARG numRequests 100 403 | ARG reqSize 4k 404 | ARG workload rand 405 | ARG writeFrac 100 406 | ARG randRange 1000 407 | ARG level 0 408 | ARG raid5 LS 409 | ARG reverse False 410 | ARG timing True 411 | 412 | disk:0 busy: 93.02 I/Os: 24 (sequential:0 nearly:13 random:11) 413 | disk:1 busy: 100.00 I/Os: 25 (sequential:1 nearly:11 random:13) 414 | disk:2 busy: 98.54 I/Os: 26 (sequential:0 nearly:16 random:10) 415 | disk:3 busy: 96.45 I/Os: 25 (sequential:0 nearly:17 random:8) 416 | 417 | STAT totalTime 177.6 418 | 419 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 1 -R 1000 -W rand -t -w 100 -c 420 | ARG blockSize 4096 421 | ARG seed 0 422 | ARG numDisks 4 423 | ARG chunkSize 4k 424 | ARG numRequests 100 425 | ARG reqSize 4k 426 | ARG workload rand 427 | ARG writeFrac 100 428 | ARG randRange 1000 429 | ARG level 1 430 | ARG raid5 LS 431 | ARG reverse False 432 | ARG timing True 433 | 434 | disk:0 busy: 96.71 I/Os: 50 (sequential:0 nearly:21 random:29) 435 | disk:1 busy: 96.71 I/Os: 50 (sequential:0 nearly:21 random:29) 436 | disk:2 busy: 100.00 I/Os: 50 (sequential:0 nearly:15 random:35) 437 | disk:3 busy: 100.00 I/Os: 50 (sequential:0 nearly:15 random:35) 438 | 439 | STAT totalTime 424.9 440 | 441 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 4 -R 1000 -W rand -t -w 100 -c 442 | ARG blockSize 4096 443 | ARG seed 0 444 | ARG numDisks 4 445 | ARG chunkSize 4k 446 | ARG numRequests 100 447 | ARG reqSize 4k 448 | ARG workload rand 449 | ARG writeFrac 100 450 | ARG randRange 1000 451 | ARG level 4 452 | ARG raid5 LS 453 | ARG reverse False 454 | ARG timing True 455 | 456 | disk:0 busy: 31.95 I/Os: 64 (sequential:0 nearly:49 random:15) 457 | disk:1 busy: 32.77 I/Os: 68 (sequential:0 nearly:54 random:14) 458 | disk:2 busy: 32.96 I/Os: 68 (sequential:0 nearly:56 random:12) 459 | disk:3 busy: 100.00 I/Os: 200 (sequential:0 nearly:154 random:46) 460 | 461 | STAT totalTime 715.7 462 | 463 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 5 -R 1000 -W rand -t -w 100 -c 464 | ARG blockSize 4096 465 | ARG seed 0 466 | ARG numDisks 4 467 | ARG chunkSize 4k 468 | ARG numRequests 100 469 | ARG reqSize 4k 470 | ARG workload rand 471 | ARG writeFrac 100 472 | ARG randRange 1000 473 | ARG level 5 474 | ARG raid5 LS 475 | ARG reverse False 476 | ARG timing True 477 | 478 | disk:0 busy: 100.00 I/Os: 122 (sequential:1 nearly:92 random:29) 479 | disk:1 busy: 82.33 I/Os: 96 (sequential:0 nearly:76 random:20) 480 | disk:2 busy: 67.34 I/Os: 86 (sequential:0 nearly:69 random:17) 481 | disk:3 busy: 79.73 I/Os: 96 (sequential:0 nearly:73 random:23) 482 | 483 | STAT totalTime 443.6 484 | ``` 485 | 486 | * **问题 8 答案** 487 | ``` 488 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 0 -R 1000 -W seq -t -w 100 -c 489 | ARG blockSize 4096 490 | ARG seed 0 491 | ARG numDisks 4 492 | ARG chunkSize 4k 493 | ARG numRequests 100 494 | ARG reqSize 4k 495 | ARG workload seq 496 | ARG writeFrac 100 497 | ARG randRange 1000 498 | ARG level 0 499 | ARG raid5 LS 500 | ARG reverse False 501 | ARG timing True 502 | 503 | disk:0 busy: 100.00 I/Os: 25 (sequential:24 nearly:0 random:1) 504 | disk:1 busy: 100.00 I/Os: 25 (sequential:24 nearly:0 random:1) 505 | disk:2 busy: 100.00 I/Os: 25 (sequential:24 nearly:0 random:1) 506 | disk:3 busy: 100.00 I/Os: 25 (sequential:24 nearly:0 random:1) 507 | 508 | STAT totalTime 12.5 509 | 510 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 1 -R 1000 -W seq -t -w 100 -c 511 | ARG blockSize 4096 512 | ARG seed 0 513 | ARG numDisks 4 514 | ARG chunkSize 4k 515 | ARG numRequests 100 516 | ARG reqSize 4k 517 | ARG workload seq 518 | ARG writeFrac 100 519 | ARG randRange 1000 520 | ARG level 1 521 | ARG raid5 LS 522 | ARG reverse False 523 | ARG timing True 524 | 525 | disk:0 busy: 100.00 I/Os: 50 (sequential:49 nearly:0 random:1) 526 | disk:1 busy: 100.00 I/Os: 50 (sequential:49 nearly:0 random:1) 527 | disk:2 busy: 100.00 I/Os: 50 (sequential:49 nearly:0 random:1) 528 | disk:3 busy: 100.00 I/Os: 50 (sequential:49 nearly:0 random:1) 529 | 530 | STAT totalTime 15.0 531 | 532 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 4 -R 1000 -W seq -t -w 100 -c 533 | ARG blockSize 4096 534 | ARG seed 0 535 | ARG numDisks 4 536 | ARG chunkSize 4k 537 | ARG numRequests 100 538 | ARG reqSize 4k 539 | ARG workload seq 540 | ARG writeFrac 100 541 | ARG randRange 1000 542 | ARG level 4 543 | ARG raid5 LS 544 | ARG reverse False 545 | ARG timing True 546 | 547 | disk:0 busy: 100.00 I/Os: 68 (sequential:33 nearly:34 random:1) 548 | disk:1 busy: 99.25 I/Os: 66 (sequential:32 nearly:33 random:1) 549 | disk:2 busy: 99.25 I/Os: 66 (sequential:32 nearly:33 random:1) 550 | disk:3 busy: 100.00 I/Os: 200 (sequential:33 nearly:166 random:1) 551 | 552 | STAT totalTime 13.4 553 | 554 | [testjz@localhost file-raid]$ ./raid.py -n 100 -L 5 -R 1000 -W seq -t -w 100 -c 555 | ARG blockSize 4096 556 | ARG seed 0 557 | ARG numDisks 4 558 | ARG chunkSize 4k 559 | ARG numRequests 100 560 | ARG reqSize 4k 561 | ARG workload seq 562 | ARG writeFrac 100 563 | ARG randRange 1000 564 | ARG level 5 565 | ARG raid5 LS 566 | ARG reverse False 567 | ARG timing True 568 | 569 | disk:0 busy: 99.25 I/Os: 98 (sequential:32 nearly:65 random:1) 570 | disk:1 busy: 99.25 I/Os: 98 (sequential:32 nearly:65 random:1) 571 | disk:2 busy: 100.00 I/Os: 100 (sequential:33 nearly:66 random:1) 572 | disk:3 busy: 100.00 I/Os: 104 (sequential:33 nearly:70 random:1) 573 | 574 | STAT totalTime 13.4 575 | ``` 576 | -------------------------------------------------------------------------------- /Chapter-39/39.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(int argc, char * argv[]) { 4 | if(argc < 2) 5 | return 0; 6 | struct stat st; 7 | stat(argv[1], &st); 8 | printf("inode: %d\n", st.st_ino); 9 | printf("hard link: %d\n", st.st_nlink); 10 | printf("total size: %d\n", st.st_size); 11 | printf("blocks: %d\n", st.st_blocks); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Chapter-39/39.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int main(int argc, char * argv[]) { 7 | char * sdir = "."; 8 | if(argc > 1) 9 | sdir = argv[1]; 10 | int flag = 0; 11 | if(argc > 2 && strcmp(argv[2], "-l") == 0) 12 | flag = 1; 13 | DIR * dp = opendir(sdir); 14 | assert(dp != NULL); 15 | struct dirent *d; 16 | while((d = readdir(dp)) != NULL) { 17 | printf("%s\n", d->d_name); 18 | if(flag) { 19 | char filestr[200] = ""; 20 | strcat(filestr, sdir); 21 | strcat(filestr, "/"); 22 | strcat(filestr, d->d_name); 23 | struct stat st; 24 | stat(filestr, &st); 25 | printf("inode: %d uid: %d mode: %d\n", st.st_ino, st.st_uid, st.st_mode); 26 | } 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /Chapter-39/39.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int main(int argc, char *argv[]) { 6 | assert(argc > 2); 7 | assert(argv[1][0] == '-'); 8 | int n = atoi(&argv[1][1]); 9 | assert(n > 0); 10 | int fd = open(argv[2], O_RDONLY); 11 | assert(fd >= 0); 12 | char buf[1025]; 13 | int size; 14 | int lines = 1; 15 | while(1) { 16 | size = read(fd, buf, 1024); 17 | if(size == 0) 18 | break; 19 | int i; 20 | for(i = 0; i< size; ++i) 21 | if(buf[i] == '\n') 22 | lines++; 23 | } 24 | lines -= n; 25 | lseek(fd, 0, SEEK_SET); 26 | n = 1; 27 | while(1) { 28 | size = read(fd, buf, 1024); 29 | if(size == 0) 30 | break; 31 | int i; 32 | for(i = 0; i< size; ++i) { 33 | if(n >= lines) 34 | putchar(buf[i]); 35 | if(buf[i] == '\n') { 36 | ++n; 37 | } 38 | } 39 | } 40 | close(fd); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Chapter-39/39.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void readTotal(const char * sdir) { 8 | DIR * dp = opendir(sdir); 9 | assert(dp != NULL); 10 | struct dirent *d; 11 | while((d = readdir(dp)) != NULL) { 12 | if(strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) 13 | continue; 14 | printf("%s/%s\n", sdir, d->d_name); 15 | char filestr[200] = ""; 16 | strcat(filestr, sdir); 17 | strcat(filestr, "/"); 18 | strcat(filestr, d->d_name); 19 | struct stat st; 20 | stat(filestr, &st); 21 | if(S_ISDIR(st.st_mode)) 22 | readTotal(filestr); 23 | } 24 | } 25 | 26 | int main(int argc, char * argv[]) { 27 | char * sdir = "."; 28 | if(argc > 1) 29 | sdir = argv[1]; 30 | readTotal(sdir); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /Chapter-39/Chapter-39-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | [答案代码](39.1.c) 3 | ```C 4 | #include 5 | #include 6 | int main(int argc, char * argv[]) { 7 | if(argc < 2) 8 | return 0; 9 | struct stat st; 10 | stat(argv[1], &st); 11 | printf("inode: %d\n", st.st_ino); 12 | printf("hard link: %d\n", st.st_nlink); 13 | printf("total size: %d\n", st.st_size); 14 | printf("blocks: %d\n", st.st_blocks); 15 | return 0; 16 | } 17 | ``` 18 | 测试 19 | ``` 20 | [testjz@localhost OS_test]$ gcc -o 39.1 39.1.c 21 | [testjz@localhost OS_test]$ ./39.1 39.1.c 22 | inode: 19149 23 | hard link: 1 24 | total size: 309 25 | blocks: 8 26 | [testjz@localhost OS_test]$ ./39.1 . 27 | inode: 75 28 | hard link: 2 29 | total size: 4096 30 | blocks: 16 31 | [testjz@localhost OS_test]$ echo hello > file 32 | [testjz@localhost OS_test]$ ./39.1 . 33 | inode: 75 34 | hard link: 2 35 | total size: 4096 36 | blocks: 16 37 | ``` 38 | stat接口看不到什么目录的引用计数,只能看到硬链接。 39 | 40 | * **问题 2 答案** 41 | [答案代码](39.2.c) 42 | ```C 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | int main(int argc, char * argv[]) { 49 | char * sdir = "."; 50 | if(argc > 1) 51 | sdir = argv[1]; 52 | int flag = 0; 53 | if(argc > 2 && strcmp(argv[2], "-l") == 0) 54 | flag = 1; 55 | DIR * dp = opendir(sdir); 56 | assert(dp != NULL); 57 | struct dirent *d; 58 | while((d = readdir(dp)) != NULL) { 59 | printf("%s\n", d->d_name); 60 | if(flag) { 61 | char filestr[200] = ""; 62 | strcat(filestr, sdir); 63 | strcat(filestr, "/"); 64 | strcat(filestr, d->d_name); 65 | struct stat st; 66 | stat(filestr, &st); 67 | printf("inode: %d uid: %d mode: %d\n", st.st_ino, st.st_uid, st.st_mode); 68 | } 69 | } 70 | return 0; 71 | } 72 | ``` 73 | 测试 74 | ``` 75 | [testjz@localhost OS_test]$ gcc -o 39.2 39.2.c 76 | [testjz@localhost OS_test]$ ./39.2 abc 77 | . 78 | .. 79 | p1 80 | p1.c 81 | [testjz@localhost OS_test]$ ./39.2 abc -l 82 | . 83 | inode: 19157 uid: 1000 mode: 16877 84 | .. 85 | inode: 75 uid: 1000 mode: 16893 86 | p1 87 | inode: 4186 uid: 1000 mode: 33277 88 | p1.c 89 | inode: 12164 uid: 1000 mode: 33204 90 | ``` 91 | 92 | * **问题 3 答案** 93 | [答案代码](39.3.c) 94 | ```C 95 | #include 96 | #include 97 | #include 98 | #include 99 | int main(int argc, char *argv[]) { 100 | assert(argc > 2); 101 | assert(argv[1][0] == '-'); 102 | int n = atoi(&argv[1][1]); 103 | assert(n > 0); 104 | int fd = open(argv[2], O_RDONLY); 105 | assert(fd >= 0); 106 | char buf[1025]; 107 | int size; 108 | int lines = 1; 109 | while(1) { 110 | size = read(fd, buf, 1024); 111 | if(size == 0) 112 | break; 113 | int i; 114 | for(i = 0; i< size; ++i) 115 | if(buf[i] == '\n') 116 | lines++; 117 | } 118 | lines -= n; 119 | lseek(fd, 0, SEEK_SET); 120 | n = 1; 121 | while(1) { 122 | size = read(fd, buf, 1024); 123 | if(size == 0) 124 | break; 125 | int i; 126 | for(i = 0; i< size; ++i) { 127 | if(n >= lines) 128 | putchar(buf[i]); 129 | if(buf[i] == '\n') { 130 | ++n; 131 | } 132 | } 133 | } 134 | close(fd); 135 | return 0; 136 | } 137 | ``` 138 | 测试 139 | ``` 140 | [testjz@localhost OS_test]$ gcc -o 39.2 39.2.c 141 | [testjz@localhost OS_test]$ gcc -o 39.3 39.3.c 142 | [testjz@localhost OS_test]$ ./39.3 -1 39.3.c 143 | } 144 | [testjz@localhost OS_test]$ ./39.3 -3 39.3.c 145 | close(fd); 146 | return 0; 147 | } 148 | ``` 149 | 150 | * **问题 4 答案** 151 | [答案代码](39.4.c) 152 | ```C 153 | #include 154 | #include 155 | #include 156 | #include 157 | #include 158 | 159 | void readTotal(const char * sdir) { 160 | DIR * dp = opendir(sdir); 161 | assert(dp != NULL); 162 | struct dirent *d; 163 | while((d = readdir(dp)) != NULL) { 164 | if(strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) 165 | continue; 166 | printf("%s/%s\n", sdir, d->d_name); 167 | char filestr[200] = ""; 168 | strcat(filestr, sdir); 169 | strcat(filestr, "/"); 170 | strcat(filestr, d->d_name); 171 | struct stat st; 172 | stat(filestr, &st); 173 | if(S_ISDIR(st.st_mode)) 174 | readTotal(filestr); 175 | } 176 | } 177 | 178 | int main(int argc, char * argv[]) { 179 | char * sdir = "."; 180 | if(argc > 1) 181 | sdir = argv[1]; 182 | readTotal(sdir); 183 | return 0; 184 | } 185 | ``` 186 | 测试 187 | ``` 188 | [testjz@localhost OS_test]$ gcc -o 39.3 39.4.c 189 | [testjz@localhost OS_test]$ ./39.4 /home/testjz 190 | /home/testjz/.mozilla 191 | /home/testjz/.mozilla/extensions 192 | /home/testjz/.mozilla/plugins 193 | /home/testjz/.mozilla/firefox 194 | /home/testjz/.mozilla/firefox/1lzwsclw.default 195 | /home/testjz/.mozilla/firefox/1lzwsclw.default/times.json 196 | [testjz@localhost OS_test]$ ./39.4 197 | ./2.1.1.c 198 | ./common.h 199 | ./cpu 200 | ./2.2.1.c 201 | ``` 202 | 返回内容太多,后面不列出了 203 | 204 | -------------------------------------------------------------------------------- /Chapter-4/Chapter-4-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 3 | ``` 4 | [testjz@localhost cpu-intro]$ ./process-run.py -l 5:100,5:100 5 | Produce a trace of what would happen when you run these processes: 6 | Process 0 7 | cpu 8 | cpu 9 | cpu 10 | cpu 11 | cpu 12 | 13 | Process 1 14 | cpu 15 | cpu 16 | cpu 17 | cpu 18 | cpu 19 | 20 | Important behaviors: 21 | System will switch whenthe current process is FINISHED or ISSUES AN IO 22 | After IOs, the process issuing the IO willrun LATER (when it is its turn) 23 | 24 | [testjz@localhost cpu-intro]$ ./process-run.py -l 5:100,5:100 -c 25 | Time PID: 0 PID: 1 CPU IOs 26 | 1 RUN:cpu READY 1 27 | 2 RUN:cpu READY 1 28 | 3 RUN:cpu READY 1 29 | 4 RUN:cpu READY 1 30 | 5 RUN:cpu READY 1 31 | 6 DONE RUN:cpu 1 32 | 7 DONE RUN:cpu 1 33 | 8 DONE RUN:cpu 1 34 | 9 DONE RUN:cpu 1 35 | 10 DONE RUN:cpu 1 36 | [testjz@localhost cpu-intro]$ 37 | ``` 38 | 39 | * **问题 2 答案** 40 | ``` 41 | [testjz@localhost cpu-intro]$ ./process-run.py -l 4:100,1:0 42 | Produce a trace of what would happen when you run these processes: 43 | Process 0 44 | cpu 45 | cpu 46 | cpu 47 | cpu 48 | 49 | Process 1 50 | io 51 | 52 | Important behaviors: 53 | System will switch whenthe current process is FINISHED or ISSUES AN IO 54 | After IOs, the process issuing the IO willrun LATER (when it is its turn) 55 | 56 | [testjz@localhost cpu-intro]$ ./process-run.py -l 4:100,1:0 -c 57 | Time PID: 0 PID: 1 CPU IOs 58 | 1 RUN:cpu READY 1 59 | 2 RUN:cpu READY 1 60 | 3 RUN:cpu READY 1 61 | 4 RUN:cpu READY 1 62 | 5 DONE RUN:io 1 63 | 6 DONE WAITING 1 64 | 7 DONE WAITING 1 65 | 8 DONE WAITING 1 66 | 9 DONE WAITING 1 67 | 10* DONE DONE 1 68 | [testjz@localhost cpu-intro]$ 69 | ``` 70 | 71 | * **问题 3 答案** 72 | ``` 73 | [testjz@localhost cpu-intro]$ ./process-run.py -l 1:0,4:100 74 | Produce a trace of what would happen when you run these processes: 75 | Process 0 76 | io 77 | 78 | Process 1 79 | cpu 80 | cpu 81 | cpu 82 | cpu 83 | 84 | Important behaviors: 85 | System will switch whenthe current process is FINISHED or ISSUES AN IO 86 | After IOs, the process issuing the IO willrun LATER (when it is its turn) 87 | 88 | [testjz@localhost cpu-intro]$ ./process-run.py -l 1:0,4:100 -c 89 | Time PID: 0 PID: 1 CPU IOs 90 | 1 RUN:io READY 1 91 | 2 WAITING RUN:cpu 1 1 92 | 3 WAITING RUN:cpu 1 1 93 | 4 WAITING RUN:cpu 1 1 94 | 5 WAITING RUN:cpu 1 1 95 | 6* DONE DONE 1 96 | [testjz@localhost cpu-intro]$ 97 | ``` 98 | 99 | * **问题 4 答案** 100 | ``` 101 | [testjz@localhost cpu-intro]$ ./process-run.py -l 1:0,4:100 -c -S SWITCH_ON_END 102 | Time PID: 0 PID: 1 CPU IOs 103 | 1 RUN:io READY 1 104 | 2 WAITING READY 1 105 | 3 WAITING READY 1 106 | 4 WAITING READY 1 107 | 5 WAITING READY 1 108 | 6* DONE RUN:cpu 1 109 | 7 DONE RUN:cpu 1 110 | 8 DONE RUN:cpu 1 111 | 9 DONE RUN:cpu 1 112 | [testjz@localhost cpu-intro]$ 113 | ``` 114 | 115 | * **问题 5 答案** 116 | ``` 117 | [testjz@localhost cpu-intro]$ ./process-run.py -l 1:0,4:100 -c -S SWITCH_ON_IO 118 | Time PID: 0 PID: 1 CPU IOs 119 | 1 RUN:io READY 1 120 | 2 WAITING RUN:cpu 1 1 121 | 3 WAITING RUN:cpu 1 1 122 | 4 WAITING RUN:cpu 1 1 123 | 5 WAITING RUN:cpu 1 1 124 | 6* DONE DONE 1 125 | [testjz@localhost cpu-intro]$ 126 | ``` 127 | 128 | * **问题 6 答案** 129 | ``` 130 | [testjz@localhost cpu-intro]$ ./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_LATER -c -p 131 | Time PID: 0 PID: 1 PID: 2 PID: 3 CPU IOs 132 | 1 RUN:io READY READY READY 1 133 | 2 WAITING RUN:cpu READY READY 1 1 134 | 3 WAITING RUN:cpu READY READY 1 1 135 | 4 WAITING RUN:cpu READY READY 1 1 136 | 5 WAITING RUN:cpu READY READY 1 1 137 | 6* READY RUN:cpu READY READY 1 138 | 7 READY DONE RUN:cpu READY 1 139 | 8 READY DONE RUN:cpu READY 1 140 | 9 READY DONE RUN:cpu READY 1 141 | 10 READY DONE RUN:cpu READY 1 142 | 11 READY DONE RUN:cpu READY 1 143 | 12 READY DONE DONE RUN:cpu 1 144 | 13 READY DONE DONE RUN:cpu 1 145 | 14 READY DONE DONE RUN:cpu 1 146 | 15 READY DONE DONE RUN:cpu 1 147 | 16 READY DONE DONE RUN:cpu 1 148 | 17 RUN:io DONE DONE DONE 1 149 | 18 WAITING DONE DONE DONE 1 150 | 19 WAITING DONE DONE DONE 1 151 | 20 WAITING DONE DONE DONE 1 152 | 21 WAITING DONE DONE DONE 1 153 | 22* RUN:io DONE DONE DONE 1 154 | 23 WAITING DONE DONE DONE 1 155 | 24 WAITING DONE DONE DONE 1 156 | 25 WAITING DONE DONE DONE 1 157 | 26 WAITING DONE DONE DONE 1 158 | 27* DONE DONE DONE DONE 1 159 | 160 | Stats: Total Time 27 161 | Stats: CPU Busy 19 (70.37%) 162 | Stats: IO Busy 12 (44.44%) 163 | 164 | [testjz@localhost cpu-intro]$ 165 | ``` 166 | 167 | * **问题 7 答案** 168 | ``` 169 | [testjz@localhost cpu-intro]$ ./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_IMMEDIATE -c -p 170 | Time PID: 0 PID: 1 PID: 2 PID: 3 CPU IOs 171 | 1 RUN:io READY READY READY 1 172 | 2 WAITING RUN:cpu READY READY 1 1 173 | 3 WAITING RUN:cpu READY READY 1 1 174 | 4 WAITING RUN:cpu READY READY 1 1 175 | 5 WAITING RUN:cpu READY READY 1 1 176 | 6* RUN:io READY READY READY 1 177 | 7 WAITING RUN:cpu READY READY 1 1 178 | 8 WAITING DONE RUN:cpu READY 1 1 179 | 9 WAITING DONE RUN:cpu READY 1 1 180 | 10 WAITING DONE RUN:cpu READY 1 1 181 | 11* RUN:io DONE READY READY 1 182 | 12 WAITING DONE RUN:cpu READY 1 1 183 | 13 WAITING DONE RUN:cpu READY 1 1 184 | 14 WAITING DONE DONE RUN:cpu 1 1 185 | 15 WAITING DONE DONE RUN:cpu 1 1 186 | 16* DONE DONE DONE RUN:cpu 1 187 | 17 DONE DONE DONE RUN:cpu 1 188 | 18 DONE DONE DONE RUN:cpu 1 189 | 190 | Stats: Total Time 18 191 | Stats: CPU Busy 18 (100.00%) 192 | Stats: IO Busy 12 (66.67%) 193 | 194 | [testjz@localhost cpu-intro]$ 195 | ``` 196 | 因为有过IO操作的进程很有可能后面也会进行IO操作,为了使CPU有效利用,应该在IO结束不久后运行该进程,使其得到继续阻塞IO的机会。 197 | 198 | * **问题 8 答案** 199 | 随机测试,无答案。 200 | -------------------------------------------------------------------------------- /Chapter-40/Chapter-40-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 答案太长,这里只给出命令 3 | ``` 4 | [testjz@localhost file-implementation]$ ./vsfs.py -s 17 -c 5 | [testjz@localhost file-implementation]$ ./vsfs.py -s 18 -c 6 | [testjz@localhost file-implementation]$ ./vsfs.py -s 19 -c 7 | [testjz@localhost file-implementation]$ ./vsfs.py -s 20 -c 8 | ``` 9 | 10 | * **问题 2 答案** 11 | 答案太长,这里只给出命令 12 | ``` 13 | [testjz@localhost file-implementation]$ ./vsfs.py -s 21 -r -c 14 | [testjz@localhost file-implementation]$ ./vsfs.py -s 22 -r -c 15 | [testjz@localhost file-implementation]$ ./vsfs.py -s 23 -r -c 16 | [testjz@localhost file-implementation]$ ./vsfs.py -s 24 -r -c 17 | ``` 18 | 喜欢从序列的前面往后分配。 19 | 20 | * **问题 3 答案** 21 | ``` 22 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -c 23 | ARG seed 0 24 | ARG numInodes 8 25 | ARG numData 2 26 | ARG numRequests 100 27 | ARG reverse False 28 | ARG printFinal False 29 | 30 | Initial state 31 | 32 | inode bitmap 10000000 33 | inodes [d a:0 r:2][][][][][][][] 34 | data bitmap 10 35 | data [(.,0) (..,0)][] 36 | 37 | mkdir("/g"); 38 | File system out of data blocks; rerun with more via command-line flag? 39 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 1 -c 40 | ARG seed 1 41 | ARG numInodes 8 42 | ARG numData 2 43 | ARG numRequests 100 44 | ARG reverse False 45 | ARG printFinal False 46 | 47 | Initial state 48 | 49 | inode bitmap 10000000 50 | inodes [d a:0 r:2][][][][][][][] 51 | data bitmap 10 52 | data [(.,0) (..,0)][] 53 | 54 | mkdir("/n"); 55 | File system out of data blocks; rerun with more via command-line flag? 56 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 2 -c 57 | ARG seed 2 58 | ARG numInodes 8 59 | ARG numData 2 60 | ARG numRequests 100 61 | ARG reverse False 62 | ARG printFinal False 63 | 64 | Initial state 65 | 66 | inode bitmap 10000000 67 | inodes [d a:0 r:2][][][][][][][] 68 | data bitmap 10 69 | data [(.,0) (..,0)][] 70 | 71 | mkdir("/c"); 72 | File system out of data blocks; rerun with more via command-line flag? 73 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 3 -c 74 | ARG seed 3 75 | ARG numInodes 8 76 | ARG numData 2 77 | ARG numRequests 100 78 | ARG reverse False 79 | ARG printFinal False 80 | 81 | Initial state 82 | 83 | inode bitmap 10000000 84 | inodes [d a:0 r:2][][][][][][][] 85 | data bitmap 10 86 | data [(.,0) (..,0)][] 87 | 88 | creat("/z"); 89 | 90 | inode bitmap 11000000 91 | inodes [d a:0 r:2][f a:-1 r:1][][][][][][] 92 | data bitmap 10 93 | data [(.,0) (..,0) (z,1)][] 94 | 95 | unlink("/z"); 96 | 97 | inode bitmap 10000000 98 | inodes [d a:0 r:2][][][][][][][] 99 | data bitmap 10 100 | data [(.,0) (..,0)][] 101 | 102 | creat("/s"); 103 | 104 | inode bitmap 11000000 105 | inodes [d a:0 r:2][f a:-1 r:1][][][][][][] 106 | data bitmap 10 107 | data [(.,0) (..,0) (s,1)][] 108 | 109 | fd=open("/s", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 110 | File system out of data blocks; rerun with more via command-line flag? 111 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 4 -c 112 | ARG seed 4 113 | ARG numInodes 8 114 | ARG numData 2 115 | ARG numRequests 100 116 | ARG reverse False 117 | ARG printFinal False 118 | 119 | Initial state 120 | 121 | inode bitmap 10000000 122 | inodes [d a:0 r:2][][][][][][][] 123 | data bitmap 10 124 | data [(.,0) (..,0)][] 125 | 126 | mkdir("/f"); 127 | File system out of data blocks; rerun with more via command-line flag? 128 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 5 -c 129 | ARG seed 5 130 | ARG numInodes 8 131 | ARG numData 2 132 | ARG numRequests 100 133 | ARG reverse False 134 | ARG printFinal False 135 | 136 | Initial state 137 | 138 | inode bitmap 10000000 139 | inodes [d a:0 r:2][][][][][][][] 140 | data bitmap 10 141 | data [(.,0) (..,0)][] 142 | 143 | mkdir("/t"); 144 | File system out of data blocks; rerun with more via command-line flag? 145 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 6 -c 146 | ARG seed 6 147 | ARG numInodes 8 148 | ARG numData 2 149 | ARG numRequests 100 150 | ARG reverse False 151 | ARG printFinal False 152 | 153 | Initial state 154 | 155 | inode bitmap 10000000 156 | inodes [d a:0 r:2][][][][][][][] 157 | data bitmap 10 158 | data [(.,0) (..,0)][] 159 | 160 | mkdir("/g"); 161 | File system out of data blocks; rerun with more via command-line flag? 162 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 7 -c 163 | ARG seed 7 164 | ARG numInodes 8 165 | ARG numData 2 166 | ARG numRequests 100 167 | ARG reverse False 168 | ARG printFinal False 169 | 170 | Initial state 171 | 172 | inode bitmap 10000000 173 | inodes [d a:0 r:2][][][][][][][] 174 | data bitmap 10 175 | data [(.,0) (..,0)][] 176 | 177 | creat("/r"); 178 | 179 | inode bitmap 11000000 180 | inodes [d a:0 r:2][f a:-1 r:1][][][][][][] 181 | data bitmap 10 182 | data [(.,0) (..,0) (r,1)][] 183 | 184 | creat("/z"); 185 | 186 | inode bitmap 11100000 187 | inodes [d a:0 r:2][f a:-1 r:1][f a:-1 r:1][][][][][] 188 | data bitmap 10 189 | data [(.,0) (..,0) (r,1) (z,2)][] 190 | 191 | fd=open("/z", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 192 | File system out of data blocks; rerun with more via command-line flag? 193 | [testjz@localhost file-implementation]$ ./vsfs.py -d 2 -n 100 -s 8 -c 194 | ARG seed 8 195 | ARG numInodes 8 196 | ARG numData 2 197 | ARG numRequests 100 198 | ARG reverse False 199 | ARG printFinal False 200 | 201 | Initial state 202 | 203 | inode bitmap 10000000 204 | inodes [d a:0 r:2][][][][][][][] 205 | data bitmap 10 206 | data [(.,0) (..,0)][] 207 | 208 | creat("/c"); 209 | 210 | inode bitmap 11000000 211 | inodes [d a:0 r:2][f a:-1 r:1][][][][][][] 212 | data bitmap 10 213 | data [(.,0) (..,0) (c,1)][] 214 | 215 | fd=open("/c", O_WRONLY|O_APPEND); write(fd, buf, BLOCKSIZE); close(fd); 216 | File system out of data blocks; rerun with more via command-line flag? 217 | ``` 218 | 创建目录会失败。创建文件成功,写入文件会失败。可以创建多个文件,可以unlink。 219 | 模拟器似乎要求必须剩下一个数据块不能被使用。 220 | 221 | * **问题 4 答案** 222 | ``` 223 | [testjz@localhost file-implementation]$ ./vsfs.py -i 2 -n 100 -s 1 -c 224 | ARG seed 1 225 | ARG numInodes 2 226 | ARG numData 8 227 | ARG numRequests 100 228 | ARG reverse False 229 | ARG printFinal False 230 | 231 | Initial state 232 | 233 | inode bitmap 10 234 | inodes [d a:0 r:2][] 235 | data bitmap 10000000 236 | data [(.,0) (..,0)][][][][][][][] 237 | 238 | mkdir("/n"); 239 | File system out of inodes; rerun with more via command-line flag? 240 | [testjz@localhost file-implementation]$ ./vsfs.py -i 2 -n 100 -s 2 -c 241 | ARG seed 2 242 | ARG numInodes 2 243 | ARG numData 8 244 | ARG numRequests 100 245 | ARG reverse False 246 | ARG printFinal False 247 | 248 | Initial state 249 | 250 | inode bitmap 10 251 | inodes [d a:0 r:2][] 252 | data bitmap 10000000 253 | data [(.,0) (..,0)][][][][][][][] 254 | 255 | mkdir("/c"); 256 | File system out of inodes; rerun with more via command-line flag? 257 | [testjz@localhost file-implementation]$ ./vsfs.py -i 2 -n 100 -s 3 -c 258 | ARG seed 3 259 | ARG numInodes 2 260 | ARG numData 8 261 | ARG numRequests 100 262 | ARG reverse False 263 | ARG printFinal False 264 | 265 | Initial state 266 | 267 | inode bitmap 10 268 | inodes [d a:0 r:2][] 269 | data bitmap 10000000 270 | data [(.,0) (..,0)][][][][][][][] 271 | 272 | creat("/z"); 273 | File system out of inodes; rerun with more via command-line flag? 274 | [testjz@localhost file-implementation]$ ./vsfs.py -i 2 -n 100 -s 4 -c 275 | ARG seed 4 276 | ARG numInodes 2 277 | ARG numData 8 278 | ARG numRequests 100 279 | ARG reverse False 280 | ARG printFinal False 281 | 282 | Initial state 283 | 284 | inode bitmap 10 285 | inodes [d a:0 r:2][] 286 | data bitmap 10000000 287 | data [(.,0) (..,0)][][][][][][][] 288 | 289 | mkdir("/f"); 290 | File system out of inodes; rerun with more via command-line flag? 291 | [testjz@localhost file-implementation]$ ./vsfs.py -i 2 -n 100 -s 5 -c 292 | ARG seed 5 293 | ARG numInodes 2 294 | ARG numData 8 295 | ARG numRequests 100 296 | ARG reverse False 297 | ARG printFinal False 298 | 299 | Initial state 300 | 301 | inode bitmap 10 302 | inodes [d a:0 r:2][] 303 | data bitmap 10000000 304 | data [(.,0) (..,0)][][][][][][][] 305 | 306 | mkdir("/t"); 307 | File system out of inodes; rerun with more via command-line flag? 308 | ``` 309 | 创建文件,创建目录都不行。 310 | 模拟器似乎也要求必须剩下一个inode块不能被使用。 311 | -------------------------------------------------------------------------------- /Chapter-49/Chapter-49-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 这里只给出简单例子,其它自行实验即可。 3 | ``` 4 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -n 2 -s 12 -f 2 -c 5 | ARG seed 12 6 | ARG numclients 2 7 | ARG numsteps 2 8 | ARG numfiles 2 9 | ARG readratio 0.5 10 | ARG actions 11 | ARG schedule 12 | ARG detail 0 13 | 14 | [(1, 'a', 0), (3, 0), (4, 0), (1, 'b', 1), (2, 1), (4, 1)] 15 | [(1, 'a', 0), (2, 0), (4, 0), (1, 'a', 1), (3, 1), (4, 1)] 16 | Server c0 c1 17 | file:a contains:0 18 | file:b contains:1 19 | open:a [fd:0] 20 | read:0 -> 0 21 | close:0 22 | open:a [fd:1] 23 | open:a [fd:0] 24 | write:0 0 -> 2 25 | close:0 26 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 27 | write:1 0 -> 3 28 | open:b [fd:1] 29 | close:1 30 | invalidate file:a cache: {'a': {'valid': True, 'data': 2, 'dirty': False, 'refcnt': 0}, 'b': {'valid': True, 'data': 1, 'dirty': False, 'refcnt': 1}} 31 | read:1 -> 1 32 | close:1 33 | file:a contains:3 34 | file:b contains:1 35 | ``` 36 | 37 | * **问题 2 答案** 38 | ``` 39 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -f 1 -s 2 -c -d 3 40 | ARG seed 2 41 | ARG numclients 2 42 | ARG numsteps 2 43 | ARG numfiles 1 44 | ARG readratio 0.5 45 | ARG actions 46 | ARG schedule 47 | ARG detail 3 48 | 49 | [(1, 'a', 0), (3, 0), (4, 0), (1, 'a', 1), (2, 1), (4, 1)] 50 | [(1, 'a', 0), (3, 0), (4, 0), (1, 'a', 1), (2, 1), (4, 1)] 51 | Server c0 c1 52 | file:a contains:0 53 | open:a [fd:0] 54 | getfile:a c:c1 [0] 55 | 56 | write:0 0 -> 1 57 | 58 | close:0 59 | putfile:a c:c1 [1] 60 | 61 | open:a [fd:0] 62 | getfile:a c:c0 [1] 63 | 64 | write:0 1 -> 2 65 | 66 | close:0 67 | putfile:a c:c0 [2] 68 | callback: c:c1 file:a 69 | invalidate file:a cache: {'a': {'valid': True, 'data': 1, 'dirty': False, 'refcnt': 0}} 70 | invalidate a 71 | 72 | open:a [fd:1] 73 | getfile:a c:c1 [2] 74 | 75 | read:1 -> 2 76 | 77 | close:1 78 | 79 | open:a [fd:1] 80 | 81 | read:1 -> 2 82 | 83 | close:1 84 | 85 | file:a contains:2 86 | ``` 87 | 当写文件然后关闭时,被写入的文件在其他客户端有副本时,发生回调。 88 | 89 | * **问题 3 答案** 90 | ``` 91 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -f 1 -s 3 -c -d 7 92 | ARG seed 3 93 | ARG numclients 2 94 | ARG numsteps 2 95 | ARG numfiles 1 96 | ARG readratio 0.5 97 | ARG actions 98 | ARG schedule 99 | ARG detail 7 100 | 101 | [(1, 'a', 0), (3, 0), (4, 0), (1, 'a', 1), (3, 1), (4, 1)] 102 | [(1, 'a', 0), (2, 0), (4, 0), (1, 'a', 1), (3, 1), (4, 1)] 103 | Server c0 c1 104 | file:a contains:0 105 | open:a [fd:0] 106 | getfile:a c:c0 [0] 107 | [a: 0 (v=1,d=0,r=1)] 108 | 109 | write:0 0 -> 1 110 | [a: 1 (v=1,d=1,r=1)] 111 | 112 | open:a [fd:0] 113 | getfile:a c:c1 [0] 114 | [a: 0 (v=1,d=0,r=1)] 115 | 116 | close:0 117 | putfile:a c:c0 [1] 118 | callback: c:c1 file:a 119 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 120 | invalidate a 121 | [a: 0 (v=0,d=0,r=1)] 122 | [a: 1 (v=1,d=0,r=0)] 123 | 124 | read:0 -> 0 125 | [a: 0 (v=0,d=0,r=1)] 126 | 127 | open:a [fd:1] 128 | [a: 1 (v=1,d=0,r=1)] 129 | 130 | close:0 131 | 132 | write:1 1 -> 2 133 | [a: 2 (v=1,d=1,r=1)] 134 | 135 | open:a [fd:1] 136 | getfile:a c:c1 [1] 137 | [a: 1 (v=1,d=0,r=1)] 138 | 139 | write:1 1 -> 3 140 | [a: 3 (v=1,d=1,r=1)] 141 | 142 | close:1 143 | putfile:a c:c1 [3] 144 | callback: c:c0 file:a 145 | invalidate file:a cache: {'a': {'valid': True, 'data': 2, 'dirty': True, 'refcnt': 1}} 146 | invalidate a 147 | [a: 2 (v=0,d=1,r=1)] 148 | [a: 3 (v=1,d=0,r=0)] 149 | 150 | close:1 151 | putfile:a c:c0 [2] 152 | callback: c:c1 file:a 153 | invalidate file:a cache: {'a': {'valid': True, 'data': 3, 'dirty': False, 'refcnt': 0}} 154 | invalidate a 155 | [a: 3 (v=0,d=0,r=0)] 156 | [a: 2 (v=1,d=0,r=0)] 157 | 158 | file:a contains:2 159 | ``` 160 | 161 | * **问题 4 答案** 162 | ``` 163 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -s 1 -c 164 | ARG seed 1 165 | ARG numclients 2 166 | ARG numsteps 2 167 | ARG numfiles 1 168 | ARG readratio 0.5 169 | ARG actions oa1:w1:c1,oa1:r1:c1 170 | ARG schedule 171 | ARG detail 0 172 | 173 | [(1, 'a', 1), (3, 1), (4, 1)] 174 | [(1, 'a', 1), (2, 1), (4, 1)] 175 | Server c0 c1 176 | file:a contains:0 177 | open:a [fd:1] 178 | open:a [fd:1] 179 | read:1 -> 0 180 | write:1 0 -> 1 181 | close:1 182 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 183 | close:1 184 | file:a contains:1 185 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -s 2 -c 186 | ARG seed 2 187 | ARG numclients 2 188 | ARG numsteps 2 189 | ARG numfiles 1 190 | ARG readratio 0.5 191 | ARG actions oa1:w1:c1,oa1:r1:c1 192 | ARG schedule 193 | ARG detail 0 194 | 195 | [(1, 'a', 1), (3, 1), (4, 1)] 196 | [(1, 'a', 1), (2, 1), (4, 1)] 197 | Server c0 c1 198 | file:a contains:0 199 | open:a [fd:1] 200 | read:1 -> 0 201 | open:a [fd:1] 202 | write:1 0 -> 1 203 | close:1 204 | close:1 205 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 0}} 206 | file:a contains:1 207 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -s 3 -c 208 | ARG seed 3 209 | ARG numclients 2 210 | ARG numsteps 2 211 | ARG numfiles 1 212 | ARG readratio 0.5 213 | ARG actions oa1:w1:c1,oa1:r1:c1 214 | ARG schedule 215 | ARG detail 0 216 | 217 | [(1, 'a', 1), (3, 1), (4, 1)] 218 | [(1, 'a', 1), (2, 1), (4, 1)] 219 | Server c0 c1 220 | file:a contains:0 221 | open:a [fd:1] 222 | open:a [fd:1] 223 | write:1 0 -> 1 224 | read:1 -> 0 225 | close:1 226 | close:1 227 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 0}} 228 | file:a contains:1 229 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -s 4 -c 230 | ARG seed 4 231 | ARG numclients 2 232 | ARG numsteps 2 233 | ARG numfiles 1 234 | ARG readratio 0.5 235 | ARG actions oa1:w1:c1,oa1:r1:c1 236 | ARG schedule 237 | ARG detail 0 238 | 239 | [(1, 'a', 1), (3, 1), (4, 1)] 240 | [(1, 'a', 1), (2, 1), (4, 1)] 241 | Server c0 c1 242 | file:a contains:0 243 | open:a [fd:1] 244 | write:1 0 -> 1 245 | close:1 246 | open:a [fd:1] 247 | read:1 -> 1 248 | close:1 249 | file:a contains:1 250 | ``` 251 | 只有客户端C0关闭后C1打开文件,才会导致读取到1。 252 | 253 | * **问题 5 答案** 254 | ``` 255 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -S 01 -c 256 | ARG seed 0 257 | ARG numclients 2 258 | ARG numsteps 2 259 | ARG numfiles 1 260 | ARG readratio 0.5 261 | ARG actions oa1:w1:c1,oa1:r1:c1 262 | ARG schedule 01 263 | ARG detail 0 264 | 265 | [(1, 'a', 1), (3, 1), (4, 1)] 266 | [(1, 'a', 1), (2, 1), (4, 1)] 267 | Server c0 c1 268 | file:a contains:0 269 | open:a [fd:1] 270 | open:a [fd:1] 271 | write:1 0 -> 1 272 | read:1 -> 0 273 | close:1 274 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 275 | close:1 276 | file:a contains:1 277 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -S 100011 -c 278 | ARG seed 0 279 | ARG numclients 2 280 | ARG numsteps 2 281 | ARG numfiles 1 282 | ARG readratio 0.5 283 | ARG actions oa1:w1:c1,oa1:r1:c1 284 | ARG schedule 100011 285 | ARG detail 0 286 | 287 | [(1, 'a', 1), (3, 1), (4, 1)] 288 | [(1, 'a', 1), (2, 1), (4, 1)] 289 | Server c0 c1 290 | file:a contains:0 291 | open:a [fd:1] 292 | open:a [fd:1] 293 | write:1 0 -> 1 294 | close:1 295 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 296 | read:1 -> 0 297 | close:1 298 | file:a contains:1 299 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:r1:c1 -S 011100 -c 300 | ARG seed 0 301 | ARG numclients 2 302 | ARG numsteps 2 303 | ARG numfiles 1 304 | ARG readratio 0.5 305 | ARG actions oa1:w1:c1,oa1:r1:c1 306 | ARG schedule 011100 307 | ARG detail 0 308 | 309 | [(1, 'a', 1), (3, 1), (4, 1)] 310 | [(1, 'a', 1), (2, 1), (4, 1)] 311 | Server c0 c1 312 | file:a contains:0 313 | open:a [fd:1] 314 | open:a [fd:1] 315 | read:1 -> 0 316 | close:1 317 | write:1 0 -> 1 318 | close:1 319 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 0}} 320 | file:a contains:1 321 | ``` 322 | 都读到0。 323 | 324 | * **问题 6 答案** 325 | ``` 326 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:w1:c1 -S 011100 -c 327 | ARG seed 0 328 | ARG numclients 2 329 | ARG numsteps 2 330 | ARG numfiles 1 331 | ARG readratio 0.5 332 | ARG actions oa1:w1:c1,oa1:w1:c1 333 | ARG schedule 011100 334 | ARG detail 0 335 | 336 | [(1, 'a', 1), (3, 1), (4, 1)] 337 | [(1, 'a', 1), (3, 1), (4, 1)] 338 | Server c0 c1 339 | file:a contains:0 340 | open:a [fd:1] 341 | open:a [fd:1] 342 | write:1 0 -> 1 343 | close:1 344 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 345 | write:1 0 -> 2 346 | close:1 347 | invalidate file:a cache: {'a': {'valid': True, 'data': 1, 'dirty': False, 'refcnt': 0}} 348 | file:a contains:2 349 | [testjz@localhost dist-afs]$ ./afs.py -C 2 -A oa1:w1:c1,oa1:w1:c1 -S 010011 -c 350 | ARG seed 0 351 | ARG numclients 2 352 | ARG numsteps 2 353 | ARG numfiles 1 354 | ARG readratio 0.5 355 | ARG actions oa1:w1:c1,oa1:w1:c1 356 | ARG schedule 010011 357 | ARG detail 0 358 | 359 | [(1, 'a', 1), (3, 1), (4, 1)] 360 | [(1, 'a', 1), (3, 1), (4, 1)] 361 | Server c0 c1 362 | file:a contains:0 363 | open:a [fd:1] 364 | open:a [fd:1] 365 | write:1 0 -> 1 366 | close:1 367 | invalidate file:a cache: {'a': {'valid': True, 'data': 0, 'dirty': False, 'refcnt': 1}} 368 | write:1 0 -> 2 369 | close:1 370 | invalidate file:a cache: {'a': {'valid': True, 'data': 1, 'dirty': False, 'refcnt': 0}} 371 | file:a contains:2 372 | ``` 373 | 会导致后关闭文件的客户端写入最终被保存到文件中。 374 | -------------------------------------------------------------------------------- /Chapter-5/5.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int x = 100; 8 | printf("x = %d, (pid:%d)\n", x, (int)getpid()); 9 | int rc = fork(); 10 | if (rc < 0) { 11 | fprintf(stderr, "fork failed"); 12 | exit(1); 13 | } else if (rc == 0) { 14 | printf("child x = %d (pid:%d)\n", x, (int)getpid()); 15 | x = 200; 16 | printf("child after changed x = %d (pid:%d)\n", x, (int)getpid()); 17 | } else { 18 | printf("parent x = %d (pid:%d)\n", x, (int)getpid()); 19 | x = 300; 20 | printf("parent after changed x = %d (pid:%d)\n", x, (int)getpid()); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Chapter-5/5.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int fd = open("./5.2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU); 11 | int rc = fork(); 12 | if (rc < 0) { 13 | close(fd); 14 | fprintf(stderr, "fork failed"); 15 | exit(1); 16 | } else if (rc == 0) { 17 | char * s = "child write something!\n"; 18 | write(fd, s, strlen(s)); 19 | } else { 20 | char * s = "parent write something\n"; 21 | write(fd, s, strlen(s)); 22 | wait(NULL); 23 | close(fd); 24 | } 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Chapter-5/5.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int rc = vfork(); 8 | if (rc < 0) { 9 | fprintf(stderr, "fork failed"); 10 | exit(1); 11 | } else if (rc == 0) { 12 | printf("hello\n"); 13 | exit(1); 14 | } else { 15 | printf("goodbye\n"); 16 | } 17 | return 0; 18 | } -------------------------------------------------------------------------------- /Chapter-5/5.4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int flag = 0; 6 | const int MAX = 6; 7 | int main() 8 | { 9 | char * s = "/bin/ls"; 10 | char * ss = "ls"; 11 | char * s2 = "/"; 12 | char * sv[] = { ss, s2, NULL }; 13 | for(flag = 0;flag < MAX; ++flag) { 14 | int rc = fork(); 15 | if (rc < 0) { 16 | fprintf(stderr, "fork failed"); 17 | exit(1); 18 | } else if (rc == 0) { 19 | switch(flag) { 20 | case 0: 21 | execl(s, ss, s2, NULL); 22 | break; 23 | case 1: 24 | execle(s, ss, s2, NULL); 25 | break; 26 | case 2: 27 | execlp(s, s, s2, NULL); 28 | break; 29 | case 3: 30 | execv(s, sv); 31 | break; 32 | case 4: 33 | execvp(ss, sv); 34 | break; 35 | case 5: 36 | execvpe(ss, sv); 37 | break; 38 | default: break; 39 | } 40 | } else { 41 | wait(NULL); 42 | } 43 | } 44 | return 0; 45 | } -------------------------------------------------------------------------------- /Chapter-5/5.5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int rc = fork(); 9 | int wc = wait(NULL); 10 | if(rc < 0) { 11 | fprintf(stderr, "fork failed"); 12 | exit(1); 13 | } else if (rc == 0) { 14 | printf("child"); 15 | } else { 16 | printf("parent"); 17 | } 18 | printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /Chapter-5/5.6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int rc = fork(); 9 | int wc = waitpid(rc, NULL, 0); 10 | if(rc < 0) { 11 | fprintf(stderr, "fork failed"); 12 | exit(1); 13 | } else if (rc == 0) { 14 | printf("child"); 15 | } else { 16 | printf("parent"); 17 | } 18 | printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /Chapter-5/5.7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | int rc = fork(); 8 | if (rc < 0) { 9 | fprintf(stderr, "fork failed"); 10 | exit(1); 11 | } else if (rc == 0) { 12 | close(STDOUT_FILENO); 13 | printf("output child\n"); 14 | } 15 | wait(NULL); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Chapter-5/5.8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | int pi[2]; 7 | int p = pipe(pi); 8 | if(p < 0) { 9 | fprintf(stderr, "pipe failed"); 10 | exit(1); 11 | } 12 | int i = 0; 13 | int rc[2]; 14 | char buf[256]; 15 | for(i=0;i<2;++i) { 16 | rc[i] = fork(); 17 | if (rc[i] < 0) { 18 | fprintf(stderr, "fork failed"); 19 | exit(1); 20 | } else if (rc[i] == 0) { 21 | switch(i) { 22 | case 0: 23 | dup2(pi[1], STDOUT_FILENO); 24 | puts("child input"); 25 | break; 26 | case 1: 27 | dup2(pi[0], STDIN_FILENO); 28 | gets(buf); 29 | printf("child0 out (%s) in the child1\n", buf); 30 | return 2; 31 | } 32 | break; 33 | } 34 | } 35 | waitpid(rc[0], NULL, 0); 36 | waitpid(rc[1], NULL, 0); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /Chapter-5/Chapter-5-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | [答案代码](5.1.c) 3 | ```C 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int x = 100; 11 | printf("x = %d, (pid:%d)\n", x, (int)getpid()); 12 | int rc = fork(); 13 | if (rc < 0) { 14 | fprintf(stderr, "fork failed"); 15 | exit(1); 16 | } else if (rc == 0) { 17 | printf("child x = %d (pid:%d)\n", x, (int)getpid()); 18 | x = 200; 19 | printf("child after changed x = %d (pid:%d)\n", x, (int)getpid()); 20 | } else { 21 | printf("parent x = %d (pid:%d)\n", x, (int)getpid()); 22 | x = 300; 23 | printf("parent after changed x = %d (pid:%d)\n", x, (int)getpid()); 24 | } 25 | return 0; 26 | } 27 | ``` 28 | 执行结果 29 | ``` 30 | [testjz@localhost OS_test]$ ./5.1 31 | x = 100, (pid:6368) 32 | parent x = 100 (pid:6368) 33 | parent after changed x = 300 (pid:6368) 34 | child x = 100 (pid:6369) 35 | child after changed x = 200 (pid:6369) 36 | ``` 37 | 子进程的变量子一开始与父进程相同。但是实际上父子进程中的同名变量已经不在同一内存区域,实际上是两个变量,因此父子进程的变量值改变不会影响另外一个进程。 38 | 39 | * **问题 2 答案** 40 | [答案代码](5.2.c) 41 | ```C 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | int main() 50 | { 51 | int fd = open("./5.2.txt", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU); 52 | int rc = fork(); 53 | if (rc < 0) { 54 | close(fd); 55 | fprintf(stderr, "fork failed"); 56 | exit(1); 57 | } else if (rc == 0) { 58 | char * s = "child write something!\n"; 59 | write(fd, s, strlen(s)); 60 | } else { 61 | char * s = "parent write something\n"; 62 | write(fd, s, strlen(s)); 63 | wait(NULL); 64 | close(fd); 65 | } 66 | return 0; 67 | } 68 | ``` 69 | 执行结果 70 | ``` 71 | [testjz@localhost OS_test]$ ./5.2 72 | [testjz@localhost OS_test]$ cat 5.2.txt 73 | parent write something 74 | child write something! 75 | ``` 76 | 看起来都可以访问文件描述符并正常写入文件。 77 | 78 | * **问题 3 答案** 79 | [答案代码](5.3.c) 80 | ```C 81 | #include 82 | #include 83 | #include 84 | 85 | int main() 86 | { 87 | int rc = vfork(); 88 | if (rc < 0) { 89 | fprintf(stderr, "fork failed"); 90 | exit(1); 91 | } else if (rc == 0) { 92 | printf("hello\n"); 93 | exit(1); 94 | } else { 95 | printf("goodbye\n"); 96 | } 97 | return 0; 98 | } 99 | ``` 100 | 使用vfork,可以在子进程执行结束后再执行父进程。 101 | 102 | * **问题 4 答案** 103 | [答案代码](5.4.c) 104 | ```C 105 | #include 106 | #include 107 | #include 108 | 109 | int flag = 0; 110 | const int MAX = 6; 111 | int main() 112 | { 113 | char * s = "/bin/ls"; 114 | char * ss = "ls"; 115 | char * s2 = "/"; 116 | char * sv[] = { ss, s2, NULL }; 117 | for(flag = 0;flag < MAX; ++flag) { 118 | int rc = fork(); 119 | if (rc < 0) { 120 | fprintf(stderr, "fork failed"); 121 | exit(1); 122 | } else if (rc == 0) { 123 | switch(flag) { 124 | case 0: 125 | execl(s, ss, s2, NULL); 126 | break; 127 | case 1: 128 | execle(s, ss, s2, NULL); 129 | break; 130 | case 2: 131 | execlp(s, s, s2, NULL); 132 | break; 133 | case 3: 134 | execv(s, sv); 135 | break; 136 | case 4: 137 | execvp(ss, sv); 138 | break; 139 | case 5: 140 | execvpe(ss, sv); 141 | break; 142 | default: break; 143 | } 144 | } else { 145 | wait(NULL); 146 | } 147 | } 148 | return 0; 149 | } 150 | ``` 151 | 执行结果 152 | ``` 153 | [testjz@localhost OS_test]$ ./5.4 154 | bin dev home lib64 mnt proc run srv tmp var 155 | boot etc lib media opt root sbin sys usr 156 | bin dev home lib64 mnt proc run srv tmp var 157 | boot etc lib media opt root sbin sys usr 158 | bin dev home lib64 mnt proc run srv tmp var 159 | boot etc lib media opt root sbin sys usr 160 | bin dev home lib64 mnt proc run srv tmp var 161 | boot etc lib media opt root sbin sys usr 162 | bin dev home lib64 mnt proc run srv tmp var 163 | boot etc lib media opt root sbin sys usr 164 | bin dev home lib64 mnt proc run srv tmp var 165 | boot etc lib media opt root sbin sys usr 166 | ``` 167 | 有多种变体是为了要适应不同的调用形式和环境要求。 168 | 169 | * **问题 5 答案** 170 | [答案代码](5.5.c) 171 | ```C 172 | #include 173 | #include 174 | #include 175 | #include 176 | 177 | int main() 178 | { 179 | int rc = fork(); 180 | int wc = wait(NULL); 181 | if(rc < 0) { 182 | fprintf(stderr, "fork failed"); 183 | exit(1); 184 | } else if (rc == 0) { 185 | printf("child"); 186 | } else { 187 | printf("parent"); 188 | } 189 | printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc); 190 | return 0; 191 | } 192 | ``` 193 | 执行结果 194 | ``` 195 | [testjz@localhost OS_test]$ ./5.5 196 | childpid:14495 wc:-1 rc:0 197 | parentpid:14494 wc:14495 rc:14495 198 | ``` 199 | 父进程使用wait()返回子进程id,子进程由于本身没有子进程,所以返回-1。 200 | 201 | * **问题 6 答案** 202 | [答案代码](5.6.c) 203 | ```C 204 | #include 205 | #include 206 | #include 207 | #include 208 | 209 | int main() 210 | { 211 | int rc = fork(); 212 | int wc = waitpid(rc, NULL, 0); 213 | if(rc < 0) { 214 | fprintf(stderr, "fork failed"); 215 | exit(1); 216 | } else if (rc == 0) { 217 | printf("child"); 218 | } else { 219 | printf("parent"); 220 | } 221 | printf("pid:%d wc:%d rc:%d\n", (int)getpid(), wc, rc); 222 | return 0; 223 | } 224 | ``` 225 | 执行结果 226 | ``` 227 | [testjz@localhost OS_test]$ ./5.6 228 | childpid:14607 wc:-1 rc:0 229 | parentpid:14606 wc:14607 rc:14607 230 | ``` 231 | waitpid在进程本身有子进程的时候有用。 232 | 233 | * **问题 7 答案** 234 | [答案代码](5.7.c) 235 | ```C 236 | #include 237 | #include 238 | #include 239 | 240 | int main() 241 | { 242 | int rc = fork(); 243 | if (rc < 0) { 244 | fprintf(stderr, "fork failed"); 245 | exit(1); 246 | } else if (rc == 0) { 247 | close(STDOUT_FILENO); 248 | printf("output child\n"); 249 | } 250 | wait(NULL); 251 | return 0; 252 | } 253 | ``` 254 | 执行结果 255 | ``` 256 | [testjz@localhost OS_test]$ ./5.7 257 | [testjz@localhost OS_test]$ 258 | ``` 259 | 无任何输出。 260 | 261 | * **问题 8 答案** 262 | [答案代码](5.8.c) 263 | ```C 264 | #include 265 | #include 266 | #include 267 | 268 | int main() { 269 | int pi[2]; 270 | int p = pipe(pi); 271 | if(p < 0) { 272 | fprintf(stderr, "pipe failed"); 273 | exit(1); 274 | } 275 | int i = 0; 276 | int rc[2]; 277 | char buf[256]; 278 | for(i=0;i<2;++i) { 279 | rc[i] = fork(); 280 | if (rc[i] < 0) { 281 | fprintf(stderr, "fork failed"); 282 | exit(1); 283 | } else if (rc[i] == 0) { 284 | switch(i) { 285 | case 0: 286 | dup2(pi[1], STDOUT_FILENO); 287 | puts("child input"); 288 | break; 289 | case 1: 290 | dup2(pi[0], STDIN_FILENO); 291 | gets(buf); 292 | printf("child0 out (%s) in the child1\n", buf); 293 | return 2; 294 | } 295 | break; 296 | } 297 | } 298 | waitpid(rc[0], NULL, 0); 299 | waitpid(rc[1], NULL, 0); 300 | return 0; 301 | } 302 | ``` 303 | 执行结果 304 | ``` 305 | [testjz@localhost OS_test]$ ./5.8 306 | child0 out (child input) in the child1 307 | ``` 308 | -------------------------------------------------------------------------------- /Chapter-6/6.1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | struct timeval start,end; 7 | int i; 8 | for(i=0;i<10;++i) { 9 | gettimeofday(&start, NULL); 10 | gettimeofday(&end, NULL); 11 | printf("%ld\n", end.tv_usec - start.tv_usec); 12 | printf("%ld %ld\n", end.tv_usec, start.tv_usec); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Chapter-6/6.2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() 8 | { 9 | int fd = open("./6.2.c", O_RDONLY); 10 | int i; 11 | char buf[10]; 12 | struct timeval start, end; 13 | if(fd == -1) { 14 | fprintf(stderr, "file open failed!\n"); 15 | exit(1); 16 | } 17 | for(i=0;i<10;++i) { 18 | gettimeofday(&start, NULL); 19 | read(fd, buf, 0); 20 | gettimeofday(&end, NULL); 21 | printf("%d\n", end.tv_usec - start.tv_usec); 22 | } 23 | close(fd); 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter-6/6.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int pi1[2]; 9 | int pi2[2]; 10 | char buf1[30], buf2[30]; 11 | int p1 = pipe(pi1); 12 | int p2 = pipe(pi2); 13 | long temptime; 14 | struct timeval start, end; 15 | int i; 16 | if (p1 < 0 || p2 < 0) 17 | { 18 | fprintf(stderr, "pipe failed"); 19 | exit(1); 20 | } 21 | int rc = fork(); 22 | for (i = 0; i < 10; ++i) 23 | { 24 | if (rc < 0) 25 | { 26 | fprintf(stderr, "fork failed"); 27 | exit(1); 28 | } 29 | else if (rc == 0) 30 | { 31 | read(pi1[0], buf1, 25); 32 | gettimeofday(&end, NULL); 33 | printf("%d\n", end.tv_usec - atol(buf1)); 34 | gettimeofday(&start, NULL); 35 | sprintf(buf2, "%ld", start.tv_usec); 36 | write(pi2[1], buf2, 25); 37 | } 38 | else 39 | { 40 | gettimeofday(&start, NULL); 41 | sprintf(buf1, "%ld", start.tv_usec); 42 | write(pi1[1], buf1, 25); 43 | read(pi2[0], buf2, 25); 44 | gettimeofday(&end, NULL); 45 | printf("%d\n", end.tv_usec - atol(buf2)); 46 | } 47 | } 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Chapter-6/Chapter-6-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | 在虚拟机中可以设置CPU的个数,直接设置为一个内核就能避免多内核CPU测量不准的情况。 2 | 3 | * **测量gettimeofdays()连续调用** 4 | [答案代码 6.1.c](6.1.c) 5 | ```C 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | struct timeval start,end; 12 | int i; 13 | for(i=0;i<10;++i) { 14 | gettimeofday(&start, NULL); 15 | gettimeofday(&end, NULL); 16 | printf("%ld\n", end.tv_usec - start.tv_usec); 17 | printf("%ld %ld\n", end.tv_usec, start.tv_usec); 18 | } 19 | return 0; 20 | } 21 | ``` 22 | 执行结果 23 | ``` 24 | [testjz@localhost OS_test]$ ./6.1 25 | 0 26 | 499384 499384 27 | 1 28 | 499443 499442 29 | 0 30 | 499448 499448 31 | 0 32 | 499452 499452 33 | 0 34 | 499457 499457 35 | 0 36 | 499462 499462 37 | 0 38 | 499467 499467 39 | 0 40 | 499471 499471 41 | 0 42 | 499476 499476 43 | 0 44 | 499480 499480 45 | ``` 46 | 感觉在连续调用的情况下,精度还是挺高的。可以使用这个函数测试。 47 | 48 | * **测量系统调用的成本** 49 | [答案代码 6.2.c](6.2.c) 50 | ```C 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | int main() 58 | { 59 | int fd = open("./6.2.c", O_RDONLY); 60 | int i; 61 | char buf[10]; 62 | struct timeval start, end; 63 | if(fd == -1) { 64 | fprintf(stderr, "file open failed!\n"); 65 | exit(1); 66 | } 67 | for(i=0;i<10;++i) { 68 | gettimeofday(&start, NULL); 69 | read(fd, buf, 0); 70 | gettimeofday(&end, NULL); 71 | printf("%d\n", end.tv_usec - start.tv_usec); 72 | } 73 | close(fd); 74 | return 0; 75 | } 76 | ``` 77 | 执行结果 78 | ``` 79 | [testjz@localhost OS_test]$ ./6.2 80 | 1 81 | 1 82 | 1 83 | 0 84 | 0 85 | 1 86 | 0 87 | 1 88 | 0 89 | 1 90 | ``` 91 | 看来是系统的调用的耗时太少了。平均不到一微秒。 92 | 93 | * **测量上下文切换的成本** 94 | [答案代码 6.3.c](6.3.c) 95 | ```C 96 | #include 97 | #include 98 | #include 99 | #include 100 | 101 | int main() 102 | { 103 | int pi1[2]; 104 | int pi2[2]; 105 | char buf1[30], buf2[30]; 106 | int p1 = pipe(pi1); 107 | int p2 = pipe(pi2); 108 | long temptime; 109 | struct timeval start, end; 110 | int i; 111 | if (p1 < 0 || p2 < 0) 112 | { 113 | fprintf(stderr, "pipe failed"); 114 | exit(1); 115 | } 116 | int rc = fork(); 117 | for (i = 0; i < 10; ++i) 118 | { 119 | if (rc < 0) 120 | { 121 | fprintf(stderr, "fork failed"); 122 | exit(1); 123 | } 124 | else if (rc == 0) 125 | { 126 | read(pi1[0], buf1, 25); 127 | gettimeofday(&end, NULL); 128 | printf("%d\n", end.tv_usec - atol(buf1)); 129 | gettimeofday(&start, NULL); 130 | sprintf(buf2, "%ld", start.tv_usec); 131 | write(pi2[1], buf2, 25); 132 | } 133 | else 134 | { 135 | gettimeofday(&start, NULL); 136 | sprintf(buf1, "%ld", start.tv_usec); 137 | write(pi1[1], buf1, 25); 138 | read(pi2[0], buf2, 25); 139 | gettimeofday(&end, NULL); 140 | printf("%d\n", end.tv_usec - atol(buf2)); 141 | } 142 | } 143 | return 0; 144 | } 145 | ``` 146 | 执行结果 147 | ``` 148 | [testjz@localhost OS_test]$ ./6.3 149 | 408 150 | 5 151 | 5 152 | 5 153 | 5 154 | 4 155 | 36 156 | 8 157 | 4 158 | 4 159 | 14 160 | 5 161 | 5 162 | 5 163 | 4 164 | 4 165 | 13 166 | 4 167 | 4 168 | 165 169 | ``` 170 | 代码中除了上下文切换,还有系统调用,还有字符串转换数字等成本。另外我在tty2运行这个程序,tty1还开着图形界面,还有一些系统进程切换的成本,所以这个数字在浮动。我们按切换少的时间计算,时间大概在4-5微秒。 171 | -------------------------------------------------------------------------------- /Chapter-7/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jzplp/OSTEP-Answers/7533b9ff75fd221a79d4137c4834cf75701f974f/Chapter-7/1.gif -------------------------------------------------------------------------------- /Chapter-7/Chapter-7-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost cpu-sched]$ ./scheduler.py -p FIFO -l 200,200,200 -c 4 | ARG policy FIFO 5 | ARG jlist 200,200,200 6 | 7 | Here is the job list, with the run time of each job: 8 | Job 0 ( length = 200.0 ) 9 | Job 1 ( length = 200.0 ) 10 | Job 2 ( length = 200.0 ) 11 | 12 | 13 | ** Solutions ** 14 | 15 | Execution trace: 16 | [ time 0 ] Run job 0 for 200.00 secs ( DONE at 200.00 ) 17 | [ time 200 ] Run job 1 for 200.00 secs ( DONE at 400.00 ) 18 | [ time 400 ] Run job 2 for 200.00 secs ( DONE at 600.00 ) 19 | 20 | Final statistics: 21 | Job 0 -- Response: 0.00 Turnaround 200.00 Wait 0.00 22 | Job 1 -- Response: 200.00 Turnaround 400.00 Wait 200.00 23 | Job 2 -- Response: 400.00 Turnaround 600.00 Wait 400.00 24 | 25 | Average -- Response: 200.00 Turnaround 400.00 Wait 200.00 26 | 27 | [testjz@localhost cpu-sched]$ ./scheduler.py -p SJF -l 200,200,200 -c 28 | ARG policy SJF 29 | ARG jlist 200,200,200 30 | 31 | Here is the job list, with the run time of each job: 32 | Job 0 ( length = 200.0 ) 33 | Job 1 ( length = 200.0 ) 34 | Job 2 ( length = 200.0 ) 35 | 36 | 37 | ** Solutions ** 38 | 39 | Execution trace: 40 | [ time 0 ] Run job 0 for 200.00 secs ( DONE at 200.00 ) 41 | [ time 200 ] Run job 1 for 200.00 secs ( DONE at 400.00 ) 42 | [ time 400 ] Run job 2 for 200.00 secs ( DONE at 600.00 ) 43 | 44 | Final statistics: 45 | Job 0 -- Response: 0.00 Turnaround 200.00 Wait 0.00 46 | Job 1 -- Response: 200.00 Turnaround 400.00 Wait 200.00 47 | Job 2 -- Response: 400.00 Turnaround 600.00 Wait 400.00 48 | 49 | Average -- Response: 200.00 Turnaround 400.00 Wait 200.00 50 | ``` 51 | 52 | * **问题 2 答案** 53 | ``` 54 | [testjz@localhost cpu-sched]$ ./scheduler.py -p FIFO -l 100,200,300 -c 55 | ARG policy FIFO 56 | ARG jlist 100,200,300 57 | 58 | Here is the job list, with the run time of each job: 59 | Job 0 ( length = 100.0 ) 60 | Job 1 ( length = 200.0 ) 61 | Job 2 ( length = 300.0 ) 62 | 63 | 64 | ** Solutions ** 65 | 66 | Execution trace: 67 | [ time 0 ] Run job 0 for 100.00 secs ( DONE at 100.00 ) 68 | [ time 100 ] Run job 1 for 200.00 secs ( DONE at 300.00 ) 69 | [ time 300 ] Run job 2 for 300.00 secs ( DONE at 600.00 ) 70 | 71 | Final statistics: 72 | Job 0 -- Response: 0.00 Turnaround 100.00 Wait 0.00 73 | Job 1 -- Response: 100.00 Turnaround 300.00 Wait 100.00 74 | Job 2 -- Response: 300.00 Turnaround 600.00 Wait 300.00 75 | 76 | Average -- Response: 133.33 Turnaround 333.33 Wait 133.33 77 | 78 | [testjz@localhost cpu-sched]$ ./scheduler.py -p SJF -l 100,200,300 -c 79 | ARG policy SJF 80 | ARG jlist 100,200,300 81 | 82 | Here is the job list, with the run time of each job: 83 | Job 0 ( length = 100.0 ) 84 | Job 1 ( length = 200.0 ) 85 | Job 2 ( length = 300.0 ) 86 | 87 | 88 | ** Solutions ** 89 | 90 | Execution trace: 91 | [ time 0 ] Run job 0 for 100.00 secs ( DONE at 100.00 ) 92 | [ time 100 ] Run job 1 for 200.00 secs ( DONE at 300.00 ) 93 | [ time 300 ] Run job 2 for 300.00 secs ( DONE at 600.00 ) 94 | 95 | Final statistics: 96 | Job 0 -- Response: 0.00 Turnaround 100.00 Wait 0.00 97 | Job 1 -- Response: 100.00 Turnaround 300.00 Wait 100.00 98 | Job 2 -- Response: 300.00 Turnaround 600.00 Wait 300.00 99 | 100 | Average -- Response: 133.33 Turnaround 333.33 Wait 133.33 101 | ``` 102 | 103 | * **问题 3 答案** 104 | ``` 105 | [testjz@localhost cpu-sched]$ ./scheduler.py -p RR -q 1 -l 100,200,300 -c 106 | ARG policy RR 107 | ARG jlist 100,200,300 108 | 109 | Here is the job list, with the run time of each job: 110 | Job 0 ( length = 100.0 ) 111 | Job 1 ( length = 200.0 ) 112 | Job 2 ( length = 300.0 ) 113 | 114 | 115 | ** Solutions ** 116 | 117 | Execution trace: 118 | [ time 0 ] Run job 0 for 1.00 secs 119 | [ time 1 ] Run job 1 for 1.00 secs 120 | [ time 2 ] Run job 2 for 1.00 secs 121 | [ time 3 ] Run job 0 for 1.00 secs 122 | [ time 4 ] Run job 1 for 1.00 secs 123 | [ time 5 ] Run job 2 for 1.00 secs 124 | [ time 6 ] Run job 0 for 1.00 secs 125 | [ time 7 ] Run job 1 for 1.00 secs 126 | [ time 8 ] Run job 2 for 1.00 secs 127 | [ time 9 ] Run job 0 for 1.00 secs 128 | [ time 10 ] Run job 1 for 1.00 secs 129 | [ time 11 ] Run job 2 for 1.00 secs 130 | [ time 12 ] Run job 0 for 1.00 secs 131 | [ time 13 ] Run job 1 for 1.00 secs 132 | [ time 14 ] Run job 2 for 1.00 secs 133 | [ time 15 ] Run job 0 for 1.00 secs 134 | [ time 16 ] Run job 1 for 1.00 secs 135 | [ time 17 ] Run job 2 for 1.00 secs 136 | [ time 18 ] Run job 0 for 1.00 secs 137 | [ time 19 ] Run job 1 for 1.00 secs 138 | [ time 20 ] Run job 2 for 1.00 secs 139 | [ time 21 ] Run job 0 for 1.00 secs 140 | [ time 22 ] Run job 1 for 1.00 secs 141 | [ time 23 ] Run job 2 for 1.00 secs 142 | [ time 24 ] Run job 0 for 1.00 secs 143 | [ time 25 ] Run job 1 for 1.00 secs 144 | [ time 26 ] Run job 2 for 1.00 secs 145 | [ time 27 ] Run job 0 for 1.00 secs 146 | [ time 28 ] Run job 1 for 1.00 secs 147 | [ time 29 ] Run job 2 for 1.00 secs 148 | [ time 30 ] Run job 0 for 1.00 secs 149 | [ time 31 ] Run job 1 for 1.00 secs 150 | [ time 32 ] Run job 2 for 1.00 secs 151 | [ time 33 ] Run job 0 for 1.00 secs 152 | [ time 34 ] Run job 1 for 1.00 secs 153 | [ time 35 ] Run job 2 for 1.00 secs 154 | [ time 36 ] Run job 0 for 1.00 secs 155 | [ time 37 ] Run job 1 for 1.00 secs 156 | [ time 38 ] Run job 2 for 1.00 secs 157 | [ time 39 ] Run job 0 for 1.00 secs 158 | [ time 40 ] Run job 1 for 1.00 secs 159 | [ time 41 ] Run job 2 for 1.00 secs 160 | [ time 42 ] Run job 0 for 1.00 secs 161 | [ time 43 ] Run job 1 for 1.00 secs 162 | [ time 44 ] Run job 2 for 1.00 secs 163 | [ time 45 ] Run job 0 for 1.00 secs 164 | [ time 46 ] Run job 1 for 1.00 secs 165 | [ time 47 ] Run job 2 for 1.00 secs 166 | [ time 48 ] Run job 0 for 1.00 secs 167 | [ time 49 ] Run job 1 for 1.00 secs 168 | [ time 50 ] Run job 2 for 1.00 secs 169 | [ time 51 ] Run job 0 for 1.00 secs 170 | [ time 52 ] Run job 1 for 1.00 secs 171 | [ time 53 ] Run job 2 for 1.00 secs 172 | [ time 54 ] Run job 0 for 1.00 secs 173 | [ time 55 ] Run job 1 for 1.00 secs 174 | [ time 56 ] Run job 2 for 1.00 secs 175 | [ time 57 ] Run job 0 for 1.00 secs 176 | [ time 58 ] Run job 1 for 1.00 secs 177 | [ time 59 ] Run job 2 for 1.00 secs 178 | [ time 60 ] Run job 0 for 1.00 secs 179 | [ time 61 ] Run job 1 for 1.00 secs 180 | [ time 62 ] Run job 2 for 1.00 secs 181 | [ time 63 ] Run job 0 for 1.00 secs 182 | [ time 64 ] Run job 1 for 1.00 secs 183 | [ time 65 ] Run job 2 for 1.00 secs 184 | [ time 66 ] Run job 0 for 1.00 secs 185 | [ time 67 ] Run job 1 for 1.00 secs 186 | [ time 68 ] Run job 2 for 1.00 secs 187 | [ time 69 ] Run job 0 for 1.00 secs 188 | [ time 70 ] Run job 1 for 1.00 secs 189 | [ time 71 ] Run job 2 for 1.00 secs 190 | [ time 72 ] Run job 0 for 1.00 secs 191 | [ time 73 ] Run job 1 for 1.00 secs 192 | [ time 74 ] Run job 2 for 1.00 secs 193 | [ time 75 ] Run job 0 for 1.00 secs 194 | [ time 76 ] Run job 1 for 1.00 secs 195 | [ time 77 ] Run job 2 for 1.00 secs 196 | [ time 78 ] Run job 0 for 1.00 secs 197 | [ time 79 ] Run job 1 for 1.00 secs 198 | [ time 80 ] Run job 2 for 1.00 secs 199 | [ time 81 ] Run job 0 for 1.00 secs 200 | [ time 82 ] Run job 1 for 1.00 secs 201 | [ time 83 ] Run job 2 for 1.00 secs 202 | [ time 84 ] Run job 0 for 1.00 secs 203 | [ time 85 ] Run job 1 for 1.00 secs 204 | [ time 86 ] Run job 2 for 1.00 secs 205 | [ time 87 ] Run job 0 for 1.00 secs 206 | [ time 88 ] Run job 1 for 1.00 secs 207 | [ time 89 ] Run job 2 for 1.00 secs 208 | [ time 90 ] Run job 0 for 1.00 secs 209 | [ time 91 ] Run job 1 for 1.00 secs 210 | [ time 92 ] Run job 2 for 1.00 secs 211 | [ time 93 ] Run job 0 for 1.00 secs 212 | [ time 94 ] Run job 1 for 1.00 secs 213 | [ time 95 ] Run job 2 for 1.00 secs 214 | [ time 96 ] Run job 0 for 1.00 secs 215 | [ time 97 ] Run job 1 for 1.00 secs 216 | [ time 98 ] Run job 2 for 1.00 secs 217 | [ time 99 ] Run job 0 for 1.00 secs 218 | [ time 100 ] Run job 1 for 1.00 secs 219 | [ time 101 ] Run job 2 for 1.00 secs 220 | [ time 102 ] Run job 0 for 1.00 secs 221 | [ time 103 ] Run job 1 for 1.00 secs 222 | [ time 104 ] Run job 2 for 1.00 secs 223 | [ time 105 ] Run job 0 for 1.00 secs 224 | [ time 106 ] Run job 1 for 1.00 secs 225 | [ time 107 ] Run job 2 for 1.00 secs 226 | [ time 108 ] Run job 0 for 1.00 secs 227 | [ time 109 ] Run job 1 for 1.00 secs 228 | [ time 110 ] Run job 2 for 1.00 secs 229 | [ time 111 ] Run job 0 for 1.00 secs 230 | [ time 112 ] Run job 1 for 1.00 secs 231 | [ time 113 ] Run job 2 for 1.00 secs 232 | [ time 114 ] Run job 0 for 1.00 secs 233 | [ time 115 ] Run job 1 for 1.00 secs 234 | [ time 116 ] Run job 2 for 1.00 secs 235 | [ time 117 ] Run job 0 for 1.00 secs 236 | [ time 118 ] Run job 1 for 1.00 secs 237 | [ time 119 ] Run job 2 for 1.00 secs 238 | [ time 120 ] Run job 0 for 1.00 secs 239 | [ time 121 ] Run job 1 for 1.00 secs 240 | [ time 122 ] Run job 2 for 1.00 secs 241 | [ time 123 ] Run job 0 for 1.00 secs 242 | [ time 124 ] Run job 1 for 1.00 secs 243 | [ time 125 ] Run job 2 for 1.00 secs 244 | [ time 126 ] Run job 0 for 1.00 secs 245 | [ time 127 ] Run job 1 for 1.00 secs 246 | [ time 128 ] Run job 2 for 1.00 secs 247 | [ time 129 ] Run job 0 for 1.00 secs 248 | [ time 130 ] Run job 1 for 1.00 secs 249 | [ time 131 ] Run job 2 for 1.00 secs 250 | [ time 132 ] Run job 0 for 1.00 secs 251 | [ time 133 ] Run job 1 for 1.00 secs 252 | [ time 134 ] Run job 2 for 1.00 secs 253 | [ time 135 ] Run job 0 for 1.00 secs 254 | [ time 136 ] Run job 1 for 1.00 secs 255 | [ time 137 ] Run job 2 for 1.00 secs 256 | [ time 138 ] Run job 0 for 1.00 secs 257 | [ time 139 ] Run job 1 for 1.00 secs 258 | [ time 140 ] Run job 2 for 1.00 secs 259 | [ time 141 ] Run job 0 for 1.00 secs 260 | [ time 142 ] Run job 1 for 1.00 secs 261 | [ time 143 ] Run job 2 for 1.00 secs 262 | [ time 144 ] Run job 0 for 1.00 secs 263 | [ time 145 ] Run job 1 for 1.00 secs 264 | [ time 146 ] Run job 2 for 1.00 secs 265 | [ time 147 ] Run job 0 for 1.00 secs 266 | [ time 148 ] Run job 1 for 1.00 secs 267 | [ time 149 ] Run job 2 for 1.00 secs 268 | [ time 150 ] Run job 0 for 1.00 secs 269 | [ time 151 ] Run job 1 for 1.00 secs 270 | [ time 152 ] Run job 2 for 1.00 secs 271 | [ time 153 ] Run job 0 for 1.00 secs 272 | [ time 154 ] Run job 1 for 1.00 secs 273 | [ time 155 ] Run job 2 for 1.00 secs 274 | [ time 156 ] Run job 0 for 1.00 secs 275 | [ time 157 ] Run job 1 for 1.00 secs 276 | [ time 158 ] Run job 2 for 1.00 secs 277 | [ time 159 ] Run job 0 for 1.00 secs 278 | [ time 160 ] Run job 1 for 1.00 secs 279 | [ time 161 ] Run job 2 for 1.00 secs 280 | [ time 162 ] Run job 0 for 1.00 secs 281 | [ time 163 ] Run job 1 for 1.00 secs 282 | [ time 164 ] Run job 2 for 1.00 secs 283 | [ time 165 ] Run job 0 for 1.00 secs 284 | [ time 166 ] Run job 1 for 1.00 secs 285 | [ time 167 ] Run job 2 for 1.00 secs 286 | [ time 168 ] Run job 0 for 1.00 secs 287 | [ time 169 ] Run job 1 for 1.00 secs 288 | [ time 170 ] Run job 2 for 1.00 secs 289 | [ time 171 ] Run job 0 for 1.00 secs 290 | [ time 172 ] Run job 1 for 1.00 secs 291 | [ time 173 ] Run job 2 for 1.00 secs 292 | [ time 174 ] Run job 0 for 1.00 secs 293 | [ time 175 ] Run job 1 for 1.00 secs 294 | [ time 176 ] Run job 2 for 1.00 secs 295 | [ time 177 ] Run job 0 for 1.00 secs 296 | [ time 178 ] Run job 1 for 1.00 secs 297 | [ time 179 ] Run job 2 for 1.00 secs 298 | [ time 180 ] Run job 0 for 1.00 secs 299 | [ time 181 ] Run job 1 for 1.00 secs 300 | [ time 182 ] Run job 2 for 1.00 secs 301 | [ time 183 ] Run job 0 for 1.00 secs 302 | [ time 184 ] Run job 1 for 1.00 secs 303 | [ time 185 ] Run job 2 for 1.00 secs 304 | [ time 186 ] Run job 0 for 1.00 secs 305 | [ time 187 ] Run job 1 for 1.00 secs 306 | [ time 188 ] Run job 2 for 1.00 secs 307 | [ time 189 ] Run job 0 for 1.00 secs 308 | [ time 190 ] Run job 1 for 1.00 secs 309 | [ time 191 ] Run job 2 for 1.00 secs 310 | [ time 192 ] Run job 0 for 1.00 secs 311 | [ time 193 ] Run job 1 for 1.00 secs 312 | [ time 194 ] Run job 2 for 1.00 secs 313 | [ time 195 ] Run job 0 for 1.00 secs 314 | [ time 196 ] Run job 1 for 1.00 secs 315 | [ time 197 ] Run job 2 for 1.00 secs 316 | [ time 198 ] Run job 0 for 1.00 secs 317 | [ time 199 ] Run job 1 for 1.00 secs 318 | [ time 200 ] Run job 2 for 1.00 secs 319 | [ time 201 ] Run job 0 for 1.00 secs 320 | [ time 202 ] Run job 1 for 1.00 secs 321 | [ time 203 ] Run job 2 for 1.00 secs 322 | [ time 204 ] Run job 0 for 1.00 secs 323 | [ time 205 ] Run job 1 for 1.00 secs 324 | [ time 206 ] Run job 2 for 1.00 secs 325 | [ time 207 ] Run job 0 for 1.00 secs 326 | [ time 208 ] Run job 1 for 1.00 secs 327 | [ time 209 ] Run job 2 for 1.00 secs 328 | [ time 210 ] Run job 0 for 1.00 secs 329 | [ time 211 ] Run job 1 for 1.00 secs 330 | [ time 212 ] Run job 2 for 1.00 secs 331 | [ time 213 ] Run job 0 for 1.00 secs 332 | [ time 214 ] Run job 1 for 1.00 secs 333 | [ time 215 ] Run job 2 for 1.00 secs 334 | [ time 216 ] Run job 0 for 1.00 secs 335 | [ time 217 ] Run job 1 for 1.00 secs 336 | [ time 218 ] Run job 2 for 1.00 secs 337 | [ time 219 ] Run job 0 for 1.00 secs 338 | [ time 220 ] Run job 1 for 1.00 secs 339 | [ time 221 ] Run job 2 for 1.00 secs 340 | [ time 222 ] Run job 0 for 1.00 secs 341 | [ time 223 ] Run job 1 for 1.00 secs 342 | [ time 224 ] Run job 2 for 1.00 secs 343 | [ time 225 ] Run job 0 for 1.00 secs 344 | [ time 226 ] Run job 1 for 1.00 secs 345 | [ time 227 ] Run job 2 for 1.00 secs 346 | [ time 228 ] Run job 0 for 1.00 secs 347 | [ time 229 ] Run job 1 for 1.00 secs 348 | [ time 230 ] Run job 2 for 1.00 secs 349 | [ time 231 ] Run job 0 for 1.00 secs 350 | [ time 232 ] Run job 1 for 1.00 secs 351 | [ time 233 ] Run job 2 for 1.00 secs 352 | [ time 234 ] Run job 0 for 1.00 secs 353 | [ time 235 ] Run job 1 for 1.00 secs 354 | [ time 236 ] Run job 2 for 1.00 secs 355 | [ time 237 ] Run job 0 for 1.00 secs 356 | [ time 238 ] Run job 1 for 1.00 secs 357 | [ time 239 ] Run job 2 for 1.00 secs 358 | [ time 240 ] Run job 0 for 1.00 secs 359 | [ time 241 ] Run job 1 for 1.00 secs 360 | [ time 242 ] Run job 2 for 1.00 secs 361 | [ time 243 ] Run job 0 for 1.00 secs 362 | [ time 244 ] Run job 1 for 1.00 secs 363 | [ time 245 ] Run job 2 for 1.00 secs 364 | [ time 246 ] Run job 0 for 1.00 secs 365 | [ time 247 ] Run job 1 for 1.00 secs 366 | [ time 248 ] Run job 2 for 1.00 secs 367 | [ time 249 ] Run job 0 for 1.00 secs 368 | [ time 250 ] Run job 1 for 1.00 secs 369 | [ time 251 ] Run job 2 for 1.00 secs 370 | [ time 252 ] Run job 0 for 1.00 secs 371 | [ time 253 ] Run job 1 for 1.00 secs 372 | [ time 254 ] Run job 2 for 1.00 secs 373 | [ time 255 ] Run job 0 for 1.00 secs 374 | [ time 256 ] Run job 1 for 1.00 secs 375 | [ time 257 ] Run job 2 for 1.00 secs 376 | [ time 258 ] Run job 0 for 1.00 secs 377 | [ time 259 ] Run job 1 for 1.00 secs 378 | [ time 260 ] Run job 2 for 1.00 secs 379 | [ time 261 ] Run job 0 for 1.00 secs 380 | [ time 262 ] Run job 1 for 1.00 secs 381 | [ time 263 ] Run job 2 for 1.00 secs 382 | [ time 264 ] Run job 0 for 1.00 secs 383 | [ time 265 ] Run job 1 for 1.00 secs 384 | [ time 266 ] Run job 2 for 1.00 secs 385 | [ time 267 ] Run job 0 for 1.00 secs 386 | [ time 268 ] Run job 1 for 1.00 secs 387 | [ time 269 ] Run job 2 for 1.00 secs 388 | [ time 270 ] Run job 0 for 1.00 secs 389 | [ time 271 ] Run job 1 for 1.00 secs 390 | [ time 272 ] Run job 2 for 1.00 secs 391 | [ time 273 ] Run job 0 for 1.00 secs 392 | [ time 274 ] Run job 1 for 1.00 secs 393 | [ time 275 ] Run job 2 for 1.00 secs 394 | [ time 276 ] Run job 0 for 1.00 secs 395 | [ time 277 ] Run job 1 for 1.00 secs 396 | [ time 278 ] Run job 2 for 1.00 secs 397 | [ time 279 ] Run job 0 for 1.00 secs 398 | [ time 280 ] Run job 1 for 1.00 secs 399 | [ time 281 ] Run job 2 for 1.00 secs 400 | [ time 282 ] Run job 0 for 1.00 secs 401 | [ time 283 ] Run job 1 for 1.00 secs 402 | [ time 284 ] Run job 2 for 1.00 secs 403 | [ time 285 ] Run job 0 for 1.00 secs 404 | [ time 286 ] Run job 1 for 1.00 secs 405 | [ time 287 ] Run job 2 for 1.00 secs 406 | [ time 288 ] Run job 0 for 1.00 secs 407 | [ time 289 ] Run job 1 for 1.00 secs 408 | [ time 290 ] Run job 2 for 1.00 secs 409 | [ time 291 ] Run job 0 for 1.00 secs 410 | [ time 292 ] Run job 1 for 1.00 secs 411 | [ time 293 ] Run job 2 for 1.00 secs 412 | [ time 294 ] Run job 0 for 1.00 secs 413 | [ time 295 ] Run job 1 for 1.00 secs 414 | [ time 296 ] Run job 2 for 1.00 secs 415 | [ time 297 ] Run job 0 for 1.00 secs ( DONE at 298.00 ) 416 | [ time 298 ] Run job 1 for 1.00 secs 417 | [ time 299 ] Run job 2 for 1.00 secs 418 | [ time 300 ] Run job 1 for 1.00 secs 419 | [ time 301 ] Run job 2 for 1.00 secs 420 | [ time 302 ] Run job 1 for 1.00 secs 421 | [ time 303 ] Run job 2 for 1.00 secs 422 | [ time 304 ] Run job 1 for 1.00 secs 423 | [ time 305 ] Run job 2 for 1.00 secs 424 | [ time 306 ] Run job 1 for 1.00 secs 425 | [ time 307 ] Run job 2 for 1.00 secs 426 | [ time 308 ] Run job 1 for 1.00 secs 427 | [ time 309 ] Run job 2 for 1.00 secs 428 | [ time 310 ] Run job 1 for 1.00 secs 429 | [ time 311 ] Run job 2 for 1.00 secs 430 | [ time 312 ] Run job 1 for 1.00 secs 431 | [ time 313 ] Run job 2 for 1.00 secs 432 | [ time 314 ] Run job 1 for 1.00 secs 433 | [ time 315 ] Run job 2 for 1.00 secs 434 | [ time 316 ] Run job 1 for 1.00 secs 435 | [ time 317 ] Run job 2 for 1.00 secs 436 | [ time 318 ] Run job 1 for 1.00 secs 437 | [ time 319 ] Run job 2 for 1.00 secs 438 | [ time 320 ] Run job 1 for 1.00 secs 439 | [ time 321 ] Run job 2 for 1.00 secs 440 | [ time 322 ] Run job 1 for 1.00 secs 441 | [ time 323 ] Run job 2 for 1.00 secs 442 | [ time 324 ] Run job 1 for 1.00 secs 443 | [ time 325 ] Run job 2 for 1.00 secs 444 | [ time 326 ] Run job 1 for 1.00 secs 445 | [ time 327 ] Run job 2 for 1.00 secs 446 | [ time 328 ] Run job 1 for 1.00 secs 447 | [ time 329 ] Run job 2 for 1.00 secs 448 | [ time 330 ] Run job 1 for 1.00 secs 449 | [ time 331 ] Run job 2 for 1.00 secs 450 | [ time 332 ] Run job 1 for 1.00 secs 451 | [ time 333 ] Run job 2 for 1.00 secs 452 | [ time 334 ] Run job 1 for 1.00 secs 453 | [ time 335 ] Run job 2 for 1.00 secs 454 | [ time 336 ] Run job 1 for 1.00 secs 455 | [ time 337 ] Run job 2 for 1.00 secs 456 | [ time 338 ] Run job 1 for 1.00 secs 457 | [ time 339 ] Run job 2 for 1.00 secs 458 | [ time 340 ] Run job 1 for 1.00 secs 459 | [ time 341 ] Run job 2 for 1.00 secs 460 | [ time 342 ] Run job 1 for 1.00 secs 461 | [ time 343 ] Run job 2 for 1.00 secs 462 | [ time 344 ] Run job 1 for 1.00 secs 463 | [ time 345 ] Run job 2 for 1.00 secs 464 | [ time 346 ] Run job 1 for 1.00 secs 465 | [ time 347 ] Run job 2 for 1.00 secs 466 | [ time 348 ] Run job 1 for 1.00 secs 467 | [ time 349 ] Run job 2 for 1.00 secs 468 | [ time 350 ] Run job 1 for 1.00 secs 469 | [ time 351 ] Run job 2 for 1.00 secs 470 | [ time 352 ] Run job 1 for 1.00 secs 471 | [ time 353 ] Run job 2 for 1.00 secs 472 | [ time 354 ] Run job 1 for 1.00 secs 473 | [ time 355 ] Run job 2 for 1.00 secs 474 | [ time 356 ] Run job 1 for 1.00 secs 475 | [ time 357 ] Run job 2 for 1.00 secs 476 | [ time 358 ] Run job 1 for 1.00 secs 477 | [ time 359 ] Run job 2 for 1.00 secs 478 | [ time 360 ] Run job 1 for 1.00 secs 479 | [ time 361 ] Run job 2 for 1.00 secs 480 | [ time 362 ] Run job 1 for 1.00 secs 481 | [ time 363 ] Run job 2 for 1.00 secs 482 | [ time 364 ] Run job 1 for 1.00 secs 483 | [ time 365 ] Run job 2 for 1.00 secs 484 | [ time 366 ] Run job 1 for 1.00 secs 485 | [ time 367 ] Run job 2 for 1.00 secs 486 | [ time 368 ] Run job 1 for 1.00 secs 487 | [ time 369 ] Run job 2 for 1.00 secs 488 | [ time 370 ] Run job 1 for 1.00 secs 489 | [ time 371 ] Run job 2 for 1.00 secs 490 | [ time 372 ] Run job 1 for 1.00 secs 491 | [ time 373 ] Run job 2 for 1.00 secs 492 | [ time 374 ] Run job 1 for 1.00 secs 493 | [ time 375 ] Run job 2 for 1.00 secs 494 | [ time 376 ] Run job 1 for 1.00 secs 495 | [ time 377 ] Run job 2 for 1.00 secs 496 | [ time 378 ] Run job 1 for 1.00 secs 497 | [ time 379 ] Run job 2 for 1.00 secs 498 | [ time 380 ] Run job 1 for 1.00 secs 499 | [ time 381 ] Run job 2 for 1.00 secs 500 | [ time 382 ] Run job 1 for 1.00 secs 501 | [ time 383 ] Run job 2 for 1.00 secs 502 | [ time 384 ] Run job 1 for 1.00 secs 503 | [ time 385 ] Run job 2 for 1.00 secs 504 | [ time 386 ] Run job 1 for 1.00 secs 505 | [ time 387 ] Run job 2 for 1.00 secs 506 | [ time 388 ] Run job 1 for 1.00 secs 507 | [ time 389 ] Run job 2 for 1.00 secs 508 | [ time 390 ] Run job 1 for 1.00 secs 509 | [ time 391 ] Run job 2 for 1.00 secs 510 | [ time 392 ] Run job 1 for 1.00 secs 511 | [ time 393 ] Run job 2 for 1.00 secs 512 | [ time 394 ] Run job 1 for 1.00 secs 513 | [ time 395 ] Run job 2 for 1.00 secs 514 | [ time 396 ] Run job 1 for 1.00 secs 515 | [ time 397 ] Run job 2 for 1.00 secs 516 | [ time 398 ] Run job 1 for 1.00 secs 517 | [ time 399 ] Run job 2 for 1.00 secs 518 | [ time 400 ] Run job 1 for 1.00 secs 519 | [ time 401 ] Run job 2 for 1.00 secs 520 | [ time 402 ] Run job 1 for 1.00 secs 521 | [ time 403 ] Run job 2 for 1.00 secs 522 | [ time 404 ] Run job 1 for 1.00 secs 523 | [ time 405 ] Run job 2 for 1.00 secs 524 | [ time 406 ] Run job 1 for 1.00 secs 525 | [ time 407 ] Run job 2 for 1.00 secs 526 | [ time 408 ] Run job 1 for 1.00 secs 527 | [ time 409 ] Run job 2 for 1.00 secs 528 | [ time 410 ] Run job 1 for 1.00 secs 529 | [ time 411 ] Run job 2 for 1.00 secs 530 | [ time 412 ] Run job 1 for 1.00 secs 531 | [ time 413 ] Run job 2 for 1.00 secs 532 | [ time 414 ] Run job 1 for 1.00 secs 533 | [ time 415 ] Run job 2 for 1.00 secs 534 | [ time 416 ] Run job 1 for 1.00 secs 535 | [ time 417 ] Run job 2 for 1.00 secs 536 | [ time 418 ] Run job 1 for 1.00 secs 537 | [ time 419 ] Run job 2 for 1.00 secs 538 | [ time 420 ] Run job 1 for 1.00 secs 539 | [ time 421 ] Run job 2 for 1.00 secs 540 | [ time 422 ] Run job 1 for 1.00 secs 541 | [ time 423 ] Run job 2 for 1.00 secs 542 | [ time 424 ] Run job 1 for 1.00 secs 543 | [ time 425 ] Run job 2 for 1.00 secs 544 | [ time 426 ] Run job 1 for 1.00 secs 545 | [ time 427 ] Run job 2 for 1.00 secs 546 | [ time 428 ] Run job 1 for 1.00 secs 547 | [ time 429 ] Run job 2 for 1.00 secs 548 | [ time 430 ] Run job 1 for 1.00 secs 549 | [ time 431 ] Run job 2 for 1.00 secs 550 | [ time 432 ] Run job 1 for 1.00 secs 551 | [ time 433 ] Run job 2 for 1.00 secs 552 | [ time 434 ] Run job 1 for 1.00 secs 553 | [ time 435 ] Run job 2 for 1.00 secs 554 | [ time 436 ] Run job 1 for 1.00 secs 555 | [ time 437 ] Run job 2 for 1.00 secs 556 | [ time 438 ] Run job 1 for 1.00 secs 557 | [ time 439 ] Run job 2 for 1.00 secs 558 | [ time 440 ] Run job 1 for 1.00 secs 559 | [ time 441 ] Run job 2 for 1.00 secs 560 | [ time 442 ] Run job 1 for 1.00 secs 561 | [ time 443 ] Run job 2 for 1.00 secs 562 | [ time 444 ] Run job 1 for 1.00 secs 563 | [ time 445 ] Run job 2 for 1.00 secs 564 | [ time 446 ] Run job 1 for 1.00 secs 565 | [ time 447 ] Run job 2 for 1.00 secs 566 | [ time 448 ] Run job 1 for 1.00 secs 567 | [ time 449 ] Run job 2 for 1.00 secs 568 | [ time 450 ] Run job 1 for 1.00 secs 569 | [ time 451 ] Run job 2 for 1.00 secs 570 | [ time 452 ] Run job 1 for 1.00 secs 571 | [ time 453 ] Run job 2 for 1.00 secs 572 | [ time 454 ] Run job 1 for 1.00 secs 573 | [ time 455 ] Run job 2 for 1.00 secs 574 | [ time 456 ] Run job 1 for 1.00 secs 575 | [ time 457 ] Run job 2 for 1.00 secs 576 | [ time 458 ] Run job 1 for 1.00 secs 577 | [ time 459 ] Run job 2 for 1.00 secs 578 | [ time 460 ] Run job 1 for 1.00 secs 579 | [ time 461 ] Run job 2 for 1.00 secs 580 | [ time 462 ] Run job 1 for 1.00 secs 581 | [ time 463 ] Run job 2 for 1.00 secs 582 | [ time 464 ] Run job 1 for 1.00 secs 583 | [ time 465 ] Run job 2 for 1.00 secs 584 | [ time 466 ] Run job 1 for 1.00 secs 585 | [ time 467 ] Run job 2 for 1.00 secs 586 | [ time 468 ] Run job 1 for 1.00 secs 587 | [ time 469 ] Run job 2 for 1.00 secs 588 | [ time 470 ] Run job 1 for 1.00 secs 589 | [ time 471 ] Run job 2 for 1.00 secs 590 | [ time 472 ] Run job 1 for 1.00 secs 591 | [ time 473 ] Run job 2 for 1.00 secs 592 | [ time 474 ] Run job 1 for 1.00 secs 593 | [ time 475 ] Run job 2 for 1.00 secs 594 | [ time 476 ] Run job 1 for 1.00 secs 595 | [ time 477 ] Run job 2 for 1.00 secs 596 | [ time 478 ] Run job 1 for 1.00 secs 597 | [ time 479 ] Run job 2 for 1.00 secs 598 | [ time 480 ] Run job 1 for 1.00 secs 599 | [ time 481 ] Run job 2 for 1.00 secs 600 | [ time 482 ] Run job 1 for 1.00 secs 601 | [ time 483 ] Run job 2 for 1.00 secs 602 | [ time 484 ] Run job 1 for 1.00 secs 603 | [ time 485 ] Run job 2 for 1.00 secs 604 | [ time 486 ] Run job 1 for 1.00 secs 605 | [ time 487 ] Run job 2 for 1.00 secs 606 | [ time 488 ] Run job 1 for 1.00 secs 607 | [ time 489 ] Run job 2 for 1.00 secs 608 | [ time 490 ] Run job 1 for 1.00 secs 609 | [ time 491 ] Run job 2 for 1.00 secs 610 | [ time 492 ] Run job 1 for 1.00 secs 611 | [ time 493 ] Run job 2 for 1.00 secs 612 | [ time 494 ] Run job 1 for 1.00 secs 613 | [ time 495 ] Run job 2 for 1.00 secs 614 | [ time 496 ] Run job 1 for 1.00 secs 615 | [ time 497 ] Run job 2 for 1.00 secs 616 | [ time 498 ] Run job 1 for 1.00 secs ( DONE at 499.00 ) 617 | [ time 499 ] Run job 2 for 1.00 secs 618 | [ time 500 ] Run job 2 for 1.00 secs 619 | [ time 501 ] Run job 2 for 1.00 secs 620 | [ time 502 ] Run job 2 for 1.00 secs 621 | [ time 503 ] Run job 2 for 1.00 secs 622 | [ time 504 ] Run job 2 for 1.00 secs 623 | [ time 505 ] Run job 2 for 1.00 secs 624 | [ time 506 ] Run job 2 for 1.00 secs 625 | [ time 507 ] Run job 2 for 1.00 secs 626 | [ time 508 ] Run job 2 for 1.00 secs 627 | [ time 509 ] Run job 2 for 1.00 secs 628 | [ time 510 ] Run job 2 for 1.00 secs 629 | [ time 511 ] Run job 2 for 1.00 secs 630 | [ time 512 ] Run job 2 for 1.00 secs 631 | [ time 513 ] Run job 2 for 1.00 secs 632 | [ time 514 ] Run job 2 for 1.00 secs 633 | [ time 515 ] Run job 2 for 1.00 secs 634 | [ time 516 ] Run job 2 for 1.00 secs 635 | [ time 517 ] Run job 2 for 1.00 secs 636 | [ time 518 ] Run job 2 for 1.00 secs 637 | [ time 519 ] Run job 2 for 1.00 secs 638 | [ time 520 ] Run job 2 for 1.00 secs 639 | [ time 521 ] Run job 2 for 1.00 secs 640 | [ time 522 ] Run job 2 for 1.00 secs 641 | [ time 523 ] Run job 2 for 1.00 secs 642 | [ time 524 ] Run job 2 for 1.00 secs 643 | [ time 525 ] Run job 2 for 1.00 secs 644 | [ time 526 ] Run job 2 for 1.00 secs 645 | [ time 527 ] Run job 2 for 1.00 secs 646 | [ time 528 ] Run job 2 for 1.00 secs 647 | [ time 529 ] Run job 2 for 1.00 secs 648 | [ time 530 ] Run job 2 for 1.00 secs 649 | [ time 531 ] Run job 2 for 1.00 secs 650 | [ time 532 ] Run job 2 for 1.00 secs 651 | [ time 533 ] Run job 2 for 1.00 secs 652 | [ time 534 ] Run job 2 for 1.00 secs 653 | [ time 535 ] Run job 2 for 1.00 secs 654 | [ time 536 ] Run job 2 for 1.00 secs 655 | [ time 537 ] Run job 2 for 1.00 secs 656 | [ time 538 ] Run job 2 for 1.00 secs 657 | [ time 539 ] Run job 2 for 1.00 secs 658 | [ time 540 ] Run job 2 for 1.00 secs 659 | [ time 541 ] Run job 2 for 1.00 secs 660 | [ time 542 ] Run job 2 for 1.00 secs 661 | [ time 543 ] Run job 2 for 1.00 secs 662 | [ time 544 ] Run job 2 for 1.00 secs 663 | [ time 545 ] Run job 2 for 1.00 secs 664 | [ time 546 ] Run job 2 for 1.00 secs 665 | [ time 547 ] Run job 2 for 1.00 secs 666 | [ time 548 ] Run job 2 for 1.00 secs 667 | [ time 549 ] Run job 2 for 1.00 secs 668 | [ time 550 ] Run job 2 for 1.00 secs 669 | [ time 551 ] Run job 2 for 1.00 secs 670 | [ time 552 ] Run job 2 for 1.00 secs 671 | [ time 553 ] Run job 2 for 1.00 secs 672 | [ time 554 ] Run job 2 for 1.00 secs 673 | [ time 555 ] Run job 2 for 1.00 secs 674 | [ time 556 ] Run job 2 for 1.00 secs 675 | [ time 557 ] Run job 2 for 1.00 secs 676 | [ time 558 ] Run job 2 for 1.00 secs 677 | [ time 559 ] Run job 2 for 1.00 secs 678 | [ time 560 ] Run job 2 for 1.00 secs 679 | [ time 561 ] Run job 2 for 1.00 secs 680 | [ time 562 ] Run job 2 for 1.00 secs 681 | [ time 563 ] Run job 2 for 1.00 secs 682 | [ time 564 ] Run job 2 for 1.00 secs 683 | [ time 565 ] Run job 2 for 1.00 secs 684 | [ time 566 ] Run job 2 for 1.00 secs 685 | [ time 567 ] Run job 2 for 1.00 secs 686 | [ time 568 ] Run job 2 for 1.00 secs 687 | [ time 569 ] Run job 2 for 1.00 secs 688 | [ time 570 ] Run job 2 for 1.00 secs 689 | [ time 571 ] Run job 2 for 1.00 secs 690 | [ time 572 ] Run job 2 for 1.00 secs 691 | [ time 573 ] Run job 2 for 1.00 secs 692 | [ time 574 ] Run job 2 for 1.00 secs 693 | [ time 575 ] Run job 2 for 1.00 secs 694 | [ time 576 ] Run job 2 for 1.00 secs 695 | [ time 577 ] Run job 2 for 1.00 secs 696 | [ time 578 ] Run job 2 for 1.00 secs 697 | [ time 579 ] Run job 2 for 1.00 secs 698 | [ time 580 ] Run job 2 for 1.00 secs 699 | [ time 581 ] Run job 2 for 1.00 secs 700 | [ time 582 ] Run job 2 for 1.00 secs 701 | [ time 583 ] Run job 2 for 1.00 secs 702 | [ time 584 ] Run job 2 for 1.00 secs 703 | [ time 585 ] Run job 2 for 1.00 secs 704 | [ time 586 ] Run job 2 for 1.00 secs 705 | [ time 587 ] Run job 2 for 1.00 secs 706 | [ time 588 ] Run job 2 for 1.00 secs 707 | [ time 589 ] Run job 2 for 1.00 secs 708 | [ time 590 ] Run job 2 for 1.00 secs 709 | [ time 591 ] Run job 2 for 1.00 secs 710 | [ time 592 ] Run job 2 for 1.00 secs 711 | [ time 593 ] Run job 2 for 1.00 secs 712 | [ time 594 ] Run job 2 for 1.00 secs 713 | [ time 595 ] Run job 2 for 1.00 secs 714 | [ time 596 ] Run job 2 for 1.00 secs 715 | [ time 597 ] Run job 2 for 1.00 secs 716 | [ time 598 ] Run job 2 for 1.00 secs 717 | [ time 599 ] Run job 2 for 1.00 secs ( DONE at 600.00 ) 718 | 719 | Final statistics: 720 | Job 0 -- Response: 0.00 Turnaround 298.00 Wait 198.00 721 | Job 1 -- Response: 1.00 Turnaround 499.00 Wait 299.00 722 | Job 2 -- Response: 2.00 Turnaround 600.00 Wait 300.00 723 | 724 | Average -- Response: 1.00 Turnaround 465.67 Wait 265.67 725 | ``` 726 | 727 | * **问题 4 答案** 728 | 长度更短的工作负载先到的情况下,SJF和FIFO有相同的周转时间。 729 | 730 | * **问题 5 答案** 731 | 量子长度大于最长的工作负载的长度时,RR可以看作是SJF,因此有相同的相应时间。 732 | 733 | * **问题 6 答案** 734 | 随着工作长度的增加,响应时间会越来越大。 735 | 模拟程序: 736 | ``` 737 | [testjz@localhost cpu-sched]$ ./scheduler.py -p SJF -l 100,100,100 -c 738 | ARG policy SJF 739 | ARG jlist 100,100,100 740 | 741 | Here is the job list, with the run time of each job: 742 | Job 0 ( length = 100.0 ) 743 | Job 1 ( length = 100.0 ) 744 | Job 2 ( length = 100.0 ) 745 | 746 | 747 | ** Solutions ** 748 | 749 | Execution trace: 750 | [ time 0 ] Run job 0 for 100.00 secs ( DONE at 100.00 ) 751 | [ time 100 ] Run job 1 for 100.00 secs ( DONE at 200.00 ) 752 | [ time 200 ] Run job 2 for 100.00 secs ( DONE at 300.00 ) 753 | 754 | Final statistics: 755 | Job 0 -- Response: 0.00 Turnaround 100.00 Wait 0.00 756 | Job 1 -- Response: 100.00 Turnaround 200.00 Wait 100.00 757 | Job 2 -- Response: 200.00 Turnaround 300.00 Wait 200.00 758 | 759 | Average -- Response: 100.00 Turnaround 200.00 Wait 100.00 760 | 761 | [testjz@localhost cpu-sched]$ ./scheduler.py -p SJF -l 200,200,200 -c 762 | ARG policy SJF 763 | ARG jlist 200,200,200 764 | 765 | Here is the job list, with the run time of each job: 766 | Job 0 ( length = 200.0 ) 767 | Job 1 ( length = 200.0 ) 768 | Job 2 ( length = 200.0 ) 769 | 770 | 771 | ** Solutions ** 772 | 773 | Execution trace: 774 | [ time 0 ] Run job 0 for 200.00 secs ( DONE at 200.00 ) 775 | [ time 200 ] Run job 1 for 200.00 secs ( DONE at 400.00 ) 776 | [ time 400 ] Run job 2 for 200.00 secs ( DONE at 600.00 ) 777 | 778 | Final statistics: 779 | Job 0 -- Response: 0.00 Turnaround 200.00 Wait 0.00 780 | Job 1 -- Response: 200.00 Turnaround 400.00 Wait 200.00 781 | Job 2 -- Response: 400.00 Turnaround 600.00 Wait 400.00 782 | 783 | Average -- Response: 200.00 Turnaround 400.00 Wait 200.00 784 | 785 | [testjz@localhost cpu-sched]$ ./scheduler.py -p SJF -l 300,300,300 -c 786 | ARG policy SJF 787 | ARG jlist 300,300,300 788 | 789 | Here is the job list, with the run time of each job: 790 | Job 0 ( length = 300.0 ) 791 | Job 1 ( length = 300.0 ) 792 | Job 2 ( length = 300.0 ) 793 | 794 | 795 | ** Solutions ** 796 | 797 | Execution trace: 798 | [ time 0 ] Run job 0 for 300.00 secs ( DONE at 300.00 ) 799 | [ time 300 ] Run job 1 for 300.00 secs ( DONE at 600.00 ) 800 | [ time 600 ] Run job 2 for 300.00 secs ( DONE at 900.00 ) 801 | 802 | Final statistics: 803 | Job 0 -- Response: 0.00 Turnaround 300.00 Wait 0.00 804 | Job 1 -- Response: 300.00 Turnaround 600.00 Wait 300.00 805 | Job 2 -- Response: 600.00 Turnaround 900.00 Wait 600.00 806 | 807 | Average -- Response: 300.00 Turnaround 600.00 Wait 300.00 808 | ``` 809 | 三次模拟,每次的任务长度分别为100,200,300,每次都是三个任务。 810 | 可以看到,响应时间分别为100,200,300。响应时间随着周转时间的增加而增加。 811 | 812 | * **问题 7 答案** 813 | 随着量子长度的增加,响应时间会越来越大。 814 | 设量子长度为m,且每个任务的长度比量子长度更长。 815 | 则响应时间的计算过程为: 816 | ![响应时间](1.gif) 817 | -------------------------------------------------------------------------------- /Chapter-8/Chapter-8-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | ``` 3 | [testjz@localhost cpu-sched-mlfq]$ ./mlfq.py -j 2 -m 10 -M 0 -n 2 -q 3 -c 4 | Here is the list of inputs: 5 | OPTIONS jobs 2 6 | OPTIONS queues 2 7 | OPTIONS allotments for queue 1 is 1 8 | OPTIONS quantum length for queue 1 is 3 9 | OPTIONS allotments for queue 0 is 1 10 | OPTIONS quantum length for queue 0 is 3 11 | OPTIONS boost 0 12 | OPTIONS ioTime 5 13 | OPTIONS stayAfterIO False 14 | OPTIONS iobump False 15 | 16 | 17 | For each job, three defining characteristics are given: 18 | startTime : at what time does the job enter the system 19 | runTime : the total CPU time needed by the job to finish 20 | ioFreq : every ioFreq time units, the job issues an I/O 21 | (the I/O takes ioTime units to complete) 22 | 23 | Job List: 24 | Job 0: startTime 0 - runTime 8 - ioFreq 0 25 | Job 1: startTime 0 - runTime 4 - ioFreq 0 26 | 27 | 28 | Execution Trace: 29 | 30 | [ time 0 ] JOB BEGINS by JOB 0 31 | [ time 0 ] JOB BEGINS by JOB 1 32 | [ time 0 ] Run JOB 0 at PRIORITY 1 [ TICKS 2 ALLOT 1 TIME 7 (of 8) ] 33 | [ time 1 ] Run JOB 0 at PRIORITY 1 [ TICKS 1 ALLOT 1 TIME 6 (of 8) ] 34 | [ time 2 ] Run JOB 0 at PRIORITY 1 [ TICKS 0 ALLOT 1 TIME 5 (of 8) ] 35 | [ time 3 ] Run JOB 1 at PRIORITY 1 [ TICKS 2 ALLOT 1 TIME 3 (of 4) ] 36 | [ time 4 ] Run JOB 1 at PRIORITY 1 [ TICKS 1 ALLOT 1 TIME 2 (of 4) ] 37 | [ time 5 ] Run JOB 1 at PRIORITY 1 [ TICKS 0 ALLOT 1 TIME 1 (of 4) ] 38 | [ time 6 ] Run JOB 0 at PRIORITY 0 [ TICKS 2 ALLOT 1 TIME 4 (of 8) ] 39 | [ time 7 ] Run JOB 0 at PRIORITY 0 [ TICKS 1 ALLOT 1 TIME 3 (of 8) ] 40 | [ time 8 ] Run JOB 0 at PRIORITY 0 [ TICKS 0 ALLOT 1 TIME 2 (of 8) ] 41 | [ time 9 ] Run JOB 1 at PRIORITY 0 [ TICKS 2 ALLOT 1 TIME 0 (of 4) ] 42 | [ time 10 ] FINISHED JOB 1 43 | [ time 10 ] Run JOB 0 at PRIORITY 0 [ TICKS 2 ALLOT 1 TIME 1 (of 8) ] 44 | [ time 11 ] Run JOB 0 at PRIORITY 0 [ TICKS 1 ALLOT 1 TIME 0 (of 8) ] 45 | [ time 12 ] FINISHED JOB 0 46 | 47 | Final statistics: 48 | Job 0: startTime 0 - response 0 - turnaround 12 49 | Job 1: startTime 0 - response 3 - turnaround 10 50 | 51 | Avg 1: startTime n/a - response 1.50 - turnaround 11.00 52 | 53 | ``` 54 | * **问题 2 答案** 55 | 答案结果太长,所以我只写出命令,按照命令执行即可产生答案。 56 | ``` 57 | 实例1:单个长工作 58 | ./mlfq.py -l 0,200,0 -q 10 -n 3 -c 59 | 实例2:来了一个短工作 60 | ./mlfq.py -l 0,200,0:100,20,0 -q 10 -n 3 -c 61 | 实例3:如果有I/O呢 62 | ./mlfq.py -l 0,40,2:0,200,0 -q 10 -n 3 -i 5 -c 63 | 尝试2:提升优先级 图8.5左 64 | ./mlfq.py -l 0,150,0:100,50,5:100,50,5 -q 10 -n 3 -i 5 -S -c 65 | 尝试2:提升优先级 图8.5右 66 | ./mlfq.py -l 0,150,0:100,50,5:100,50,5 -q 10 -n 3 -i 5 -S -B 50 -c 67 | 尝试3:更好的计时方式 图8.6左 68 | ./mlfq.py -l 0,200,0:30,200,9 -q 10 -n 3 -i 1 -S -c 69 | 尝试3:更好的计时方式 图8.6右 70 | ./mlfq.py -l 0,200,0:30,200,9 -q 10 -n 3 -i 1 -c 71 | 8.5 MLFQ调优及其他问题 图8.7 72 | ./mlfq.py -l 0,200,0:0,200,0 -Q 10,20,40 -n 3 -c 73 | ``` 74 | 75 | * **问题 3 答案** 76 | 队列个数设置为1即可。 77 | 由于结果太长,这里只写出命令。 78 | ``` 79 | ./mlfq.py -l 0,50,0:0,50,0:0,50,0 -q 10 -n 1 -c 80 | ``` 81 | 82 | * **问题 4 答案** 83 | 由于结果太长,这里只写出命令。 84 | ``` 85 | ./mlfq.py -l 0,1000,0:300,1000,99 -q 100 -n 3 -i 1 -S -c 86 | ``` 87 | 88 | * **问题 5 答案** 89 | 由于结果太长,这里只写出命令。 90 | ``` 91 | ./mlfq.py -l 0,200,0:0,100,5:0,100,5 -q 10 -n 3 -i 5 -B 100 -c 92 | ``` 93 | 94 | * **问题 6 答案** 95 | 由于结果太长,这里只写出命令。 96 | ``` 97 | ./mlfq.py -l 0,50,5:0,50,5:0,50,5 -q 10 -n 3 -i 5 -S -c 98 | ./mlfq.py -l 0,50,5:0,50,5:0,50,5 -q 10 -n 3 -i 5 -S -I -c 99 | ``` 100 | 如果不加-I,三个任务交替执行。如果增加了-I,则第一个和第二个任务交替执行,第三个任务没有机会被执行。 101 | -------------------------------------------------------------------------------- /Chapter-9/Chapter-9-Homework-Answers.md: -------------------------------------------------------------------------------- 1 | * **问题 1 答案** 2 | 由于结果太长,这里只写出命令。 3 | ``` 4 | ./lottery.py -j 3 -s 1 -c 5 | ./lottery.py -j 3 -s 2 -c 6 | ./lottery.py -j 3 -s 3 -c 7 | ``` 8 | 9 | * **问题 2 答案** 10 | 由于结果太长,这里只写出命令。 11 | ``` 12 | ./lottery.py -l 10:1,10:100 -c 13 | ``` 14 | 在工作1完成之前,工作0基本没有机会运行。这种不平衡会造成进程饥饿现象。 15 | 16 | * **问题 3 答案** 17 | 由于结果太长,这里只写出命令和简化结果。 18 | ``` 19 | ./lottery.py -l 100:100,100:100 -s 1 -c 20 | --> JOB 1 DONE at time 196 21 | --> JOB 0 DONE at time 200 22 | 23 | ./lottery.py -l 100:100,100:100 -s 2 -c 24 | --> JOB 1 DONE at time 190 25 | --> JOB 0 DONE at time 200 26 | 27 | ./lottery.py -l 100:100,100:100 -s 3 -c 28 | --> JOB 0 DONE at time 196 29 | --> JOB 1 DONE at time 200 30 | 31 | ./lottery.py -l 100:100,100:100 -s 4 -c 32 | --> JOB 1 DONE at time 199 33 | --> JOB 0 DONE at time 200 34 | ``` 35 | 我觉得还是挺公平的。 36 | 37 | 38 | * **问题 4 答案** 39 | 由于结果太长,这里只写出命令和简化结果。 40 | ``` 41 | ./lottery.py -l 100:100,100:100 -s 1 -q 10 -c 42 | --> JOB 1 DONE at time 160 43 | --> JOB 0 DONE at time 200 44 | 45 | ./lottery.py -l 100:100,100:100 -s 2 -q 10 -c 46 | --> JOB 0 DONE at time 190 47 | --> JOB 1 DONE at time 200 48 | 49 | ./lottery.py -l 100:100,100:100 -s 3 -q 10 -c 50 | --> JOB 1 DONE at time 190 51 | --> JOB 0 DONE at time 200 52 | 53 | ./lottery.py -l 100:100,100:100 -s 4 -q 10 -c 54 | --> JOB 0 DONE at time 190 55 | --> JOB 1 DONE at time 200 56 | ``` 57 | 由于量子规模变大,相当于工作长度缩短了,因此进程的不公平性增加。 58 | 59 | 60 | * **问题 5 答案** 61 | 用步长调度程序制作图表,如果选取调度周期作为采样时间点,那么图表会是精确的完全公平直线。 62 | 如果同时选用非调度周期作为时间点,那么在直线附近会有一些起伏,且起伏程度越来越小。 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSTEP-Answers 2 | OSTEP-操作系统导论 答案 Operating Systems: Three Easy Pieces 3 | 4 | 操作系统导论(中文版) 5 | * 作业答案 6 | 7 | ## 答案目录 8 | 9 | ### 第一部分 虚拟化 10 | #### 第4章 抽象:进程 11 | * [模拟作业答案](Chapter-4/Chapter-4-Homework-Answers.md) 12 | #### 第5章 插叙:进程API 13 | * [编程作业答案](Chapter-5/Chapter-5-Homework-Answers.md) 14 | #### 第6章 机制:受限直接执行 15 | * [测量作业答案](Chapter-6/Chapter-6-Homework-Answers.md) 16 | #### 第7章 进程调度:介绍 17 | * [模拟作业答案](Chapter-7/Chapter-7-Homework-Answers.md) 18 | #### 第8章 调度:多级反馈队列 19 | * [模拟作业答案](Chapter-8/Chapter-8-Homework-Answers.md) 20 | #### 第9章 调度:比例份额 21 | * [模拟作业答案](Chapter-9/Chapter-9-Homework-Answers.md) 22 | #### 第14章 插叙:内存操作API 23 | * [编程作业答案](Chapter-14/Chapter-14-Homework-Answers.md) 24 | #### 第15章 机制:地址转换 25 | * [模拟作业答案](Chapter-15/Chapter-15-Homework-Answers.md) 26 | #### 第16章 分段 27 | * [模拟作业答案](Chapter-16/Chapter-16-Homework-Answers.md) 28 | #### 第17章 空闲空间管理 29 | * [模拟作业答案](Chapter-17/Chapter-17-Homework-Answers.md) 30 | #### 第18章 分页:介绍 31 | * [模拟作业答案](Chapter-18/Chapter-18-Homework-Answers.md) 32 | #### 第19章 分页:快速地址转换(TLB) 33 | * [测量作业答案](Chapter-19/Chapter-19-Homework-Answers.md) 34 | #### 第20章 分页:较小的表 35 | * [模拟作业答案](Chapter-20/Chapter-20-Homework-Answers.md) 36 | #### 第22章 超越物理内存:策略 37 | * [模拟作业答案](Chapter-22/Chapter-22-Homework-Answers.md) 38 | ### 第二部分 并发 39 | #### 第26章 并发:介绍 40 | * [模拟作业答案](Chapter-26/Chapter-26-Homework-Answers.md) 41 | #### 第28章 锁 42 | * [模拟作业答案](Chapter-28/Chapter-28-Homework-Answers.md) 43 | ### 第三部分 持久性 44 | #### 第37章 磁盘驱动器 45 | * [模拟作业答案](Chapter-37/Chapter-37-Homework-Answers.md) 46 | #### 第38章 廉价冗余磁盘阵列(RAID) 47 | * [模拟作业答案](Chapter-38/Chapter-38-Homework-Answers.md) 48 | #### 第39章 插叙:文件和目录 49 | * [编程作业答案](Chapter-39/Chapter-39-Homework-Answers.md) 50 | #### 第40章 文件系统实现 51 | * [模拟作业答案](Chapter-40/Chapter-40-Homework-Answers.md) 52 | #### 第49章 Andrew文件系统(AFS) 53 | * [模拟作业答案](Chapter-49/Chapter-49-Homework-Answers.md) 54 | 55 | 56 | 注:只有部分章节包含作业。开源书有部分章节比中文出版书作业更多,这里仅按照中文出版书中的出现的作业回答。 57 | 58 | ## 编译/执行环境 59 | * 操作系统 Centos7 60 | * C语言 gcc 4.8.5 61 | * Python 2.7.5 62 | 63 | ## 相关链接 64 | * [本书相关信息网站](http://pages.cs.wisc.edu/~remzi/OSTEP/) 65 | * [书正文中代码下载](https://github.com/remzi-arpacidusseau/ostep-code) 66 | * [作业相关代码下载](https://github.com/remzi-arpacidusseau/ostep-homework) 67 | * [项目说明下载](https://github.com/remzi-arpacidusseau/ostep-projects) 68 | --------------------------------------------------------------------------------