实验一 Linux基本环境
一、实验目的
(1)熟悉Linux下的基本操作,学会使用各种Shell命令去操作Linux,对Linux有一个感性认识。
(2)学会使用vi编辑器编辑简单的C语言程序,并能对其编译和调试。
二、实验学时
1学时
三、实验内容
(1) 以root用户身份登陆,并使用“ls”,“cat”“cd”等命令来实现基本的文件操作并观察Linux文件系统的特点;
(2) 使用vi编辑器编写一C程序,并用gcc命令进行编译和链接,并用a.out来进行输出结果。
四、背景知识
常用命令练习:
用root账号(超级用户)注册,注册成功出现#号(超级用户系统提示符,普通用户的系统提示符为$)。
1. 注销(退出)系统:logout 或exit
2.练习使用命令ls(注意Linux命令区分大小写。) 使用ls 按字母顺序列出当前目录中所有非隐藏文件;
使用ls –a按字母顺序列出当前目录中所有文件,包括隐藏文件
使用ls –l 查看当前目录所有文件包括当前目录和父目录,包括长度、拥有者和权限; 使用dir 查看当前目录内容 3.使用cd改变当前目录 cd .. 回到上层目录;
cd /home/mj 移动到用户mj的主目录;
cd – 移动到自己的主目录,适用于任何用户 4.pwd 显示当前目录绝对路径 5.建立目录mkdir
mkdir 目录名; mkdir /home/s2001/newdir 6.删除目录:rmdir; 7.复制文件cp:
cp file1 file2 将file1内容复制到目标文件file2中,目标文件得到新的生成日期和inode编号;(在linux里每个文件都有一个唯一的inode号) 8.移动文件或目录: mv
mv file1 file2 将文件名从file1变成file2。 9.删除文件rm
rm file1 删除file1而不提示确认;
rm –i file1 提示用户确认之后删除file1 10. 显示文件内容:more (分页显示);
11. 显示文件:cat 文件名
12. 建立文件:cat >文件名,ctrl+d结束输入
使用编辑器vi 编辑文件
1. 进入linux的文本模式之后,在命令行键入vi filename.c 然后回车。下面作一些简单的解释:首先vi命令是打开vi编辑器。后面的filename.c是用户即将编辑的c文件名字,注意扩展名字是.c;当然,vi编辑器功能很强,可以用它来编辑其它格式的文件,比如汇编文件,其扩展名字是.s;也可以直接用vi打开一个新的未命名的文件,当保存的时候再给它命名,只是这样做不很方便。
2. 最基本的命令I :当进入刚打开的文件时,不能写入信息,这时按一下键盘上的I键(insert),插入的意思,就可以进入编辑模式了。 3. a与i是相同的用法
4. 当文件编辑完后,需要保存退出,这时需要经过以下几个步骤:1)按一下键盘上的Esc 键;2)键入冒号(:),紧跟在冒号后面是wq(意思是保存并退出)。如果不想保存退出,则在第二步键入冒号之后,键入q !(不带w,机尾部保存)
5. 退出vi编辑器的编辑模式之后,要对刚才编写的程序进行编译。 编译的命令是:gcc [-o outputfilename.out] filename.c,其中gcc是c的编译器。参数:filename.c 是要编译的源文件的名称,outputfilename表示输出文件名称,中括号表示括号内部的内容可输入也可以不输入(中括号本身不再命令行中出现)。如果不输入outputfilename.out,默认的输出文件是a.out 。
6. 最后一步是运行程序,方法如下:./outputfilename.out
实验二 进程管理
一、实验目的
1. 加深对进程概念的理解,明确进程和程序的区别。 2. 进一步认识并发执行的实质。
3. 分析进程争用资源的现象,学习解决进程互斥的方法 4. 了解Linux系统中进程通信的基本原理
二、实验学时
3学时
三、实验内容
1.进程的创建
编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示字符“a”;子进程分别显示字符“b”和字符“c”。试观察记录屏幕上的显示结果,并分析原因。
2
实验指导:
<背景知识> 一、进程
UNIX中,进程既是一个独立拥有资源的基本单位,又是一个独立调度的基本单位。一个进程实体由若干个区(段)组成,包括程序区、数据区、栈区、共享存储区等。每个区又分为若干页,每个进程配置有唯一的进程控制块PCB,用于控制和管理进程。 PCB的数据结构如下:
1、进程表项(Process Table Entry)。包括一些最常用的核心数据:
进程标识符PID、用户标识符UID、进程状态、事件描述符、进程和U区在内存或外存的地址、软中断信号、计时域、进程的大小、偏置值nice、指向就绪队列中下一个PCB的指针P_Link、指向U区进程正文、数据及栈在内存区域的指针。 2、U区(U Area)。用于存放进程表项的一些扩充信息。
每一个进程都有一个私用的U区,其中含有:进程表项指针、真正用户标识符u-ruid(read user ID)、有效用户标识符u-euid(effective user ID)、用户文件描述符表、计时器、内部I/O参数、限制字段、差错字段、返回值、信号处理数组。
由于UNIX系统采用段页式存储管理,为了把段的起始虚地址变换为段在系统中的物理地址,便于实现区的共享,所以还有:
3、系统区表项。以存放各个段在物理存储器中的位置等信息。
系统把一个进程的虚地址空间划分为若干个连续的逻辑区,有正文区、数据区、栈区等。这些区是可被共享和保护的独立实体,多个进程可共享一个区。为了对区进行管理,核心中设置一个系统区表,各表项中记录了以下有关描述活动区的信息:
区的类型和大小、区的状态、区在物理存储器中的位置、引用计数、指向文件索引结点的指针。
4、进程区表
系统为每个进程配置了一张进程区表。表中,每一项记录一个区的起始虚地址及指向系统区表中对应的区表项。核心通过查找进程区表和系统区表,便可将区的逻辑地址变换为物理地址。
二、进程映像 UNIX系统中,进程是进程映像的执行过程,也就是正在执行的进程实体。它由三部分组成: 1、用户级上、下文。主要成分是用户程序;
2、寄存器上、下文。由CPU中的一些寄存器的内容组成,如PC,PSW,SP及通用寄存器等;
3、系统级上、下文。包括OS为管理进程所用的信息,有静态和动态之分。 三、所涉及的系统调用 fork( )
创建一个新进程。 系统调用格式: pid=fork( ) 参数定义: int fork( )
fork( )返回值意义如下:
0:在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。
>0:在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。 -1:创建失败。
3
如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。此时OS在内存中建立一个新进程,所建的新进程是调用fork( )父进程(parent process)的副本,称为子进程(child process)。子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。父进程与子进程并发执行。 核心为fork( )完成以下操作:
(1)为新进程分配一进程表项和进程标识符
进入fork( )后,核心检查系统是否有足够的资源来建立一个新进程。若资源不足,则fork( )系统调用失败;否则,核心为新进程分配一进程表项和唯一的进程标识符。 (2)检查同时运行的进程数目
超过预先规定的最大数目时,fork( )系统调用失败。 (3)拷贝进程表项中的数据
将父进程的当前目录和所有已打开的数据拷贝到子进程表项中,并置进程的状态为“创建”状态。
(4)子进程继承父进程的所有文件
对父进程当前目录和所有已打开的文件表项中的引用计数加1。 (5)为子进程创建进程上、下文
进程创建结束,设子进程状态为“内存中就绪”并返回子进程的标识符。 (6)子进程执行
虽然父进程与子进程程序完全相同,但每个进程都有自己的程序计数器PC(注意子进程的PC开始位置),然后根据pid变量保存的fork( )返回值的不同,执行了不同的分支语句。 四、参考程序 #include
int p1,p2;
while((p1=fork( ))= = -1); /*创建子进程p1*/ if (p1= =0) putchar('b'); else {
while((p2=fork( ))= = -1); /*创建子进程p2*/ if(p2= =0) putchar('c'); else putchar('a'); } }
<运行结果>bca(有时会出现abc的任意的排列)
分析:从进程执行并发来看,输出abc的排列都是有可能的。
原因:fork()创建进程所需的时间虽然可能多于输出一个字符的时间,但各个进程的时间片的获得却不是一定是顺序的,所以输出abc的排列都是有可能的。
2.进程的控制
修改已编写的程序,将每个进程输出一个字符改为每个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。
如果在程序中使用系统调用lockf()来给每一个进程加锁,可以实现进程之间
4
的互斥,观察并分析出现的现象。
实验指导:
一、所涉及的系统调用 lockf()
lockf(files,function,size):
用作锁定文件的某些段或者整个文件,本函数适用的头文件为: #include
int lockf(files,function,size) int files,function; long size;
其中:files是文件描述符:function是锁定和解锁;1表示锁定,0表示解锁。size是锁定和解锁的字节数,若用0,表示从文件的当前位置到文件尾。
二、参考程序
〈程序1〉
#include
int p1,p2,i;
while((p1=fork( ))= = -1); /*创建子进程p1*/ if (p1= =0)
for(i=0;i<100;i++)
printf(\else {
while((p2=fork( ))= = -1); /*创建子进程p2*/ if(p2= =0)
for(i=0;i<100;i++)
printf(\else
for(i=0;i<100;i++)
printf(\} }
〈运行结果〉 2、parent… son… daughter.. daughter.. 或 parent… son… parent…
5