NJU-ICS|PA0

Installing Linux

最恶心的装虚拟机来咯,首先需要下载 Ubuntu 22.03 的镜像,官网下载即可。

之后通过 VMWare 来进行虚拟机的安装,这里直接通过典型的安装步骤即可,网上很多,这里不再记录归档。

遇到的问题

针对 VMWare 不能全屏幕显示的这个问题,主要是需要安装 VMWare Tools,但是在按照官方的文档配置安装的过程中爆出了 segementation fault 的错误选项,这里查询到了几种解决方案。

VMWare tools 安装以及一些常见错误

踩坑

值得注意的是官方的讲义中明确指出了第一次进去的时候弹出更新软件包的窗口,要求不要让我们更新软件包,否则之后将以的操作会产生冲突,我们这里严格按照要求来就好了。

至于如何永久关闭软件包的更新,这里按照这个配置来即可

First Exploration

这部分就是简单的一个初体验快速上手我们的 Linux,如果你之前有过Linux操作的经验应该不是问题。

同时还强调了 CLI 相较于 GUI 的优势, vim 为何是编辑器之神 XD。

Installing Tools

按照文档来即可 Installing Tools

解决 Unable to Correct Problems ‘You have Held Broken Packages

在英文的 Linux 系统中安装中文输入法

当我们通过 fcitx 下载了最新的 sunpinyin 语言包之后,就可以进入到左上角小键盘右键的 configure 选项卡中进行追加中文输入法了,但是保持系统语言还是英文。

之后重启/注销即可生效。

Configuring vim

Learning vim

为什么 vim 是神?因为他确实太好用了。

讲义中给出了很多推荐的 tutorial 这边我采用的是这个 Open Vim Tutorial

这边简单进行记录和总结,具体还是需要多实战练习。

  • 基本移动

    • h 左,j 下,k 上,l 右。
    • w 表示光标移动到下一个 word 的开头,e 表示光标移动到这个单词的结尾(end),b 表示移动到这个单词的开头(begin)。
    • 移动操作不仅包括一次移动一格,同时也包括了一次移动倍数格,可以通过组合键的形式进行移动,例如 3w 就是移动三个 word。
    • 同时倍数的操作也可以用于插入,我们都知道插入操作是 i 这个按键,也可以进行组合,比如 3igo + esc 表示我们在普通模式下进入插入模式写三个 go 之后再退回普通模式。
    • 0 返回这一行的开头,$ 移动到这一行的末尾。
    • gg 移动到文件的开头,G 移动到文件的末尾,如果要定位第几行,用 nG。
  • 查询

    • 通过 f 来进行查询某个字母第一次出现的位置并定位。
    • 也可以配合数字倍数进行查询第 n 次出现的位置。
    • 通过 % 可以匹配对应的各种括号。
    • # 可以查询并移动到当前下标所指单词的下一个位置,* 起到反作用。

Enabling syntax highlight

这一部分主要是让我们修改一下 vim 的配置文件来开启文本高亮的显示,修改不是问题,主要在这个过程中学到了 GNU 合并格式的 diff 的这么一个阅读方式,收益很大。

关于 diff 的语法格式这里可以参考 阮一峰 的博客:读懂diff - 阮一峰的网络日志

(说白了其实就是把 syntax on 给他注释了的开起来)

1
2
3
4
5
6
7
--- before modification
+++ after modification
@@ -17,3 +17,3 @@
" Vim5 and later versions support syntax highlighting. Uncommenting the next
" line enables syntax highlighting by default.
-"syntax on
+syntax on

具体解释一下就是,diff 中的 - 表示的是修改前的文档, + 表示的是修改后的文档,第三行的意思是两次修改分别都是在 第一个/第二个文件的第 17 行处进行的修改,同时都只展示三行的内容合并显示。

More Exploration

man 命令

man 命令可以说是 GNU/Linux 系统中最重要的一个命令了,因为他是其他所有命令的说明书一般的存在,这里有man 命令的快速上手教程,可以稍微了解一下,学会最基本的 RTFM 即可。

