文章

BUAA-OS Lab0

lab0

Lab 0 主要就是一个 Makefile 和 Linux shell 的练习。你可以从这里获取今年实验的公开指导书(截至发稿时的版本,存于互联网档案馆)。

练习题

Exercise 0.1

好久没写 C。虽然连 palindrome 都不会写了,但是好像懂得比以前多了很多)

剩下 3 问没什么难度。唯须注意的是:

[Makefile 中] 有一点尤为需要注意,每一个命令 (command) 之前必须用一个制表符(Tab)缩进。这里必须使用制表符而不能是空格,否则 make 会报错。

考试的时候被坑了。

Exercise 0.2

Shell 的条件和循环。

a=1
while [ $a -le 100 ]
do
        if [ $a -gt 70 ]
        then
                rm -r "file$a"
        elif [ $a -gt 40 ]
        then
                mv "file$a" "newfile$a"
        fi
        # ((a++))
        a=$((a+1))
        # don't forget change the loop variable
done

Exercise 0.3

# First you can use grep (-n) to find the number of lines of string.
# Then you can use awk to separate the answer.
 
grep -n "$2" "$1" | cut -d: -f1 > "$3"

cut -d 后面是分隔符,-f1 是第一个字段,即行号。

Exercise 0.4

./csc/code/modify.sh
sed -i "s|$2|$3|g" "$1"

需要 include 头文件。

./csc/code/Makefile
all:
        bash modify.sh fibo.c char int
        gcc -c fibo.c main.c -I../include
