Lab0实验报告

思考题

Thinking 0.1

思考下列有关 Git 的问题:

• 在前述已初始化的 ~/learnGit 目录下,创建一个名为 README.txt 的文件。 执行命令 git status > Untracked.txt。

• 在 README.txt 文件中添加任意文件内容,然后使用 add 命令,再执行命令 git status > Stage.txt。

• 提交 README.txt,并在提交说明里写入自己的学号。

• 执行命令 cat Untracked.txt 和 cat Stage.txt,对比两次运行的结果,体 会 README.txt 两次所处位置的不同。

• 修改 README.txt 文件,再执行命令 git status > Modified.txt。

• 执行命令 cat Modified.txt,观察其结果和第一次执行 add 命令之前的 status 是否一样,并思考原因。

  • 解:
    • 执行git status > Untracked.txt ,表示查询当前README.txt文件状态,并将其记录在Untracked.txt文件中;git status > Stage.txtgit status > Modified.txt 同理。
    • cat Untracked.txt后,第二行显示Untracked files:,说明:在 README.txt 新建的时候,其处于为未跟踪状态 (untracked);
    • cat Stage.txt后,第二行显示 Changes to be committed:,说明:在 README.txt 中任意添加内容,接着用 add 命令之后,文件处于暂存状 态(staged);
    • cat Modified.txt后,第二行显示 Changes not staged for commit:,说明:在修改 README.txt 之后,其处于被修改状态(modified)。

Thinking 0.2

仔细看看0.10,思考一下箭头中的 add the file 、stage the file 和 commit 分别对应的是 Git 里的哪些命令呢?