Linux 快速上手

这边有 jyy 老师的Linux快速上手指南

综合体验

hello world

Write a “Hello World” program, compile it, then run it under GNU/Linux. If you do not know what to do, refer to the GNU/Linux tutorial above.

1
2
3
4
5
6
#include <stdio.h>
int main()
{
printf("Hello World\n");
return 0;
}

test

makefile

Write a Makefile to compile the “Hello World” program above. If you do not know what to do, refer to the GNU/Linux tutorial above.

这块的话其实还是第一次写 makefile ,这边稍微看了一下文档进行记录。

最简单的demo

基于我们上面写的 hello.c 我们可以针对他做出如下的 Makefile demo:

1
2
3
4
5
6
7
hello:hello.c
gcc hello.c -o hello # 注意开头的tab, 而不是空格

.PHONY: clean

clean:
rm hello # 注意开头的tab, 而不是空格

这个时候我们保存并键入 make 命令,可以看到 makefile 帮助我们进行了 gcc 的编译。

image-20221123221038058

makefile 语法

makefile文件的一般格式和语法如下:

1
2
目标文件名:该文件依赖的文件列表
用于生成这个目标文件的命令序列

比如上面这段 makefile :

1
2
hello:hello.c
gcc hello.c -o hello

意思就是我们想要生成 hello 文件,他依赖于 hello.c 这个源文件,而具体生成则是需要 gcc hello.c -o hello 这段命令序列。

上面例子中的 clean 规则比较特殊, 它并不是用来生成一个名为 clean 的文件, 而是用于清除编译结果, 并且它不依赖于其它任何文件。

我们需要键入 make clean 命令来告诉 make 程序执行 clean 规则, 这是因为 make 默认执行在 Makefile 中文本序排在最前面的规则. 但如果很不幸地, 目录下已经存在了一个名为clean的文件, 执行make clean会得到”文件已经是最新版本”的提示.。

为了解决这一个问题,我们在 Makefile 中加入一行 PHONY: clean , 用于指示 “clean是一个伪目标” 。

这样以后, make 程序就不会判断目标文件的新旧, 伪目标相应的命令序列总是会被执行

其他内容

对于一个规模稍大一点的工程, Makefile 文件还会使用变量, 函数, 调用Shell命令, 隐含规则等功能,希望能够 STFW.

Learn to us GDB

Read the GDB tutorial and use GDB following the tutorial.

In PA1, you will be required to implement a simplified version of GDB. If you have not used GDB, you may have no idea to finish PA1.

RTFM: GDB, The GNU Debugger, By Example

必要准备

首先需要编译你的源代码生成可执行文件,在编译的同时开启编译器警告,比如这里有一个 cpp 源程序:

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
#include<iostream>

using namespace std;

long factorial(int n);

int main()
{
int n(0);
cin>>n;
long val=factorial(n);
cout<<val;
cin.get();
return 0;
}

long factorial(int n)
{
long result(1);
while(n--)
{
result*=n;
}
return result;
}
1
g++ main.cpp -g -Wall -o main

之后直接通过 gdb 可执行程序名 即可进行调试:

1
gdb main

设置断点,运行中debug

通过 break linenumber 可以对源代码的指定行数进行断点设置。

由于是命令行,不像是 IDE 中当前位置一目了然,我们需要 list 命令来查看当前程序进行到哪一行了,这里会列出最近的十行程序。

next 命令走到下一行,而 step 命令有可能会走到源码里。

我们可以通过 print <var> 来对当前程序中的变量值进行检查,同时也可以通过 set <var> = <value>修改某个变量的值,这样也是便于调试,如果修改成功了说明问题已经被我们 debug 出来了。

记录程序变化

watch <var> 命令可以查看当前所有变量在运行时的修改情况,每当程序发生变化的时候程序都会提供详细的修改信息。

总结

事实上这个程序有 bug ,我们通过断点调试就可以看出来,这里手册上详细说出来了,这里就截图跑了一遍体验了一下。

