赞
踩
2.1.1 文件与目录操作
(1)显示文件目录名ls
ls命令运行如下图所示,显示主目录下文件目录名。
(2)改变当前目录命令cd
cd命令运行如下图所示,图中用以切换到桌面目录下的文件夹Test1中。
(3)建立子目录mkdir
在桌面的Test1文件夹中创建子目录Test2,并用cd命令进入Teste2验证。
(4)删除子目录命令rmdir
通过cd .. 命令返回上一级目录(Test1),利用rmdir命令删除其子目录Test2,再次通过cd命令试图进入,显示没有Test2这个目录,删除成功。
(5)删除文件命令rm
通过“文本编辑器”在Test1目录下创建“1.txt”文件,如下图所示。
此时,通过find命令可以查找到该文件。我们再利用rm命令删除文件,再次通过find命令没有查找到此文件,证明已经删除成功。
(6)文件改名命令mv
通过“文本编辑器”在Test1目录下创建“yuan.txt”文件,如下图所示。
通过find命令在Test1目录下成功找到“yuan.txt”文件,通过mv命令将其重命名为“hou.txt”。再次通过find命令查找“yuan.txt”发现文件已不存在,而查找“hou.txt”则文件存在,说明文件改名成功。
(7)文件复制命令cp
事先通过文本编辑器在“Test1”目录下创建“1.txt”文本文件,并设置其内容为“这是我想要copy的文件内容”。在终端通过more命令可以查看1.txt的内容。
然后,利用cp命令将“1.txt”文件的内容复制给“copy.txt”文件,并通过more命令查看“copy.txt”文件内容,发现其与“1.txt”内容一致,证明复制成功。
(8)显示文件的内容more或者less
在第(7)点的图中已展示more命令的使用,不再赘述。
对于less命令,它可以全屏浏览文件中的内容,结果如下图所示。
(9)查找文件find
在(5)(6)点的图中已展示find命令的使用,不再赘述。对于可以成功查找到的文件,终端会输出文件名;对于无法找到的文件,终端会输出“没有那个文件或目录”。
(10)重定向与管道
Linux进程在启动后,通常打开标准输入文件(stdin)、标准输出文件(stdout)和标准错误文件(stderr)3个文件句柄。其中,系统想从用户那里读入输入的信息,就从stdin文件里读取信息;要输出信息展示给用户,就输出到stdout;要输出错误提示给用户,就输出到stderr。而缺省情况下,这三个文件都指向终端设备。
“>”是stdout的重定向符号,表示stdout不指向终端设备,而是重定向到了指定文件。下图中利用“>”将ls命令下读取的Test1目录下的所有文件名输入到“out”文件中,利用cat命令查看一致。
若要重定向stderr,则使用重定向符号“2>”;若要同时重定向stdout和stderr,则使用“> temp 2>&1”或“&> temp”。
“<”是stdin的重定向符号,表示stdin不指向终端设备,而重定向到指定文件。下图中利用“<”将输入文字输出到“file”文件中,当输入eof时结束。当利用cat查看file文件时,内容与输入信息一致。
因此,可以得出:
输入/输出 | 重定向符号 | 意义 |
stdout | > / >> | 覆盖/追加重定向到指定文件 |
stderr | 2> / 2>> | 覆盖/追加重定向到指定文件 |
stdin | < / << | <重定向到文件中去读取,<<表示结束输入的字符 |
对于管道,竖线 | 就是管道操作符。以ps –ef | grep 6536为例,它起的作用是将前面的ps –ef命令的stdout重定向到一个临时管道设备里面,同时将后一个命令grep 6536 的stdin重定向到这个临时的管道设备。
下图中,通过ls -l /etc/会显示许多目录,而通过ls -l /etc/ | more命令,则将上一次的输出结果作为more命令的输入(类似管道流),实现对上述1064条目录的分页显示,结果如下图所示。
2.1.2 在线帮助
(1)man命令
通过man命令,在后面输入想要获取的命令名称,man会给出一份完整的说明,内容包括命令语法、各选项意义、相关命令等。利于初学者掌握基础命令知识。下图为ls命令的帮助说明。
(2)help命令
help命令用于查看所有shell命令,利于初学者掌握shell命令。
(3)whereis命令
whereis命令的功能是找一个命令所在的目录,可以看到ls命令是在bin目录下的。
2.1.3 全屏幕文本编辑器Vi
(1)进入vi
输入vi命令准备进入vi文本编辑器。
成功进入,结果如下图所示。
(2)切换至文本输入模式编辑文件
在这里,有i、a、o三种进入文本输入模式的命令,通过o命令从新的一行行首开始输入文字,结果如下图所示。
(3)移动游标
利用h、j、k、l控制游标左、下、上、右移动,^b往后一页、^f往前一页、G移动到最后、0移动到最开头,esc命令退出文本编辑模式。
(4)删除
通过x命令或者dd命令可以删除一些文字。
(5)更改
通过cw命令更改游标所指处。
(6)复制
通过yy命令使游标所在的位置的行整行复制,通过p命令将其复制到下一行,yy、yw必须与p命令搭配才能使用。
(7)跳至指定之行
通过3G(#G)命令移动游标至第3行行首。
(8)离开vi及存档
“:w filename”(存入指定档案)、“:wq”(写入并离开vi)、“:q!”(离开并放弃编辑的档案)。下图中,输入:wq进入vi界面的最后一行,准备写入以上所有内容并离开vi。
利用more命令查看测试文本中内容,与刚才写入的完全一致。
2.1.4 gcc编译器的使用
现有hello.c文件,里面有简单的printf函数,通过gcc -o hello hello.c生成一个hello的可执行文件,执行./hello就可以看到程序的输出结果了。
命令行中gcc表示是用gcc来编译源程序,-o 选项表示我们要求编译器给我们输出的可执行文件名为hello,而hello.c是我们的源程序文件,结果如下图所示。
(1)运行以下附录部分给出的程序,查看运行结果并分析(详见三中代码及结果分析)
(2)编写程序(详见三中代码及运行结果分析)
3.1.1 代码
3.1.2 运行结果
3.1.3 结果分析
3.1.4 程序进程树
3.2.1 代码
3.2.2 运行结果
3.2.3 结果分析
3.2.4 程序进程树
3.3.1 代码
3.3.2 运行结果
3.3.3 结果分析
3.3.4 程序进程树
3.4.1 代码
3.4.2 部分运行结果
3.4.3 结果分析
3.5.1 要求
要求程序运行时,系统中存在如下的进程树结构,写出程序源代码及程序运行结果并在进程树的相应进程节点上标上进程号。
3.5.2 代码
- #include<stdio.h>
- int main(){
- int a,b,c;
- a = fork();
- printf("PID:%d\t", getpid());
- printf("Return value of fork():%d\t\t", a);
- printf( "a\n" );
- b = fork();
- printf("PID:%d\t", getpid());
- printf("Return value of fork():%d\t\t",b);
- printf( "b\n" );
- if(a && b) {
- c = fork();
- printf("PID:%d\t", getpid());
- printf("Return value of fork():%d\t\t", c);
- printf( "c\n" );
- }
- return ;
- }
3.5.3 运行结果
3.5.4 结果分析
3.5.5 程序进程树
3.6.1 要求
对以上程序4进行修改,使得修改以后的程序在运行过程中三个进程不会被相互打断。用到的知识:lockf,lockf(files,function,size):用作锁定文件的某些段或者整个文件,本函数适用的头文件为:#include<unistd.h>
参数定义:int lockf(files,function,size); int files,function; long size;
其中:files是文件描述符:function是锁定和解锁;1表示锁定,0表示解锁。Size是锁定或解锁的字节数,若用0,表示从文件的当前位置到文件尾。
若要防止一个进程在运行过程中被打断,可以用lockf(1,1,0)对整个进程进行加锁,结束前用lockf(1,0,0)做解锁操作,以便其他进程的运行。
3.5.2 代码
- #include<stdio.h>
- #include<unistd.h>
- int main(){
- int p1,p2,i;
- while((p1 = fork) == -1);
- if(p1 == 0) {
- lockf(1,1,0);
- for(i = 0; i< 50000; i++){
- printf("son%d\n", i);
- }
- lockf(1,0,0);
- } else {
- while((p2 = fork()) == -1);
- if(p2 == 0){
- lockf(1,1,0);
- for(i = ; i< 50000; i++){
- printf("daughter%d\n",i)
- }
- lockf(1,0,0);
- } else {
- lockf(1,1,0);
- for(i = 0; i < 50000; i++){
- printf("parent%d\n",i);
- }
- lockf(1,0,0);
- }
- }
- return 0;
- }
3.6.3 部分运行结果
3.6.4 结果分析
这次操作系统课程的第一次课堂实验,主要熟悉掌握Linux的基础命令、实现调度进程管理。由于需要在Linux环境下进行,所以课前我就采用双系统的方式配置了Linux环境。但是由于电脑版本问题缺失了系统引导向,在开机时无法选择启动Windows系统,导致后续我研究了很久才找到解决方法。后来,为了方便起见,我安装了虚拟机,配置了Ubuntu,并将中文布局、中文输入法、gcc编译器等基础配置完成。
在课上,我根据PPT内容逐个尝试了一下Linux系统的基本命令。其中文件与目录操作类似于git的文件代码仓库操作,故上手比较简单;管道重定向|命令是一个新的知识点,我搜查了相关资料,了解到它是将前一个管道的输出作为下一管道的输入,并通过例题掌握了这一命令。
对于文本编辑器Vi,我主要掌握了i、a、o命令进入编辑,x、cw、r等命令进行删除、更改、取代,yy、p实现复制粘贴,以及h、j、k、l控制游标。对比Linux系统自带的文本编辑器,vi编辑器胜在更适合程序员使用,带有很多的命令指令。但在用户的体验感上,我偏向于文本编辑器。
对于gcc编译器,在Linux环境下安装十分方便,通过命令行sudo apt install gcc即可完成。终端下,通过“gcc -o 文件名 源文件”,即可通过gcc对源文件进行编译,使用“./文件名”就可以执行文件,将结果输出在终端。
进程管理实验是本次实验的重点,共有四个程序分析题和两个编程题。其中涉及的函数有fork()、getpid()、wait()、lockf()等。我认为第三个实验是难点,需要理解并发执行创建子进程后,不是重新执行一遍main函数,而是从被创建的那行代码开始加入并发执行,顺序走完剩下的代码。故通过输出提示以及进程树,可以发现,最先创建的子进程有机会创建更多的子进程,而代码末创建的子进程由于之后没有fork()函数,也就不会继续创建子进程。第一个编程题,通过分析进程树,我在程序3的基础上进行了修改即可得到。将最后一个fork()纳入if判断,限制第二个子进程和第一个子进程继续执行fork()。第二个编程题,通过lockf()函数锁定for循环代码段可以限制并发执行,即执行到哪个进程就将其for循环走完,故parent、daughter、son不会随机出现,而是50000条分布出现,不存在程序4那样轮流插入输出的情况,解决了资源争用问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。