实验1熟悉Linux环境操作系统原理实验——冯耀霖●实验目的1.了解Linux的文本用户界面,掌握用户的注册、登录及注销。2.熟悉vi编辑器的基本使用方法。3.学会在Linux上开发C程序的一般方法。●实验1.1用户的注册、登录及注销Step1.启动Linux①启动VMware,在VMware的主窗口启动Linux;②在用户界面中用超级用户账号登录。用户名:root密码:xxxxxxx如果进入的是系统默认的图形用户界面,则执行③~⑤,将用户界面修改成文本用户界面。③在桌面上打开终端shell界面;④用vi编辑器打开系统配置文件“/etc/inittab”,即输入命令行:vi/etc/inittab在vi窗口中找到文本行“id:5:initdefault:”,将其中的5改为3,保存后退出,见如下图示;修改“/etc/inittab”文件将该行中的5改为3⑤重启系统进入“黑屏”shell界面,仍以超级用户(系统管理员)账号登录。Step2.新用户注册①用groupadd命令建立两个用户组:group1和group2;②用useradd命令和passwd命令建立4个新的用户账号,其中一个是你本人的账号!如:fyl、wang、zhang、student,初始密码可均设为“654321”,并指定前2个账号为group1组成员,后2个账号为group2组成员;③用vi编辑器打开系统配置文件“/etc/passwd”,查看新账号是否已生成以及他们各自的用户标识号UID。④用vi编辑器打开系统配置文件“/etc/group”,查看group1组和group2组以及它们的组标识号GID;新的用户账号是否已加入到组中?⑤用usermod命令将新用户账号添加到各自的组中;⑥再打开/etc/group文件,确定新的用户账号已加入到各自的组中。账号密码UIDGID主目录shell注释/etc/passwd示例GID组名组密码组成员的账号/etc/group示例Step3.多用户登录①用Ctrl+Alt+F2切换到虚拟控制台tty2,用你的账号登录,并用passwd命令修改初始密码(记住!)。②再切换到tty3上,用另一普通用户账号登录并修改其初始密码。③使用who命令查看本系统当前有哪些在线用户,只需在命令提示符后输入命令行who↙④在你的账号下用mkdir命令建立一个目录:ostest。Step4.注销与关机①普通用户用logout命令注销;②超级用户用shutdown命令注销并关机。●实验1.2开发简单的C程序①启动Linux,用你的普通账号登录;②进入子目录ostest;③用vi编辑器编辑一个简单的C源程序test1_1.c,参考源代码如下:#includestdio.hmain(){inti,sum=0;for(i=1;i=10;i++)sum+=i;printf(”sum=%d\n”,sum);}④用命令“gcctest1_1.c”对test1_1.c进行编译;⑤若成功,则不会有任何信息显示;否则作适当修改,直到成功;⑥执行test1_1对应的可执行程序;⑦修改test1_1.c:求1到100之和。并将新程序命名为test1_2.c;⑧编译test1_2.c,要求其可执行程序的名字为test1_2;⑨执行test1_2。⑩注销。实验2进程的创建与并发执行之一●实验目的1.理解进程与程序的联系与区别以及并发程序的基本特性。2.学会在在程序中使用fork()函数创建克隆式子进程的基本编程方法。●背景知识1.shell进程与命令进程当用户在某个控制台上登录成功时,系统将自动创建一个对应的控制台进程——shell进程,名为sh,它的程序正文即为shell解释器。shell进程是该控制台的根(祖先)进程。每当用户在该控制台上输入一条shell命令时,shell进程就接收、解释命令,并为该命令创建一个命令进程,命令进程的程序正文是该命令对应的命令处理程序。shell进程是该控制台上所有命令进程的父进程,各命令进程都是shell进程的子进程。一条shell命令一旦执行完,对应的命令进程便自动被销毁。2.涉及的shell命令■ps命令功能:显示进程的状态信息。常用选项有:-a,-u,-x,-p例如:ps-a显示本控制台上所有进程的基本信息。ps-pxxx显示PID为xxx的进程的基本信息。ps-aux显示系统中所有进程的详细信息,其中包含了每个进程的PID。■pstree命令功能:显示进程的层次结构■more命令格式:more文本文件名功能:分页显示文本文件。■kill命令格式:killxxx参数xxx是某进程的PID(进程标识码)功能:销毁指定进程3.涉及的库函数(系统调用)■fork功能:以克隆方式创建子进程,子进程复制了父进程的内存映象。原型:intfork();若创建失败,fork返回-1;否则,fork同时向子进程返回0,而向父进程返回子进程的PID值(0)。■getpid功能:返回最近所建子进程或现行进程的PID。原型:intgetpid();●实验2.1命令进程的创建与并发执行①启动Linux,进入黑屏界面;②在tty1上用root账号登录,在tty2和tty3上则分别以普通用户账号登录;③在tty1上输入命令“ps--help”,即在tty1上创建命令进程ps,以查看ps命令的help信息;④在tty2上输入命令“manman”,即在tty2上创建命令进程man,以查看man命令的help信息,不要终止该man命令;⑤在tty3上执行命令“manpstree”,即在tty3上创建命令进程man,查看pstree命令的help信息,同样也不要终止该man命令;⑥在tty1上执行ps命令,查看本控制台上所有进程的基本信息;⑦在tty1上执行pstree命令,查看进程的分层结构。⑧再在tty1上执行ps命令,查看本系统的所有进程的详细信息,并从中找到并记下tty2上的man命令进程的PID;你能看到ps命令输出的全部信息吗?如果不能,可以利用Linux的“重定向”或“管道”功能,例如,可输入如下管道命令行:ps–aux|more该命令行的语义是:将ps命令的输出结果作为输入传递给more命令(分页显示),并执行more命令。⑨撤消tty2上的man命令进程;⑩再执行ps命令,查看被撤消的进程是否还存在;⑾切换到tty2,观察man命令是否还在执行或已终止;再切换到tty3,观察man命令是否还在执行或已终止;⑿注销(不要关机)。●实验2.2使用fork创建进程本实验使用系统调用fork()创建多个子进程,实现多进程并发执行。①使用你的普通用户账号登录。②用vi编辑下面的程序test2.c:/*test2.c*/#includestdio.hintmain(){intp1,p2,p3;longi;/*接下页*/while((p1=fork())==-1);/*现行(父)进程创建第一个子进程*/if(p1==0)/*子进程1的代码*/{printf(“Child1(PID=%d)isrunning!\n”,getpid());for(i=0;i999999;i++);/*用于延时,模拟进程的动作*/printf(“Child1isover.\n”);}else{/*p1值为子进程1的PID,以下是父进程的后续代码*/while((p2=fork())==-1);/*父进程创建第二个子进程*/if(p2==0){/*子进程2的代码*/{printf(“Child2(PID=%d)isrunning!\n”,getpid());for(i=0;i999999;i++);printf(“Childprocess2isover.\n”);}else{/*p2值为子进程2的PID,以下是父进程的后续代码*/while((p3=fork())==-1);/*父进程创建第三个子进程*/if(p3==0)/*子进程3的代码*/{printf(“Child3(PID=%d)isrunning!\n”,getpid());for(i=0;i999999;i++);printf(“Child3isover.\n”);}else{/*p3值为子进程3的PID,以下是父进程代码*/for(i=0;i999999;i++);printf(“Parentisover.\n”);}}return0;}③用gcc编译该源程序,生成可执行程序test2。④多次运行test2,观察并记下每一次的运行结果。◆程序的运行结果都相同吗?◆你认为结果有没有错?若有错,是什么错?◆这反映了进程(线程)的哪一基本特性?在实验报告中给出这三个问题的回答!分析与思考实验3进程的创建与并发执行之二●实验目的1.学会使用fork()/exec()模式创建进程(具有独立映象)的编程方法。2.加深理解进程的并发特性,掌握创建进程的正确编程方法。●背景知识■exec函数在Linux中,exec系列的库函数共有5个,其基本功能相同,即生成新进程的独立映象。这里给出ececv()函数的原型:intexecv(char*pathname,char*argv[]);其中,pathname是新进程的可执行程序文件的路径名;argv是程序参数的指针数组,argv的每个元素是个指向字符串(参数)的指针,规定argv[0]指向的是程序名,最后以空指针NULL结束。若函数的返回值为-1,表示出错。exec库函数在“unistd.h”头文件中声明。■wait函数原型:intwait(int*status);功能:调用者自行阻塞以等待子进程终止执行并销毁它。参数status用来保存某个子进程终止时的状态,但如果不关心子进程是如何终止的,而只想把该子进程销毁掉(事实上绝大多数是这种情况),则可以将该参数设置为NULL,甚至可缺省。wait的返回值是子进程的PID或出错代码(-1)。wait函数在“sys/wait.h”头文件中声明。■exit函数原型:voidexit(intstatus);功能:调用者进程自行终止,并向父进程发出“已终止”信号。参数status为0表示正常终止,非0表示异常终止。exit函数在“stdlib.h”头文件中声明。●实验3.1用fork/exec模式创建进程本实验是实验2.2中test2.c的继续和改进,同样是在一个进程中用fork函数先后创建了三个克隆子进程,不同的是随后又用exec函数构建了子进程的独立映象,使得子进程具有完全不同于父进程的内存映象。实验的三个基本步骤:step1:生成各子进程的可执行代码;step2:生成父进程的可执行代码;step3:运行父进程程序,观察分析运行结果。要求用你的普通用户账号登录,并进入ostest目录。step1:生成各子进程的可执行代码(1)在ostest目录下,用vi编辑器编辑subp1.c/*子进程1的独立程序subp1.c*/#includestdio.hvoidmain(){longi;printf(“child1isrunning!\n”);for(i=0;i999999;i++);printf(“child1isover.\n”);exit(0);}(2)在ostest目录下,用vi编辑subp2.c/*子进程2的独立程序subp2.c*/#includestdio.hvoidmain(){longi;printf(“child2isrunning!\n”);for(i=0;i999999;i++);printf(“child2isover.\n”);exit(0);}(3)在ostest目录下,用vi编辑subp3.c/*子进程2的独立程序subp3.c*/#includestdio.hvoidmain(){longi;printf(“child3isrunning!\n”);for(i=0;i999999;i++);printf(“child3isover.\n”);exit(0);}(4)用gc