初始化变量

多次执行查看watch的情况

找出最终问题所在

Installing tmux

tmux 顾名思义就是 Terminal Multiplxer 的简称,一般是给 有高分屏的富哥们 拿来同时操作多件事情用的。

具体的使用还得是 STFW.

讲义中的思考题提出了原先的 terminal 其实是不支持滚动的,为什么最早的终端不支持滚动显示?

此外 tmux 的滚动实现是怎样的?

如果想让终端可以进行滚动显示,应该如何处理?

Getting Source Code for PAs

init

这里由于是一台新的机器,因此 git 需要进行初始化,否则直接拉取讲义中的源码的时候会报错:git@github.com: Permission denied (publickey).

具体解决的方案 STFW.

之后我们就可以拉取代码了,代码其实是人家写好的 shell 脚本,我们直接运行即可。

1
2
3
git branch -m master
bash init.sh nemu
bash init.sh abstract-machine

脚本运行主要是拉取一下实验需要的其他的 git 代码仓库,同时也设置了一些环境变量,我们这里可以进行验证:

1
2
echo $NEMU_HOME # 执行 shell 脚本的目录下的 nemu 目录
echo $AM_HOME #执行 shell 脚本的目录下的 abstract-machine 目录

git review

本实验基于 branch 分支对每一次实验进行管理。一个分支对应一个 PA 的实验课。

1
git checkout -b pa0 #创建 Lab0 的专属分支

每一次差不多就是在 pa 的实验开始之前先建立一个分支,之后在这个分支上进行 Lab 的开发,开发完毕之后再合并到 master 主干分支中,这也是一般的开源项目中最常见的一种开发方式。

这里我们把原先的 git 仓库指向删除,改成自己的仓库,方便版本管理,STFW 之后得到其实本质就是修改 git 文件的引用即可。

Compiling and Running NEMU

make

讲义让我们直接进入 nemu 中进行编译构建,然后就报错了XD,具体原因我们直接 STFW.

可以看到似乎是有两个问题

  • 第一个是这个 bison 指令,好像是没有安装的样子
  • 第二个好像是 makefile 在执行的时候 27 行 parser.tab.h 的时候报错了,这里先不管他,因为可能是 bison 缺少导致的问题

我们这里先直接安装 bison 工具包:

1
sudo apt-get install bison

之后再次执行,发现还是爆了:

这次发现可能是 flex 的问题,这里我们去装 flex 试试:

1
sudo apt-get install flex

这次就可以了,原来是讲义没有引导我们安装 bison 和 flex 这两个构建项目必要的工具包。

此时我们进入到一个 GUI 中,这里按照讲义的要求先退出然后保存 configuration ,之后通过 make 编译。

如果想要清除构建重新编译的话,只需要 make clean 即可。

下面我们直接通过 make run 运行 NEMU:

出现了 assertion fail ,这个问题我们会在 Lab1 中进行修复,现在只是快速体验一下把环境搭建好。

思考题:为什么在 make 的时候会出现打印提示?

这是因为 makefile 其实本质就是一个构建用的脚本,讲义的作者为我们提供的 makefile 中加入了 if , echo xxx 等的语句用于错误/成功时的信息调试,便于我们快速定位问题所在。

turn off development tracing

因为我不是 NJU 的学生,为了保证 git 提交的整洁,这里先把开发跟踪关闭了,具体在讲义中也有提到。

Summary

实验进度

  • 完成了所有内容,其中包括基本环境搭建,学习了 vim gdb makefile 等具体使用。
  • 蓝框思考题已经在以上内容中。

针对 PA0 实验的心得

深刻体会了 RTFM / STFW 对于一个 CSer 的必要性。

中间的我忘了,后面的我也忘了。

废话不多说,PA1 启动。


NJU-ICS|PA0
http://example.com/2022/11/22/NJU-ICS-PA0/
作者
Noctis64
发布于
2022年11月22日
许可协议