课程编号:B080103040Linux操作系统实验报告姓名姚柯杰学号******** 班级软工1212 指导教师石凯实验名称Linux操作系统实验开设学期2014-2015第一学期开设时间第11周——第18周报告日期评定成绩评定人石凯评定日期东北大学软件学院实验一熟悉Linux环境一、举例列出常用的shell命令使用方法1.目录操作(1)mkdir abc 创建一个目录abc(2)cd /abc 将工作目录改变到abc(3)cd 改变当前目录到主目录(4)ls 列出当前目录的内容(5)ls -l 输出当前目录内容的长列表,每个目录或文件占一行(6)pwd 显示当前目录的全路径(1)cat mx.c 显示mx.c文件内容(2)more mx.c 分屏显示mx.c内容(3)cat file1 file2 连接file1 和file2(1) cp file1 file2 将文件1复制到文件2(2)mv file1 file2 将文件重命名为file2(3)rm filename 删除文件filename二、通过实例写出Linux下C程序编辑运行过程。
在终端命令下输入vi filename 命令,这里我输入vi helloworld.c 创建并打开helloworld.c 文件按i进入编辑模式,输入下列code:# include <stdio.h>void main(void){Printf(“hello world!\n”);}输入:wq保存退出输入cc helloworld.c编译,在输入./a.out运行三、实验总结在实验一中,我初步对linux有了初步的了解,能熟练目录和文件进行操作,并且能用linux进行基本简单的基于c的编程。
师傅领进门,修行在个人,算是通过这个实验进入了linux的门。
实验二文件操作一、实现CP命令实现思路:提取出源路径和目标路径到函数中,放于定义的两个int变量,定义缓冲区buf,对两个变量进行判断,如果符合要求打开读取源文件信息存于缓冲区,然后写到目标文件中,关闭两个文件以实现等同cp效果。
此处以hello。
C文件为源文件,目标文件1.c。
在调试cp命令中,由于一开始并未定义缓冲区,导致程序出错,后假如缓冲区,程序得以正常运行。
二、实现ls命令实现思路:调用dirent.h来实现打开目录流,定义变量,随后对变量进行判定用opendir、readdir 打开并读取目录流,将值传递给另一个变量,打印出来。
编译源程序并运行:在实现ls命令中使用man手册查找需要的dir等目录流信息,man是个强大的命令,在编程的过程中由于疏忽一开始并未假如判断条件,有些突发情况会难以处理,最后通过课件修过过来。
三、设备文件操作鼠标对应的设备文件是 /dev/input/mice实验三进程间通信(一)进程的创建(必做题)编写一段程序,使用系统调用fork( )创建两个子进程,在系统中有一个父进程和两个子进程活动。
让每个进程在屏幕上显示一个字符;父进程显示字符“a”,子进程分别显示字符“b”和“c”。
试观察记录屏幕上的显示结果,并分析原因。
创建一个新的子进程。
其子进程会复制父进程的数据与堆栈空间。
Fork成功则在父进程会返回新建立的子进程pid,而在新建立的子进程中则返回0。
如果fork失败则直接返回-1。
所以在循环条件上出现上述情况。
修改已编写的程序,将每个进程的输出由单个字符改为一句话,再观察程序执行时屏幕上出现的现象,并分析其原因。
(必做题)子进程创建成功,到下一个while,第二个子进程成功到最后循环,输入parents1-500,随后返回继续上面子进程的循环输出。
【思考题】1.系统是怎样创建进程的?答:在UNIX系统中,只有0进程是在系统引导时被创建的,在系统初启时由0进程创建1进程,以后0进程变成对换进程,1进程成为系统中的始祖进程。
UNIX利用fork( )为每个终端创建一个子进程为用户服务,每个终端进程又可利用fork( )来创建其子进程,从而形成一棵进程树。
2.当前运行的程序(主进程)的父进程是什么?建立如下的c文件来获取pid得到这三个进程pid,可见父进程的pid是5182。
(二)信号量机制实验【实验内容】1.编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止:Parent process is killed!实验要求:⑴运行程序并分析结果。
⑵如果把signal(SIGINT,stop)放在①号和②号位置,结果会怎样并分析原因。
⑶该程序段前面部分用了两个wait(0),为什么?⑷该程序段中每个进程退出时都用了语句exit(0),为什么?程序代码:# include<stdio.h>#include<stdlib.h># include<signal.h># include<unistd.h>#include<sys/types.h>#include<sys/wait.h>int wait_mark;void waiting(),stop();void main(){ int p1, p2;signal(SIGINT,stop);while((p1=fork())==-1);if(p1>0){//while((p2=fork())= =-1);if(p2>0){ //wait_mark=1;waiting(0);kill(p1,10);kill(p2,12);waiting();waiting();printf("parent process is killed!\n");exit(0);}else{wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf("child process 2 is killed by parent!\n");lockf(1,0,0);exit(0);}}else{wait_mark=1;signal(10,stop);waiting();lockf(1,1,0);printf("child process 1 is killed by parent!\n");lockf(1,0,0);exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}(1)当按下ctrl+c中断进程时,程序将执行,父进程打印消息,父进程kill 子进程,子进程1收到消息上锁,打印消息,然后解锁关闭进程,随后子进程2同样操作,在kill子进程后父进程打印消息,中断自身进程。
(2)运行后表面并没有任何改变,在两处加入代码之后,偶尔会出现需要在中断第一次进程后需要进行第二次中断。
在添加两个中段接受指令后,会先执行关于子进程的代码片段。
(3)答:父进程为子进程收尸,防止僵尸程序出现。
(4)答:在调用处强行退出程序,运行一次程序就结束。
(三)进程的管道通信实验(四)【实验内容】1.编制一段程序,实现进程的管道通信。
使用pipe()建立一条管道线。
两个子进程p1和p2分别向管道各写一句话:Child 1 is sending message!Child 2 is sending message!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
实验要求:运行程序并分析结果。
2.在父进程中用pipe()建立一条管道线,往管道里写一句话,两个子进程接收这句话。
定义缓冲区,创建管道,随后创建进程,将父进程的消息写进缓冲去写进管道再传给写进子进程,子进程接受。
定义一个管道,父进程传递消息到管道,随后创建两个子进程接收这个消息,然后结束进程。
实验小结:再这个实验中一开始打算将两个子进程分开判断,但是常常最后出现结果不是出现僵尸进程就是跳过其中一个子进程结束,最后我觉得既然两个进程同时创建,不如直接将他们一起进行判断。
(四)消息的发送与接收实验【实验内容】1.消息的创建、发送和接收。
使用系统调用msgget( ),msgsnd( ),msgrev( ),及msgctl( )编制一长度为1k的消息发送和接收的程序。
<参考程序>①client.c#include <sys/types.h>#include <sys/msg.h>#include <sys/ipc.h>#define MSGKEY 75struct msgform{ long mtype;char mtext[1000];}msg;int msgqid;void client(){int i;msgqid=msgget(MSGKEY,0777);for(i=10;i>=1;i--){msg.mtype=i;printf(“(client)sent\n”);msgsnd(msgqid,&msg,1024,0);}exit(0);}main( ){client( );}②server.c#include <sys/types.h>#include <sys/msg.h>#include <sys/ipc.h>#define MSGKEY 75struct msgform{ long mtype;char mtext[1000];}msg;int msgqid;void server( ){msgqid=msgget(MSGKEY,0777|IPC_CREAT); do{msgrcv(msgqid,&msg,1030,0,0);printf(“(server)received\n”);}while(msg.mtype!=1);msgctl(msgqid,IPC_RMID,0);exit(0);}main( ){ server( );}1.列出调试通过程序的清单,分析运行结果。
首先运行client.c创建打开消息队列75,往消息对列中传递消息10-1,然后运行serve.c,打开消息队列75,然后接收其中的消息直到消息为假(不存在),退出进程。