思考题Thinking 0.1Git 的使用 1执行命令 cat Untracked.txt 和 cat Stage.txt,对比两次运行的结果,体会 README.txt 两次所处位置的不同。对比两者的输出,可以看到 README.txt 从 Untracked files 列表中移动到了 Changes to be committed 列表中。执行命令 cat Modified.txt,观察其结果和第一次执行 add 命令之前的 status 是否一样,并思考原因。当前的 status 显示 README.txt 处于 “Changes not staged for commit” 并且是 modified 状态,这意味着在 README.txt 被添加到暂存区之后内容又被修改了,但修改还没有被添加到暂存区。Thinking 0.2箭头与命令图 1 Git 中的四种状态转换关系仔细看看图 1,思考一下箭头中的 add the file、stage the file 和 commit 分别对应的是 Git 里的哪些命令呢?•add the file 和 stage the file 对应的是 git add 命令;•commit 对应的是 git commit 命令。Thinking 0.3Git 的一些场景1.代码文件 print.c 被错误删除时,应使用什么命令将其恢复?git checkout print.cShell2.代码文件 print.c 被错误删除后,执行了 git rm print.c 命令,此时应当使用什么命令将其恢复?git restore print.cShell3.无关文件 hello.txt 已经被添加到暂存区时,如何在不删除此文件的前提下将其移出暂存区?git reset hello.txtShellThinking 0.4Git 的使用 21.使用 git log 命令查看提交日志,看是否已经有三次提交,记下提交说明为 3 的哈希值。538d89392bb30646faeaf5823be2f16006f5fe881.进行版本回退。执行命令 git reset --hard HEAD^ 后,再执行 git log,观察其变化。HEAD^ 代表当前的前一个版本(提交 2)。git log 观察提交记录,3 版本的提交会消失。1.找到提交说明为 1 的哈希值,执行命令 git reset --hard 后,再执行 git log,观察其变化。当前 HEAD 指向了版本 1。1.现在已经回到了旧版本,为了再次回到新版本,执行 git reset --hard,再执行 git log,观察其变化。发现 3 版本恢复,版本历史回到了最新状态。Thinking 0.5echo 的使用git@2xxxxxxx ~# echo firstShellfirstgit@2xxxxxxx ~# echo second > output.txtgit@2xxxxxxx ~# cat output.txtsecondgit@2xxxxxxx ~# echo third > output.txtgit@2xxxxxxx ~# cat output.txtthirdgit@2xxxxxxx ~# echo forth >> output.txtgit@2xxxxxxx ~# cat output.txtthirdforthgit@2xxxxxxx ~#> 将 stdout 写入到文件中,如果文件不存在则创建,如果文件存在则覆盖,相当于 fopen() 的 w(write)模式;>> 将 stdout 追加到文件中,如果文件不存在则创建,如果文件存在则追加,相当于 fopen() 的 a(append)模式。Thinking 0.6文件的操作使用你知道的方法(包括重定向)创建下图内容的文件(文件命名为 test),将创建该文件的命令序列保存在 command 文件中,并将 test 文件作为批处理文件运行,将运行结果输出至 result 文件中。给出 command 文件和 result 文件的内容,并对最后的结果进行解释说明(可以从 test 文件的内容入手)。testShell1echo 'echo Shell Start...2echo set a = 13a=14echo set b = 25b=26echo set c = a+b7c=$[$a+$b]8echo c = $c9echo save c to ./file110echo $c>file111echo save b to ./file212echo $b>file213echo save a to ./file314echo $a>file315echo save file1 file2 file3 to file416cat file1>file417cat file2>>file418cat file3>>file419echo save file4 to ./result20cat file4>>result' > commandcommandShell132231435261具体实现的过程中思考下列问题:1.echo echo Shell Start 与 echo `echo Shell Start` 效果是否有区别;2.echo echo $c>file1 与 echo `echo $c>file1` 效果是否有区别。1.echo echo Shell Start 会输出 echo Shell Start,而 echo `echo Shell Start` 会输出 Shell Start。这是因为被 ` ` 包围的字符串会被当成命令先执行,然后将结果作为参数传递给外部命令;而前者则是将后面的三个单词(echo、Shell、Start)作为参数传递给 echo 命令。2.•第一个命令调用外层的 echo 命令,其参数为字符串 "echo" 和变量 $c 的值,同时整个命令的标准输出被重定向到文件 file1。文件 file1 中会写入 echo 与变量 $c 的值使用空格拼接的字符串。•第二个命令先执行被 ` ` 包围的 echo $c>file1,即将变量 $c 的值写入文件 file1,然后将结果作为参数传递给外部的 echo 命令。由于 ` ` 内的命令反回值为空,所以最终的结果是 file1 中只有变量 $c 的值,而终端上没有输出。难点分析1.Makefile 调用子目录下的 Makefile:$(MAKE) -C subdir。2.sed 替换文本时可使用不同的分隔符,如 sed 's|/|\\|g'。3.bash 里从完整路径提取不含扩展名的文件名:1filename=${file##*/}Shell2${filename%.*}实验体会虽然平时对 Git 略有涉猎,但本次实验让我对 Git 的基本操作有了更深入的理解,学会了以前没遇到过的情况。同时,通过文件的操作部分,我也复习了 Shell 脚本中重定向、调用命令等操作。这对于后续实验的进行想必会有很大的帮助。

lab0-exam

GCC & Makefile Quiz

完成初始化后,仓库根目录下已经生成了 Makefile、check.c、src 文件夹和 out 文件夹。

在仓库根目录(如 ~/23xxxxx )下编写 Makefile。要求实现的功能如下:

执行命令实现功能
make check利用 gcc 将同目录下的 check.c 编译成名为 check.o 的未链接的目标文件,并放在同目录下。
make完成 make check 要求的功能。然后利用 gcc 将 src 下的 main.c、output.c 编译成名为 main 的可执行文件,并放在 out 目录下。
make run直接运行可执行文件 out/main。
make clean删除目标文件 check.o、可执行文件 out/main。

GCC & Bash Quiz

完成初始化后,仓库根目录下已经生成了 exam_1.sh 至 exam_9.sh(从1开始的连续整命令名的.sh文件,共9个)、run_exam.sh、stderr.txt 和 origin 文件夹。

在仓库根目录(如 ~/23xxxxx )下编写 exam_1.sh 至 exam_9.sh。要求实现且仅实现以下第x点功能。

