前言
之前安装的ubuntu由于在各种各样的帖子引导下改动了太多配置文件,导致安装tools时总是安装失败,今天抽了一下午的时间又重新装了一遍ubuntu20.04,安装成功,可喜可贺!
ubuntu install
ubuntu的安装已经轻车熟路了,在此主要记录下一些关键步骤和遇到的问题。
-
刚安装好的ubuntu20.04没有网络,重新启动电脑后解决。
-
安装过程太慢可直接skip,进入ubuntu系统后,首先换源,可选aliyun,然后再进行软件更新
- 安装vmware tools,tar zxvf 将压缩包解压,进入文件夹,执行 ./vmware-install.pl程序,便可自适应大小和主机文件拖拽
tools install
打开terminal,执行
sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu
克隆实验源码
git clone git://g.csail.mit.edu/xv6-labs-2021
进入源码文件夹,发现没有文件,切换到util分支,测试安装
cd xv6-labs-2021
git checkout util
make qemu
输出如下,说明安装成功
# ... lots of output ...
init: starting sh
$
pointer exercises
#include <stdio.h>
#include <stdlib.h>
void
f(void)
{
int a[4];
int *b = malloc(16);
int *c; //注意:局部变量需要自己初始化,设为全局变量时编译器会自动帮你初始化。所以这里应为 int *c = NULL;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = (int *) ((char *) c + 1);
*c = 500; //指向从a[1]的后3个字节至a[2]的前一个字节的地址,所以会影响a[1]a[2]的值
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int
main(int ac, char **av)
{
f();
return 0;
}
运行结果:
Q1:
3[c]也修改了a[3]的值?
A1:
c语言语法允许使用逆序的下标,因为数组元素的访问是通过指针运算实现的,在内部它们都被翻译成*(c + 3)。所以c[3]和3[c]是等价的。
preparation
fork
创建一个子进程,拷贝创建时父进程的内存(指令和数据),所以子进程也会执行下方代码。返回子进程的pid,在子进程中返回0。
注意:二者内存不同,寄存器不同,只是创建时拷贝的内容相同,故在子进程修改变量不会影响父进程该变量
int pid = fork();
if(pid > 0){
printf("parent: child=%d\n", pid);
pid = wait((int *) 0); //等待子进程结束返回子进程pid,拷贝退出状态到传入的地址中,0表示父进程不关心结束状态
printf("child %d is done\n", pid);
} else if(pid == 0){
printf("child: exiting\n");
exit(0); //结束当前进程
} else {
printf("fork error\n");
}
an output
parent: child=1234
child: exiting
parent: child 1234 is done
redirect
0,1,2是console默认文件描述符
0代表标准输入,1代表标准输出,2代表标准错误输出
〉tmp1 将标准输出重定向到tmp1
2>&1将标准错误输出重定向到标准输出,即重定向到tmp1
故二者顺序不能颠倒
ls existing-file non-existing-file > tmp1 2>&1 #将存在的文件名和不存在文件的错误信息都输出到tmp1中