MIT 6.S081 第一章问题记录
第一章问题记录
1.3之前
1.调用exec系统调用以后,exec调用的进程的内存空间会覆盖原来调用exec的进程内存空间吗
是的,当一个进程调用 exec 系列的系统调用时,调用进程的内存空间会被新程序的内存空间覆盖。具体来说,exec 替换了当前进程的映像,包括代码段、数据段和堆栈段,但保留了进程的标识符和一些其他属性(如打开的文件描述符)。
在调用 exec 后,原来的进程代码不再可用。新程序会从入口点开始执行,原进程的内存内容将在这个替换过程中消失。因此,exec 实际上是将当前进程的运行状态变更为新程序,而不是创建新进程。
2.linux的c语言的系统调用exec之后的代码都将不再执行?
是的,在 Linux 中使用 exec 系列系统调用后,当前进程的地址空间将被新的程序替换,之后的代码将不再执行。
具体来说,exec 调用会加载并执行一个新的可执行程序,而在调用 exec 之前的代码会被替换,进程的上下文(包括变量、状态等)也会改变。因此,一旦 exec 调用成功返回(注意,如果出错会返回 -1,并保留原进程的上下文),原来的代码就不会再被执行。
例如,调用 exec 系列函数之一(如 execl、execv 等)后,若新的程序启动成功,当前进程将继续执行新的程序,而不会返回到调用 exec 的地方。
1.3
*3.int p[2]; char argv[2]; argv[0] = “wc”; argv[1] = 0; pipe(p); if (fork() == 0) { close(0); dup(p[0]); close(p[0]); close(p[1]); exec(“/bin/wc”, argv); } else { close(p[0]); write(p[1], “hello world\n”, 12); close(p[1]); }实现了什么样的功能?
这段代码实现了一个简单的管道功能,将数据从父进程传递到子进程,并由子进程调用wc命令。具体来说,代码的功能可以描述如下:
- 创建管道:使用pipe(p)创建一个管道。p是一个整型数组,p[0]是读取端,p[1]是写入端。
- 创建进程:使用fork()创建一个新进程。
- 如果是子进程(返回值为0),执行以下操作:
- 关闭标准输入(close(0))。
- 将管道的读取端p[0]复制到标准输入(dup(p[0]))。
- 关闭管道的读取端(close(p[0]))和写入端(close(p[1]))。
- 使用exec()执行/bin/wc命令,传递参数数组argv,argv[0]是”wc”,argv[1]是0,表示没有额外的参数。
- 如果是父进程,执行以下操作:
- 关闭管道的读取端(close(p[0]))。
- 向管道的写入端p[1]写入字符串”hello world\n”(长度为12字节)。
- 关闭写入端(close(p[1]))。
- 如果是子进程(返回值为0),执行以下操作:
整体功能:
父进程将字符串 “hello world\n” 通过管道传递给子进程,子进程接收这段输入并通过 wc 命令来统计输入的行数、字数和字符数。具体来说,wc 会处理从管道中读取的数据并输出统计结果。
执行结果大致会是这样的:
4.grep fork sh.c | wc -l
这个命令由几个部分组成,下面是它们的解析:
grep fork sh.c:
- grep 是 Linux/Unix 系统下的一个文本搜索工具,用于查找包含指定模式的行。
- fork 是我们要搜索的模式(关键词)。
- sh.c 是要搜索的文件名,表示在这个文件中查找包含 fork 的所有行。
这个部分的作用是从 sh.c 文件中找出所有包含 fork 这个词的行。
| (管道):
- 管道符 | 用于将前一个命令的输出作为下一个命令的输入。在这个例子中,grep 的输出(即匹配到的行)将被传递给下一个命令 wc -l。
wc -l:
- wc 是一个用于统计字数、行数和字节数的工具。
- -l 选项表示统计行数。
这个部分的作用是计算从 grep 输出的结果中有多少行。
总结:
整个命令的功能是:在文件 sh.c 中查找包含 fork 的所有行,并统计这些行的数量。最终输出的结果是包含 fork 的行数。
5.将sh.c更改为不对p->left
进行fork
,并在内部进程中运行runcmd(p->left)
。然后,例如,echo hi | wc
将不会产生输出,因为当echo hi
在runcmd
中退出时,内部进程将退出,而不会调用fork
来运行管道的右端。这是什么意思
在Unix或类Unix操作系统的Shell中,当你运行一个命令时,比如 echo hi | wc,Shell 会创建一个管道(pipe)来连接这两个命令的输入和输出。在这种情况下,echo hi 是管道的左侧命令,wc 是右侧命令。
在原始的 sh.c 实现中,Shell 会使用 fork 来创建两个子进程:一个用于执行 echo hi,另一个用于执行 wc。echo hi 生成输出,通过管道传递给 wc,然后 wc 计算输入的行数、字数或字符数并输出结果。
重新设计的 sh.c 的要求是:不对 p->left(即左侧命令 echo hi)执行 fork,而是在当前进程中直接运行 runcmd(p->left)。这意味着 echo hi 的输出将不会通过管道传递到 wc,因为在该进程(内部执行的命令)完成后,将不会调用 fork 来启动右侧的 wc 进程。
结果是:
- echo hi 在当前执行环境中直接运行,并输出 “hi”。
- 由于没有对 p->right(即 wc)进行 fork,也就不会有 wc 进程启动,因此它不会执行,并且最终不会有输出。
因此,echo hi | wc 将不会产生预期的输出,因为 wc 从未被启动,完全是由于对左侧命令不使用 fork 带来的影响。
6.正常情况下,echo hi是父进程,wc是子进程?
在Unix/Linux系统中,通常情况下,echo hi 会被视为父进程,而 wc (word count) 是通过管道将数据传递给它的一个子进程。当你使用管道(例如 echo hi | wc -w)时,echo 命令会将输出发送到 wc 命令。在这个例子中:
- echo hi 是父进程,它生成输出。
- wc -w 是子进程,它接收父进程的输出并进行处理(在这个例子中计算单词数)。
因此,形成了一个父子进程的关系,数据流动是从父进程到子进程。
7.runcmd在Xv6的操作系统中是什么意思
在Xv6操作系统中,runcmd 是一个用于执行命令的函数。Xv6是一个教学操作系统,旨在帮助学生理解操作系统的基本概念。它是一个简化版的Unix操作系统,包含了许多基本的操作系统功能。
runcmd 通常在 shell 的实现中被使用,它的主要功能是解析用户输入的命令并执行相应的操作。具体来说,runcmd 可能包括以下几个步骤:
- 命令解析:将用户输入的字符串解析成可以识别的命令和参数。
- 查找命令:确定要执行的命令以及其所在的路径。
- 创建进程:根据需要创建新的进程来执行命令。
- 输入输出重定向:如果命令包含重定向操作(比如从文件读取输入或向文件写入输出),runcmd 还需要处理这些重定向。
- 执行命令:使用 exec 系列系统调用来执行解析的命令。
总体而言,runcmd 是Xv6中一个重要的部分,它负责将用户输入的命令转化为实际的系统调用,从而实现命令的执行。
1.4
8.shell的工作目录是bash了嘛
shell 指的是一个命令行界面,它允许用户与操作系统进行交互。在Linux和Unix系统中,bash(Bourne Again SHell)是最常用的shell之一。
当你打开一个终端时,默认的工作目录通常是当前用户的家目录(例如 /home/username)。你可以使用 pwd 命令查看当前的工作目录,使用 cd 命令来更改工作目录。