OS-Lab0-课下

Dracary 发布于 2026-03-11 236 次阅读


Lab0课下的基础教程,比较简单,主要分为四个部分:

  • Exercise0.1
  • Exercise0.2
  • Exercise0.3
  • Exercise0.4

Exercise0.1

第一小问是C语言基础编程的考察,我的思路是把整数n的各个位置上的数字取出存入数组中,然后在数组中从首尾至中间进行比较即可

int flag = 1;
if(n<10)flag=1;
else{
    int arr[10]={0},cnt=0;
    while(n){
        arr[cnt++]=n%10;
        n/=10;
    }
    int s_cnt=0;
    cnt--;
    while(s_cnt<cnt){
        if(arr[s_cnt]==arr[cnt]){
            cnt--;s_cnt++;
        }else{
            flag=0;
            break;
        }
    }
}   
if (flag) {
    printf("Y\n");
} else {
    printf("N\n");
}  

第二小问考察的知识点是Makefile,本身也不难,要求在该目录下使用make即可进行编译,那么第一个构建的目标就是palindrome

palindrome: palindrome.c
            gcc palindrome.c -o palindrome

第三小问考察的是linux shell的基础知识点,只要熟练掌握shell语法即可

首先是对于文件特定行的查看,可以使用

sed -n "1p" filename

其中sed默认输出每一行,而-n代表关闭默认输出,-p代表打印对应的行数(补充:"1,3p"表示打印1至3行,"1p;3p;5p"表示打印1,3,5行)

其次是第四小问,考察shell脚本的相关知识点,假设我们执行命令行./script.sh AAA BBB,那么./script.sh就是$0AAABBB依次是$1$2

所以在script.sh中,我们使用$1就可以代表AAA$2代表BBB

sed -n "8p;32p;128p;512p;1024p" "$1" > "$2"

其中>表示重定向,把原本要输入到终端屏幕的标准输出改成输出到指定文件中,每次就覆盖内容,而>>表示追加内容不覆盖

最后就是文件的复制,我们使用cp -r source dst其中-r表示递归复制

cp -r ~/12345678/src/* ~/12345678/dst/

其中我使用的是绝对路径

Exercise0.2

考察shell的基本语法,在shell脚本中,我们可以定义

a=1

后续访问具体数值时我们需要使用$a

为了访问1至100的所有数值,我们使用循环while

while [ $a -le 100 ]
do
      a=$((a+1))
done

也可以使用for循环

for((a=1;a<=100;a++))
do
    continue
done

如果需要使用条件判断if我们可以使用

if condition
then
    comand1
    comand2
    ......
elif condition
then
    command1
elif
then
    commmand1
else
    command1
done

其中ifelif都需要紧跟then,而else则不用

创建文件时我们使用

mkdir filename

删除文件时我们使用

rm -rf filename

修改文件名时我们使用

mv filename_old filename_new

所以我们可以写出循环内部的逻辑

if((a>70)) #or [ $a -gt 70 ]
then
    rm -rf "file$a"
elif((a>40)) #or [ $a -gt 40 ]
then
    mv "file$a" "newfile$a"
done

补充一些细节:

  • [ $a -gt 70 ]首尾要留空格,不然会报错
  • bash中可以使用((condition))进行条件判断,如果条件为真,返回0,否则返回1
  • bash中可以使用$((expression))进行算术运算,比如已知a=1,执行b=$((a+1)),可以得到b=2,如果执行b=a+1,可以得到b=a+1,也即shell不会自动解析变量名字

Exercise0.3

本题前置知识点grep

grep -n "int" filename

表示搜索文件filename中含有字符串"int"的行,-n表示输出行号

更多地,如果后面是一个文件夹,可以使用-r表示递归搜索文件,有时我们也使用-R表示同时也搜索子文件夹中的链接目录

前置知识点cut

假设我们使用grep -n "echo" msg.sh得到

2:      echo "$1"
3:      echo "$2"
4:      echo "the number of parameters is $#"

但是我们只想要得到前面的行号,可以这样

grep -n "echo" msg.sh | cut -d: -f1

管道|代表把上一个命令的输出作为下一个命令行的输入,cut则会切割输入,-d:表示按照:进行切割,-f1表示只取第一列的结果(基数从1开始),而-f1,3表示取第1列和第三列,-f1-4表示取1至4列

所以我们最后可以得到

grep -n "$2" "$1" | cut -d: -f1 > "$3"

或者我们也可以使用awk

grep -n "$2" "$1" | awk -F: '{print $1}' > "$3"

这里awk的用法中,-F:表示按照:拆分行,后续的$0 $1 $2分别代表整行、第一列、第二列,以此类推

此外值得注意的是这里建议使用单引号,如果使用双引号,那么shell脚本会先解析$1,如果你先前没有定义,那么实际传入awk的是print , 从而打印整行

Exercise0.4

第一部分要求我们使用命令行对文件进行修改,推荐使用sed

前面我们说过sed -n或者sed都只会在终端输出,没有改变原文件,要改变原文件,我们可以使用-i表示重定向输出到原文件,也就是覆盖

此外,我们还要使用"s/str1/str2/"进行操作,表示替换每行中的第一个str1str2,如果是"s/str1/str2/g"表示替换全部,如果是"s/str1/str2/p"对于每一行,如果发生替换就打印

于是我们得到

sed -i "s/$2/$3/g" "$1"

第二部分是对于Makefile的进一步操作

all:
    make -C filedir

表示进入filedir中进行make操作,等价于

cd filedir
make

于是我们得到外层csc/Makefile

all:
    make -C code
clean:
    make -C code clean

对于内层code/Makefile

all: fibo

fibo: fibo.o main.o
    gcc fibo.o main.o -o ../fibo

fibo.o: fibo.c
    gcc -I ../include -c fibo.c

main.o: main.c
    gcc -I ../include -c main.c

clean:
    rm -rf fibo.o main.o

这里补充几点:

每次执行make时,每当执行到:

all: fibo

make会检查./fibo,但是我们实际生成的是../fibo,系统无法找到,所以该命令行每次都会执行

所以可以这样写

all: ../fibo

../fibo: fibo.o main.o
    gcc fibo.o main.o -o ../fibo

建议target必须与生成文件一致

target: dependencies
        command

此外需要注意的是command前面一定是tab不能使用空格代替,本文中为编辑方便不保证command前面都是tab

最后补充一下gcc -I ../include意思就是指定头文件搜索路径,因为通常GCC只会找当前目录和系统头文件目录(/usr/include),我们通常要给它指定额外的路径,这里再补充一下,在Makefile-I的基准目录就是Makefile所在的目录,因此后面可以跟相对路径

此外,值得注意的是gcc -c file.c将生成object module也就是*.o文件,而gcc -S file.c将生成assembly code也就是*.s文件,gcc -E file.c只执行预处理,输出预处理结果(可保存为*.i文件)

GCC 实际有四个阶段:

file.c
  ↓ 预处理 (-E)
file.i
  ↓ 编译
file.s
  ↓ 汇编
file.o
  ↓ 链接
a.out

这里是紫罗兰的永恒花园
最后更新于 2026-03-23