《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

368 lines
8.0 KiB

12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
  1. #!/bin/sh
  2. verbose=false
  3. if [ "x$1" = "x-v" ]; then
  4. verbose=true
  5. out=/dev/stdout
  6. err=/dev/stderr
  7. else
  8. out=/dev/null
  9. err=/dev/null
  10. fi
  11. ## make & makeopts
  12. if gmake --version > /dev/null 2>&1; then
  13. make=gmake;
  14. else
  15. make=make;
  16. fi
  17. makeopts="--quiet --no-print-directory -j"
  18. make_print() {
  19. echo `$make $makeopts print-$1`
  20. }
  21. ## command tools
  22. awk='awk'
  23. bc='bc'
  24. date='date'
  25. grep='grep'
  26. rm='rm -f'
  27. sed='sed'
  28. ## symbol table
  29. sym_table='obj/kernel.sym'
  30. ## gdb & gdbopts
  31. gdb="$(make_print GDB)"
  32. gdbport='1234'
  33. gdb_in="$(make_print GRADE_GDB_IN)"
  34. ## qemu & qemuopts
  35. qemu="$(make_print qemu)"
  36. qemu_out="$(make_print GRADE_QEMU_OUT)"
  37. if $qemu -nographic -help | grep -q '^-gdb'; then
  38. qemugdb="-gdb tcp::$gdbport"
  39. else
  40. qemugdb="-s -p $gdbport"
  41. fi
  42. ## default variables
  43. default_timeout=30
  44. default_pts=5
  45. pts=5
  46. part=0
  47. part_pos=0
  48. total=0
  49. total_pos=0
  50. ## default functions
  51. update_score() {
  52. total=`expr $total + $part`
  53. total_pos=`expr $total_pos + $part_pos`
  54. part=0
  55. part_pos=0
  56. }
  57. get_time() {
  58. echo `$date +%s.%N 2> /dev/null`
  59. }
  60. show_part() {
  61. echo "Part $1 Score: $part/$part_pos"
  62. echo
  63. update_score
  64. }
  65. show_final() {
  66. update_score
  67. echo "Total Score: $total/$total_pos"
  68. if [ $total -lt $total_pos ]; then
  69. exit 1
  70. fi
  71. }
  72. show_time() {
  73. t1=$(get_time)
  74. time=`echo "scale=1; ($t1-$t0)/1" | $sed 's/.N/.0/g' | $bc 2> /dev/null`
  75. echo "(${time}s)"
  76. }
  77. show_build_tag() {
  78. echo "$1:" | $awk '{printf "%-24s ", $0}'
  79. }
  80. show_check_tag() {
  81. echo "$1:" | $awk '{printf " -%-40s ", $0}'
  82. }
  83. show_msg() {
  84. echo $1
  85. shift
  86. if [ $# -gt 0 ]; then
  87. echo "$@" | awk '{printf " %s\n", $0}'
  88. echo
  89. fi
  90. }
  91. pass() {
  92. show_msg OK "$@"
  93. part=`expr $part + $pts`
  94. part_pos=`expr $part_pos + $pts`
  95. }
  96. fail() {
  97. show_msg WRONG "$@"
  98. part_pos=`expr $part_pos + $pts`
  99. }
  100. run_qemu() {
  101. # Run qemu with serial output redirected to $qemu_out. If $brkfun is non-empty,
  102. # wait until $brkfun is reached or $timeout expires, then kill QEMU
  103. qemuextra=
  104. if [ "$brkfun" ]; then
  105. qemuextra="-S $qemugdb"
  106. fi
  107. if [ -z "$timeout" ] || [ $timeout -le 0 ]; then
  108. timeout=$default_timeout;
  109. fi
  110. t0=$(get_time)
  111. (
  112. ulimit -t $timeout
  113. exec $qemu -nographic $qemuopts -serial file:$qemu_out -monitor null -no-reboot $qemuextra
  114. ) > $out 2> $err &
  115. pid=$!
  116. # wait for QEMU to start
  117. sleep 1
  118. if [ -n "$brkfun" ]; then
  119. # find the address of the kernel $brkfun function
  120. brkaddr=`$grep " $brkfun\$" $sym_table | $sed -e's/ .*$//g'`
  121. (
  122. echo "target remote localhost:$gdbport"
  123. echo "break *0x$brkaddr"
  124. echo "continue"
  125. ) > $gdb_in
  126. $gdb -batch -nx -x $gdb_in > /dev/null 2>&1
  127. # make sure that QEMU is dead
  128. # on OS X, exiting gdb doesn't always exit qemu
  129. kill $pid > /dev/null 2>&1
  130. fi
  131. }
  132. build_run() {
  133. # usage: build_run <tag> <args>
  134. show_build_tag "$1"
  135. shift
  136. if $verbose; then
  137. echo "$make $@ ..."
  138. fi
  139. $make $makeopts $@ 'DEFS+=-DDEBUG_GRADE' > $out 2> $err
  140. if [ $? -ne 0 ]; then
  141. echo $make $@ failed
  142. exit 1
  143. fi
  144. # now run qemu and save the output
  145. run_qemu
  146. show_time
  147. }
  148. check_result() {
  149. # usage: check_result <tag> <check> <check args...>
  150. show_check_tag "$1"
  151. shift
  152. # give qemu some time to run (for asynchronous mode)
  153. if [ ! -s $qemu_out ]; then
  154. sleep 4
  155. fi
  156. if [ ! -s $qemu_out ]; then
  157. fail > /dev/null
  158. echo 'no $qemu_out'
  159. else
  160. check=$1
  161. shift
  162. $check "$@"
  163. fi
  164. }
  165. check_regexps() {
  166. okay=yes
  167. not=0
  168. reg=0
  169. error=
  170. for i do
  171. if [ "x$i" = "x!" ]; then
  172. not=1
  173. elif [ "x$i" = "x-" ]; then
  174. reg=1
  175. else
  176. if [ $reg -ne 0 ]; then
  177. $grep '-E' "^$i\$" $qemu_out > /dev/null
  178. else
  179. $grep '-F' "$i" $qemu_out > /dev/null
  180. fi
  181. found=$(($? == 0))
  182. if [ $found -eq $not ]; then
  183. if [ $found -eq 0 ]; then
  184. msg="!! error: missing '$i'"
  185. else
  186. msg="!! error: got unexpected line '$i'"
  187. fi
  188. okay=no
  189. if [ -z "$error" ]; then
  190. error="$msg"
  191. else
  192. error="$error\n$msg"
  193. fi
  194. fi
  195. not=0
  196. reg=0
  197. fi
  198. done
  199. if [ "$okay" = "yes" ]; then
  200. pass
  201. else
  202. fail "$error"
  203. if $verbose; then
  204. exit 1
  205. fi
  206. fi
  207. }
  208. run_test() {
  209. # usage: run_test [-tag <tag>] [-Ddef...] [-check <check>] checkargs ...
  210. tag=
  211. check=check_regexps
  212. while true; do
  213. select=
  214. case $1 in
  215. -tag)
  216. select=`expr substr $1 2 ${#1}`
  217. eval $select='$2'
  218. ;;
  219. esac
  220. if [ -z "$select" ]; then
  221. break
  222. fi
  223. shift
  224. shift
  225. done
  226. defs=
  227. while expr "x$1" : "x-D.*" > /dev/null; do
  228. defs="DEFS+='$1' $defs"
  229. shift
  230. done
  231. if [ "x$1" = "x-check" ]; then
  232. check=$2
  233. shift
  234. shift
  235. fi
  236. $make $makeopts touch > /dev/null 2>&1
  237. build_run "$tag" "$defs"
  238. check_result 'check result' "$check" "$@"
  239. }
  240. quick_run() {
  241. # usage: quick_run <tag> [-Ddef...]
  242. tag="$1"
  243. shift
  244. defs=
  245. while expr "x$1" : "x-D.*" > /dev/null; do
  246. defs="DEFS+='$1' $defs"
  247. shift
  248. done
  249. $make $makeopts touch > /dev/null 2>&1
  250. build_run "$tag" "$defs"
  251. }
  252. quick_check() {
  253. # usage: quick_check <tag> checkargs ...
  254. tag="$1"
  255. shift
  256. check_result "$tag" check_regexps "$@"
  257. }
  258. ## kernel image
  259. osimg=$(make_print ucoreimg)
  260. ## swap image
  261. swapimg=$(make_print swapimg)
  262. ## set default qemu-options
  263. qemuopts="-hda $osimg -drive file=$swapimg,media=disk,cache=writeback"
  264. ## set break-function, default is readline
  265. brkfun=readline
  266. ## check now!!
  267. quick_run 'Check VMM'
  268. pts=5
  269. quick_check 'check pmm' \
  270. 'memory management: default_pmm_manager' \
  271. 'check_alloc_page() succeeded!' \
  272. 'check_pgdir() succeeded!' \
  273. 'check_boot_pgdir() succeeded!'
  274. pts=5
  275. quick_check 'check page table' \
  276. 'PDE(0e0) c0000000-f8000000 38000000 urw' \
  277. ' |-- PTE(38000) c0000000-f8000000 38000000 -rw' \
  278. 'PDE(001) fac00000-fb000000 00400000 -rw' \
  279. ' |-- PTE(000e0) faf00000-fafe0000 000e0000 urw' \
  280. ' |-- PTE(00001) fafeb000-fafec000 00001000 -rw'
  281. pts=25
  282. quick_check 'check vmm' \
  283. 'check_vma_struct() succeeded!' \
  284. 'page fault at 0x00000100: K/W [no page found].' \
  285. 'check_pgfault() succeeded!' \
  286. 'check_vmm() succeeded.'
  287. pts=20
  288. quick_check 'check swap page fault' \
  289. 'page fault at 0x00001000: K/W [no page found].' \
  290. 'page fault at 0x00002000: K/W [no page found].' \
  291. 'page fault at 0x00003000: K/W [no page found].' \
  292. 'page fault at 0x00004000: K/W [no page found].' \
  293. 'write Virt Page e in fifo_check_swap' \
  294. 'page fault at 0x00005000: K/W [no page found].' \
  295. 'page fault at 0x00001000: K/W [no page found]' \
  296. 'page fault at 0x00002000: K/W [no page found].' \
  297. 'page fault at 0x00003000: K/W [no page found].' \
  298. 'page fault at 0x00004000: K/W [no page found].' \
  299. 'check_swap() succeeded!'
  300. pts=5
  301. quick_check 'check ticks' \
  302. '++ setup timer interrupts'
  303. pts=30
  304. quick_check 'check initproc' \
  305. 'this initproc, pid = 1, name = "init"' \
  306. 'To U: "Hello world!!".' \
  307. 'To U: "en.., Bye, Bye. :)"'
  308. ## print final-score
  309. show_final