这些脚本将被 run_exam.sh 调用执行。使用 run_exam.sh 的命令格式为 bash run_exam.sh [n] [s] [t],其中 n 为小于等于9 的整数,表示将按顺序执行 exam_1.sh 至 exam_n.sh。若 n 未给出,将默认是 9。可选的 s 和 t 用于传递给 exam_9.sh,具体要求见第 9 点功能。(注意:根据命令格式,若要指定 s 和 t,必须先指定 n)

这个部分讨厌的是评测点是累进的,由于后面的操作依赖于前面的操作,所以如果前面的操作没有正确实现,写完提交一看才十几分比较虚。不过文件操作的话,后面的操作可以作为前面的提示。

  1. 创建一个新的目录,名为 result。再在 result 目录下创建两个新的目录,名为 code 和 backup。

    exam_1.sh
    mkdir result
    mkdir result/code
    mkdir result/backup
  2. 将 origin 目录下的 basic.c 的文件中包含 hello(区分大小写)的行输出。

    exam_2.sh
    grep "hello" origin/basic.c
  3. 将 origin 目录下的 basic.c 文件移动到 result 目录下。

    exam_3.sh
    mv origin/basic.c result/basic.c
  4. 将 origin 目录下的 code 目录及其内容复制到 result/backup 目录下。

    exam_4.sh
    cp -r origin/code result/backup/code
    cp origin/code/* result/backup/

    不知道具体要求的是哪一种,似乎第一次尝试时没过评测。

  5. 将 origin/code 目录下的 0.c 1.c 2.c …… 20.c(从0开始的连续整数命名的 .c 文件,共21个)文件中的所有 REPLACE(区分大小写)替换为文件名(不含扩展名),替换的结果保存到 result/code 目录下的同名文件中。

    如对于这样的 origin/code/1.c:

    int main() {
        return REPLACE;
    }

    替换的结果如下,并且这个结果保存在 result/code/1.c 中:

    int main() {
        return 1;
    }

    这里麻烦的是如何从路径提取不含后缀的文件名。之前打 Hackgergame 的时候研究过一番 shell 字符串处理(欠了两年题解没写:),但是都忘了。是次考前从图书馆借了两本 Linux Shell 编程的书,从例子部分偷到了用法。

    cover
    Linux Shell命令行及脚本编程实例详解(第2版)book2024ISBN 9787302660194
    by 刘艳涛、
    出版社:清华大学出版社

    《Linux Shell命令行及脚本编程实例详解(第2版)》是获得大量读者好评的“Linux典藏大系”中的经典畅销书《Linux Shell命令行及脚本编程实例详解》的第2版。本书第1版累计13次印刷,销量超过2万册,被ChinaUnix技术社区大力推荐。本书理论结合实践,全面、系统地介绍Linux Shell(Bash)脚本编程的语法、命令和技巧等内容。本书偏重于实践,在讲解理论知识时结合大量典型实例让读者了解理论知识在实际环境中的应用,并对易混淆和较难理解的知识点做了重点分析,以加深读者对知识的理解。本书提供教学视频、实例源程序、思维导图、教学PPT和习题参考答案等超值配套资源,以帮助读者高效、直观地学习。 《Linux Shell命令行及脚本编程实例详解(第2版)》共15章,分为2篇。第1篇“Linux Shell基础知识与命令”,主要内容包括Linux和Linux Shell简介、初识Linux Shell、常用的Shell(Bash)命令、Shell命令进阶;第2篇“Shell脚本编程”,主要内容包括Shell编程基础、Shell的条件执行、Bash循环、Shell函数、正则表达式、脚本输入处理、Shell重定向、管道和过滤器、捕获、sed和awk、其他Linux Shell概述。 《Linux Shell命令行及脚本编程实例详解(第2版)》非常适合初次接触Linux Shell命令行和脚本编程的入门读者阅读,也适合有一定基础而想进一步提升的进阶读者阅读,还适合作为高等院校和Linux培训机构的教材。对于基于Linux平台的开发人员而言,本书还是一本不可多得的案头查询手册。 刘艳涛,就职于一家全球500强通信公司,从事公司无线产品研发中心的Linux/Unix操作系统的管理和技术支持。有超过15年的Linux系统管理与运维经验,擅长用Shell等脚本语言实现自动化运维管理,以及配置Nagios与Ganglia集成的自动化监控和故障报警平台,对Linux系统性能优化有深入的研究。

    第 104 页
    exam_5.sh
    for file in `ls origin/code/*.c`
    do
        filename=${file##*/}
        # echo $filename
        # echo ${filename%.*}
        sed "s/REPLACE/${filename%.*}/g" $file > "result/code/${filename}"
        # sed 's/REPLACE//g' $file >
    done
    • 从开头删除最短匹配的模式:var#
    • 从开头删除最长匹配的模式:var##
    • 从结尾删除最短匹配的模式:var%
    • 从结尾删除最长匹配的模式:var%%

    用 basename 的话,$(basename "$file" .${file##*.})。

  6. 将 result/code 目录下的全部 .c 文件一起编译为可执行文件 result/verify。

    exam_6.sh
    gcc result/code/*.c -o result/verify
  7. 运行可执行文件 result/verify,将其标准错误输出的内容追加到仓库根目录下的 stderr.txt 文件。

    exam_7.sh
    ./result/verify 2>>stderr.txt
  8. 将 stderr.txt 文件的权限修改为 r--r-----。

    exam_8.sh
    chmod 440 stderr.txt
  9. run_exam.sh 以 bash `exam_9.sh [s] [t]` 的格式向 exam_9.sh 传入两个参数 s, t(整数且 s < t)。

    • 两个参数缺省时,输出 stderr.txt 的所有内容。
    • 仅缺省 t 时,输出 stderr.txt 自行开始(行号从 1 开始编译,输出自第 s 行)至结尾的内容。
    • 两个参数指定时,输出 stderr.txt 自第 s 行至第 t 行的内容(输出包含第 s 行,不含第 t 行)。
    exam_9.sh
    if [ -n "$1" ]; then
      if [ -n "$2" ]; then
        # echo "a"
        # echo "$(($2 - 1))"
        sed -n "$1,$(($2 - 1))p" stderr.txt
      else
        # echo "b"
        sed -n "$1,\$p" stderr.txt
      fi
    else
      cat stderr.txt
    fi

    这块需要需要注意的是,sed 的 p 命令打印的行数从 1 开始,且包含结束行。head 和 tail 组合也可以,但是仍然需要 。

提示

  • 下发文件中包含一个初始化脚本 init.sh,如果你想将你的工作目录下除了 Makefile 和 exam_1.sh 至 exam_9.sh 之外的所有文件恢复到题目下发时的状态,可以使用命令 bash init.sh 执行该脚本。
  • 将多个文件一起编译,可以借助通配符 *。如强制删除当前目录下的所有扩展名为 .txt 的文件可以使用 rm -f *.txt。

参考输出

使用下发的 init.sh 初始化后,执行 make 后再执行 make run 的参考结果为:

See also

  1. BUAA-OS Lab0 实验总结 - 北航操作系统 | Test Blog
  2. BUAA OS Lab0 - 鹿杂物阁
  3. BUAA OS——Lab0实验报告 - Fight扬尘 - 博客园
  4. 北航操作系统课程lab0实验报告 - 南风北辰 - 博客园
  5. BUAA-OS-2023-Lab0-Report | sin (cookedbear.top)
  6. 【BUAA-OS】lab0_linux基础

评论

评论将在审核后显示,阁下可以在本博客的 GitHub 仓库的 拉取请求列表 中查看。提交成功后会自动跳转。

本站不支持 Dark Reader 的暗色模式,请对本站关闭后再访问,亮色模式的对比度、亮度等选项不受影响。部分页面右上角提供暗色模式切换按钮,如果你没看到,说明你的浏览器尚不支持此特性。本提示不依赖于 JavaScript,你可自行查找其他用户在本站发表的关于如何关闭此提示的评论。