gitThinking0.2
  • 解:
    • add the file : git add
    • stage the file:git add
    • commit:`git commit

Thinking 0.3

思考下列问题:

  1. 代码文件 print.c 被错误删除时,应当使用什么命令将其恢复?
  2. 代码文件 print.c 被错误删除后,执行了 git rm print.c 命令,此时应当 使用什么命令将其恢复?
  3. 无关文件 hello.txt 已经被添加到暂存区时,如何在不删除此文件的前提下 将其移出暂存区?
  • 解:
    1. git checkout --print.c
    2. git reset HEAD print.c && git checkout --print.c
    3. git rm --cached print.c

Thinking 0.4

思考下列有关 Git 的问题:

• 找到在/home/21xxxxxx/learnGit 下刚刚创建的 README.txt 文件,若不存 在则新建该文件。

• 在文件里加入 Testing 1,git add,git commit,提交说明记为 1。

• 模仿上述做法,把 1 分别改为 2 和 3,再提交两次。

• 使用 git log 命令查看提交日志,看是否已经有三次提交,记下提交说明为 3 的哈希值a。

• 进行版本回退。执行命令 git reset --hard HEAD^后,再执行 git log,观 察其变化。

• 找到提交说明为 1 的哈希值,执行命令 git reset --hard 后,再执 行 git log,观察其变化。

• 现在已经回到了旧版本,为了再次回到新版本,执行 git reset --hard ,再执行 git log,观察其变化。

  • 解:
    • 第一次git log0.4.1
    • 第二次git log0.4.2
    • 第三次git log 0.4.3
    • 第四次git log0.4.4

Thinking 0.5

执行如下命令, 并查看结果

• echo first

• echo second > output.txt

• echo third > output.txt

• echo forth >> output.txt

  • 解:
    • 051
    • 052
    • 053
    • 054

Thinking 0.6

使用你知道的方法(包括重定向)创建下图内容的文件(文件命名为 test), 将创建该文件的命令序列保存在 command 文件中,并将 test 文件作为批处理文件运行, 将运行结果输出至 result 文件中。给出 command 文件和 result 文件的内容,并对最 后的结果进行解释说明(可以从 test 文件的内容入手). 具体实现的过程中思考下列问 题: echo echo Shell Start 与 echo echo Shell Start效果是否有区别; echo echo $c>file1 与 echo echo $c>file1效果是否有区别.

  • 解:

    • command:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      #!/bin/bash                                                              touch test
      echo 'echo Shell Start...' > test
      echo 'echo set a = 1' >> test
      echo 'a=1' >> test
      echo 'echo set b = 2' >> test
      echo 'b=2' >> test
      echo 'echo set c = a+b' >> test
      echo 'c=$[$a+$b]' >> test
      echo 'echo c = $c' >> test
      echo 'echo save c to ./file1' >> test
      echo 'echo $c>file1' >> test
      echo 'echo save b to ./file2' >> test
      echo 'echo $b>file2' >> test
      echo 'echo save a to ./file3' >> test
      echo 'echo $a>file3' >> test
      echo 'echo save file1 file2 file3 to file4' >> test
      echo 'cat file1>file4' >> test
      echo 'cat file2>>file4' >> test
      echo 'cat file3>>file4' >> test
      echo 'echo save file4 to ./result' >> test
      echo 'cat file4>>result' >> test
    • result:

      1
      2
      3
      3
      2
      1
        • echo echo Shell Start 直接把“echo Shell Start” 作为字符串输出;

        • echo (反顿号)echo Shell Start(反顿号)是将 “echo Shell Start” 的输出作为 外层echo 的输入,故会输出 Shell Start

        • echo (单引号)echo Shell Start(单引号)直接把“echo Shell Start” 作为字符串输出。

        • echo echo $c>file1 直接把“echo $c>file1” 作为字符串输出;

        • echo (反顿号)echo $c>file1(反顿号)是将 “echo $c>file1” 的输出作为 外层echo 的输入,故会输出 $c>file1

        • echo (单引号)echo $c>file1(单引号)直接把“$c>file1” 作为字符串输出。

难点分析

对于实验中的难点,可用示意图、流程图或思维导图的方式来表述清楚。

Exercise 0.1

Lab0 第一道练习题包括以下四题,如果你四道题全部完成且正确,即可获得 50 分。

1、在 Lab0 工作区的 src 目录中,存在一个名为 palindrome.c 的文件,使用刚刚学 过的工具打开 palindrome.c,使用 c 语言实现判断输入整数 n(1 ≤ n ≤ 10000) 是否为回 文数的程序 (输入输出部分已经完成)。通过 stdin 每次只输入一个整数 n,若这个数字为 回文数则输出 Y,否则输出 N。[注意:正读倒读相同的整数叫回文数]

2、在 src 目录下,存在一个未补全的 Makefile 文件,借助刚刚掌握的 Makefile 知 识,将其补全,以实现通过 make 命令触发 src 目录下的 palindrome.c 文件的编译链接 的功能,生成的可执行文件命名为 palindrome。

3、在 src/sh_test 目录下,有一个 file 文件和 hello_os.sh 文件。hello_os.sh 是一个未完成的脚本文档,请同学们借助 shell 编程的知识,将其补完,以实现通过命令 bash hello_os.sh AAA BBB,在 hello_os.sh 所处的目录新建一个名为 BBB 的文件,其 内容为 AAA 文件的第 8、32、128、512、1024 行的内容提取 (AAA 文件行数一定超过 1024 行)。[注意:对于命令 bash hello_os.sh AAA BBB,AAA 及 BBB 可为任何合法文件的名 称,例如 bash hello_os.sh file hello_os.c,若已有 hello_os.c 文件,则将其原有 内容覆盖]

4、补全后的 palindrome.c、Makefile、hello_os.sh 依次复制到路径 dst/palindrome.c, dst/Makefile, dst/sh_test/hello_os.sh [注意:文件名和路径必须与题目要求相同]

  1. .c文件得到可执行文件:gcc -o palindrome palindrome.c
  2. 提取AAA文件的第8行到BBB文件中:sed -n '8p' AAA > BBB (安静模式,且仅输出不编辑)

Exercise 0.2

Lab0 第二道练习题包括以下一题,如果你完成且正确,即可获得 12 分。

在 Lab0 工作区 ray/sh_test1 目录中,含有 100 个子目录 file1~file100,还存 在一个名为 changefile.sh 的文件,将其补完,以实现通过命令 bash changefile.sh, 可以删除该目录内 file71~file100 共计 30 个子目录,将 file41~file70 共计 30 个子 目录重命名为 newfile41~newfile70。[注意:评测时仅检测 changefile.sh 的正确性]

用shell删除叫做file70~file100的子目录:rm -r ./"file$a"($a是shell中的变量)

重命名filexxnewfilexxmv ./"file$a" ./"newfile$a"

让变量$a递增:let a=a+1

Exercise 0.3

Lab0 第三道练习题包括以下一题,如果你完成且正确,即可获得 12 分。

在 Lab0 工作区的 ray/sh_test2 目录下,存在一个未补全的 search.sh 文件, 将其补完,以实现通过命令 bash search.sh file int result,可以在当前目录下生成 result 文件,内容为 file 文件含有 int 字符串所在的行数,即若有多行含有 int 字符 串需要全部输出。[注意:对于命令 bash search.sh file int result,file 及 result 可为任何合法文件名称,int 可为任何合法字符串,若已有 result 文件,则将其原有内容 覆盖,匹配时大小写不忽略]

输出文件file中所有含有sign 字符串的行号到文件answer中:

1
2
3
4
5
touch helpfile #another file help me to finsh
grep -n sign file > helpfile
#print the number of line with "sign" and its content to helpfile
awk -F: '{print $1}' helpfile > answer
# 输出以":"为分隔符的第一个字符串

Exercise 0.4

Lab0 第四道练习题包括以下两题,如果你均完成且正确,即可获得 26 分。

1、在 Lab0 工作区的 csc/code 目录下,存在 fibo.c、main.c,其中 fibo.c 有点小 问题,还有一个未补全的 modify.sh 文件,将其补完,以实现通过命令 bash modify.sh fibo.c char int,可以将 fibo.c 中所有的 char 字符串更改为 int 字符串。[注意:对 于命令 bash modify.sh fibo.c char int,fibo.c 可为任何合法文件名,char 及 int 可以是任何字符串,评测时评测 modify.sh 的正确性,而不是检查修改后 fibo.c 的正确 性]

2、Lab0 工作区的 csc/code/fibo.c 成功更换字段后 (bash modify.sh fibo.c char int),现已有 csc/Makefile 和 csc/code/Makefile,补全两个 Makefile 文件,要求在 csc 目录下通过命令 make 可在 csc/code 目录中生成 fibo.o、main.o,在 csc 目录中 生成可执行文件 fibo,再输入命令 make clean 后只删除两个.o 文件。[注意:不能修改 fibo.h 和 main.c 文件中的内容,提交的文件中 fibo.c 必须是修改后正确的 fibo.c, 可执行文件 fibo 作用是输入一个整数 n(从 stdin 输入 n),可以输出斐波那契数列前 n 项,每一项之间用空格分开。比如 n=5,输出 1 1 2 3 5]

要求成功使用脚本文件 modify.sh 修改 fibo.c,实现使用 make 命令可以生成.o 文 件和可执行文件,再使用命令 make clean 可以将.o 文件删除,但保留 fibo 和.c 文件。

  1. file文件中的所有wrong字符串全部替换成correct字符串:

    1
    2
    sed -i "s/wrong/correct/g" file 
    #-i只编辑不输出 /g把每一个都这样替换,而不是仅仅每行第一个
    • main.c会调用fibo.c文件,预处理、编译、汇编、链接步骤如下:

      1. 预处理、编译、汇编

        fibo.c的头文件放在../include目录里面,则生成fibo.omain.oMakefile如下:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        #第一种写法:
        all: fibo main

        fibo: fibo.c
        gcc -E fibo.c -o fibo.i
        gcc -S fibo.i -o fibo.s
        gcc -c fibo.s -o fibo.o
        rm fibo.i
        rm fibo.s

        main: main.c fibo.o
        gcc -E main.c -o main.i -I ../include #Attention!
        gcc -S main.i -o main.s
        gcc -c main.s -o main.o
        rm main.i
        rm main.s

        #第二种写法(精简):
        all: fibo main

        fibo: fibo.c
        gcc -c fibo.c

        main: main.c fibo.o
        gcc -c main.c -I ../include #Attention!
      2. 链接

        生成可执行文件Main如下:

        1
        gcc fibo.o main.o -o Main
    • csc 目录下通过命令 make 可在 csc/code 目录中利用csc/code/Makefile生成 fibo.omain.o,在 csc 目录中 生成可执行文件 fibo,再输入命令 make clean 后只删除两个.o 文件:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      all: fibo

      fibo:
      cd code && make #一定先cd,再make
      gcc ./code/fibo.o ./code/main.o -o fibo

      clean:
      rm ./code/fibo.o
      rm ./code/main.o

      【Attention:在 Makefile 中 cd 到其他目录,这个 cd 只能有效于当前一行,故而必须使用 “&&” 连接要在 cd 目录下的指令,写在同一行,同时不需要 cd …/ 回来】

实验分析

写下实验过程中的体会。

​ 本次实验我参考了一些学长学姐的blog,协助理解几种不同工具的使用,在这里引用Hyggge学长的一幅图,也是我认为几点对我来说有难度或者不熟悉的知识点:

difficulty

​ 虽然Lab0课下实验的难度不大,但是仍然有许多小细节,具体我写在难点分析中了,课下实验总共花费了15个小时左右,中途也查询了许多资料,并且向同学大牛们请教颇多。

​ lab0-extra 我最后一个有关diff的操作错误了,正确代码应该是:

diff

​ 我错在写的if [ $? -eq 0 ] Shell 中,对空格非常敏感,一定要在规定的不同符号间加空格,同时,在Shell中 0 表示真 , 1 表示假!!与正常的编程语言相反!

​ OS的实验课仍然是道阻且长。

课上测试

​ 本次课上测试,我的lab0-extra只得了75分,反思确实是自己的相关知识点掌握不到位,因此我觉得是毫无怨言的。

​ 但是稍微有些可惜的是,我和100分失之交臂的点:按照我原本的性格习惯,对于$?的返回值条件为1或0(后面会具体讲解),无论怎样我都会尝试一下两种情况的两种结果,但是,在考场上的时候,由于紧张和着急,我没有选择符合之前习惯的做法,其实只要我尝试一下,就是可以满分的,对此感到些许可惜,故而反思到——考场上的心态和冷静依旧是我要培养的点。

​ 通过课后老师的讲解,和与其他同学的交流【主要是笨蛋的我向大牛们请教哇~】,可以发现lab0的课上测试,在examextra里面各有一个点卡着大家,这两点甚至老师也要思索一二才能想通,一下具体阐述:

lab0-exam

1
2
3
4
5
6
n=10
while [ $n -gt 0 ]
do
echo $n
let n=n-1
done

​ 上面这段程序在本地运行的时候是完全正确的,但是一旦提交到评测机上就会报错,原因是:

  • ​ 1. 在let语句中,如果=右边的结果变成小于或等于0的数,那么该let语句的返回值$?的值就会变成1;

    ​ 2. 而在bash中,整个程序的返回值$?=最后一条语句的返回值$?

    ​ 3. 且在评测机中一旦程序的返回值$?为1,它就认为这个程序报错了;

    ​ 故而,上述程序最后的返回值$?就是1,则报错。

  • 可能的修改方式:

    • 第一种方式:

      1
      2
      3
      4
      5
      6
      7
      n=10
      i=1
      while [ $i -le $n ]
      do
      echo $i
      let i=i+1
      done
    • 第二种方式:

      1
      2
      3
      4
      5
      6
      n=10
      while [ $n -gt 0 ]
      do
      echo $n
      n=$((n-1))
      done
    • 第三种方式:

      1
      2
      3
      4
      5
      6
      7
      n=10
      while [ $n -gt 0 ]
      do
      echo $n
      let n=n-1
      done
      exit 0

lab0-extra

diff

  • diff A B发现A和B有不同,那么该语句的返回值$? -eq 1 ,并且会输出一定的文字;当A和B完全一样的时候,那么该语句的返回值$? -eq 0 ,且不会有任何输出。

  • 题目代码为:

    1
    2
    3
    4
    5
    6
    7
    diff $1 $3 > /dev/null
    if [ $? -eq 1 ]
    then
    echo different
    else
    echo same
    fi

$? $#

  • $?表示上一条语句的返回值
  • $#表示传参个数