操作系统实验报告_第1页
操作系统实验报告_第2页
操作系统实验报告_第3页
操作系统实验报告_第4页
操作系统实验报告_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、操作系统实验报告学号:姓名:指导老师:完成日期:目录实验一1实验二2实验三7实验四10实验五15实验六18实验七22实验一UNIX/LINUX入门一、实验目的了解 UNIX/LINUX 运行环境,熟悉 UNIX/LINUX 的常用基本命令,熟悉和掌握 UNIX/LINUX 下 c 语言程序的编写、编译、调试和运行方法。二、实验内容熟悉 UNIX/LINUX的常用基本命令如ls、 who、pwd、 ps 等。练习 UNIX/LINUX的文本行编辑器vi 的使用方法熟悉 UNIX/LINUX下 c 语言编译器 cc/gcc 的使用方法。用vi 编写一个简单的显示“ Hello,World!语”言c

2、程序,用 gcc 编译并观察编译后的结果,然后运行它。三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验程序#include <stdio.h>#include <stdlib.h>int main()printf ("Hello World!n");return 0;五、实验感想通过第一次室验,我了解 UNIX/LINUX 运行环境,熟悉了 UNIX/LINUX 的常用基本命令,熟悉和掌握了 UNIX/LINUX 下 c 语言程序的编写、编译、调试和运行方法。1实验二进程管理一、实验目的

3、加深对进程概念的理解,明确进程与程序的区别;进一步认识并发执行的实质。二、实验内容(1)进程创建编写一段程序,使用系统调用fork() 创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示“a;“子进程分别显示字符”b和“字符 “c。”试观察记录屏幕上的显示结果,并分析原因。(2)进程控制修改已编写的程序,将每一个进程输出一个字符改为每一个进程输出一句话,再观察程序执行时屏幕上出现的现象,并分析原因。(3)进程的管道通信编写程序实现进程的管道通信。使用系统调用pipe() 建立一个管道, 二个子进程 P1 和 P2分别向管道各写一句

4、话:Child 1 is sending a message!Child 2 is sending a message!父进程从管道中读出二个来自子进程的信息并显示(要求先接收P1,再接收 P2)。三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1 、功能设计(1)进程创建使用 fork ()创建两个子进程,父进程等待两个子进程执行完再运行。(2)进程控制使用 fork ()创建两个子进程,父进程等待两个子进程分别输出一句话再运行。(3)进程的管道通信先创建子进程 1,向管道写入一句话, 子进程 1 结束后创建子进程 2,向管

5、道写入一句话,最后父进程从管道中读出。2 、数据结构子进程和管道。3、程序框图2五、实验程序(1)进程创建#include<stdio.h>#include<stdlib.h>int main()int pid1, pid2;pid1=fork();if (pid1<0)printf("Fork 1 failed!");if (pid1=0)printf("bn");exit(0);if (pid1>0)wait(NULL);pid2 = fork();if (pid2<0) printf("Fork

6、2 failed!"); if (pid2=0) printf("cn");exit(0);if (pid2>0) wait(NULL);printf("an");exit(0);(2)进程控制3#include<stdio.h>#include<stdlib.h>int main()int pid1, pid2;pid1=fork();if (pid1<0)printf("Fork 1 failed!");if (pid1=0)printf("This is child bn&

7、quot;);exit(0);if (pid1>0)wait(NULL);pid2 = fork();if (pid2<0) printf("Fork 2 failed!"); if (pid2=0) printf("This is child cn");exit(0);if (pid2>0) wait(NULL);printf("This is father an");exit(0);( 3)进程的管道通信#include<stdio.h>#include<stdlib.h>#include

8、<sys/types.h>#include<memory.h> int main()int pid1, pid2;int pfd2;char *msg1="Child 1 is sending a message!" char *msg2="Child 2 is sending a message!"char buf256;int r,w;if(pipe(pfd)<0)printf("pipe create error!n"); exit(1); pid1 = fork();if (pid1<0)p

9、rintf("Fork 1 failed!"); if (pid1=0)close(pfd0); /write sleep(3);if(w=write(pfd1,msg1,strlen(msg1)<0) printf("wirte error!n"); exit(1);else printf("child 1 send msg to pipe!n"); 4exit(0);if(pid1>0)wait(NULL);pid2 = fork();if(pid2<0)printf("Fork 2 failed!&q

10、uot;);if(pid2>0)close(pfd1); /readsleep(3);if(r=read(pfd0,buf,256)<0)printf("read error!n");exit(1);else printf("parent read from pipe: %sn",buf); wait(NULL);close(pfd1); /readsleep(3);if(r=read(pfd0,buf,256)<0)printf("read error!n");exit(1);else printf("p

11、arent read from pipe: %sn",buf);if(pid2=0)close(pfd0); /writesleep(6);if(w=write(pfd1,msg2,strlen(msg2)<0) printf("write error!n");exit(1);else printf("child 2 send msg to pipe!n");exit(0);六、实验结果从图中可以看出,分别输出了,三个字母,三句话,实现了子进程向管道写数据,父进程从管道中读出。七、实验感想通过本次实验, 我们对进程的概念加深了理解, 熟悉

12、了进程的创建方法与作用机制, 明确了进程与程序的异同。 同时,我们掌握了使用管道通信的机制, 进一步认识了并发执行的实质。6实验三一个进程启动另一个程序的执行一、实验目的编写 Linux 环境下, fork() 与 exec()的结合使用实现一个进程启动另一个程序的执行的基本方法,掌握 exec()的几种调用方法。二、实验内容父进程从终端读取要执行的命令, 并交给子进程执行。 父进程等待子进程结束, 并打印子进程的返回值。三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1、功能设计根据实验要求, 父进程和子进程将被分配不同的任

13、务:父进程从终端读取要执行的命令交给子进程, 然后等待子进程技术打印子进程的返回值;子进程执行父进程读取的命令并返回给父进程。因为子进程执行命令需要打开其他文件,所以需要使用exec()类的函数实现在一个进程来启动另一个程序,在这里应使用execlp() 函数从 PATH 环境变量中查找文件并执行。对于父进程,可以调用fget() 从终端读取要执行的命令,以字符串形式存储然后交给子进程执行, 待子进程执行完毕后接收子进程返回值并打印。由于要求带参数的命令也可以执行,那么需要在父进程中fets 两次,第一次gets 得到命令给串command,然后 gets 参数给串 command1,并且将这

14、两个参数分别传到子进程的exec()函数,其中前两个都是 command,第三个是 command1。2、数据结构用 char* 型全局变量 command 存放指令用 char* 型全局变量 command1 存放参数3、程序框图7五、实验程序#include <stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>char command256;char command1256;int main()int rtn;/ 子进程的返回数值int errorno;while(1)

15、 printf( ">" );/ 从终端读取要执行的命令fgets( command, 256, stdin );printf( "<" );/ 从终端读取要执行命令的参数fgets( command1, 256, stdin );commandstrlen(command)-1 = '0'command1strlen(command1)-1 = '0'if ( fork() = 0 ) / 子进程执行此命令errorno=(command10=0)?:execlp(command, command, NULL

16、, NULL),execlp(command,command, command1, NULL);/ 如果没有参数则前者的execlp()函数,8如果有参数则执行后者,有无参数只需看command10是否为 0perror( command ); /如果 exec 函数返回,表明没有正常执行命令,打印错误信息exit(errorno);else / 父进程,等待子进程结束,并打印子进程的返回值wait ( &rtn );printf( " child process return %dn", rtn );return 0;六、实验结果由图可知,执行了ls 命令,参数为

17、 -a,文件按字母顺序显示如上图所示,输入命令ls,输入参数 -a,输出文件夹的内容。七、实验感想通过本次实验,我学会了如何用execlp() 函数达到一个进程启动另外一个程序的目的。并且对execlp() 的几个参数的作用有了一定了解,别且对于fork() 和 exelp() 联合使用的方法和功能。同时,我们进一步熟悉了LINUX系统操作环境,学习了在LINUX环境下编译和调试程序的技巧。9实验四基于消息队列和共享内存的进程间通信一、实验目的Linux 系统的进程通信机构( IPC )允许在任意进程间大批量地交换数据。本实验的目的是了解和熟悉:1. Linux 支持的消息通信机制及其使用方法

18、2. Linux 系统的共享存储区的原理及使用方法。二、实验内容1消息的创建、发送和接收使用消息调用 msgget()、 msgsnd()、 msggrev()、 msgctrl ()编制长度为 1K 的消息的发送和接收程序。2共享存储取得创建、附接和断接使用系统调用 shmget()、 shmat()、 shmctl ()、 shmctl (),编制一个与上述功能相同的程序。三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1、消息的创建、发送和接收(1)功能设计为了实现进程之间消息的创建、发送和接收,首先应定义两个子进程,S

19、erver进程负责发送, Client进程负责接收,父进程负责创建。其次需要用到msgget() 、 msgsnd() 、msggrev()、 msgctrl()等 函 数 进 行 对 消 息 的 控 制 。 题 目 要 求 消 息 长 度 为1K, 那 么msgsnd(id,msgp,size,flag)和 msgrcv(id,msgp,size,type,flag)函数中参数size 应设为1024,msgget(key,flag)中的 key 应为 75。父进程获得创建消息后,子进程Server 先后发送编号为110 的 10 条消息,子进程Client先后接收这10 条消息,方能达到实

20、验目的。(2)数据结构消息 (mymsg):结构体实现,包含的成员变量有消息类型和消息内容,具体实现如下:struct mymsg/ 消息的结构体声明long int mymsgtype;/ 消息类型int text;/ 消息内容(3)程序框图102、共享存储区的创建、附接和断接(1)功能设计为了实现进程通过共享存储区进行通信,需要创建两个进程并且调用shmget() 、shmat() 、 shmctl()函数实现共享存储区的创建、附接和断接。由于共享存储区的写入和读取由两个子进程完成, 而共享存储区在本程序中为所有进程共用的,因此共享存储区的创建、附接和断接均需要在父进程中完成。具体的实现方

21、式是现在父进程中创建一块共享存储区,然后用 int类型指针list指向该存储区的地址;接着创建两个子进程,第一个子进程通过list指针实现向共享存储区写入int类型的数据, 第二个子进程通过list指针实现从共享存储区读出int类型的数据。由于两个子进程同时使用了list指针,所以需要控制两个进程互斥,在读进程序中添加了sleep(1)语句。(2)数据结构通过shmid=shmget (key ,size ,flag)函数建立 ( 获得 ) 共享存储区,返回该共享存储区的描述符shmid 。(3)程序框图11五、实验程序1、消息的创建、发送和接收#include<stdio.h>#

22、include<sys/types.h>#include<unistd.h>#include<sys/ipc.h>#include<sys/msg.h>#include<sys/shm.h>#define MAX 1024#define KEY 75struct mymsg/ 消息结构体long int mymsgtype;/ 消息类型int text;/ 消息内容msg;int main()pid_t pids;pid_t pidc;int msgid; int i=1; msgid=msgget(KEY,0666|IPC_CREA

23、T);/ 获得一个消息的描述符if(pids=fork()=0)/ 创建 Server 子进程while(i<11)msg.mymsgtype=11-i;msg.text=i;printf("the sended message is %d thn",i);i+;msgsnd(msgid,&msg,MAX,0); /向 msgid 指定的消息队列发送消息,长度为1Kexit(0);elsei=10;if(pidc=fork()=0) /创建 Client子进程while(i!=1)msgrcv(msgid,&msg,MAX,0,0); /从 msgid

24、 指定的消息队列接收消息printf("the message is %d thn",msg.text);i=msg.mymsgtype;exit(0);elsewait(0); wait(0);exit(0);2、共享存储区的创建、附接和断接#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h

25、>#define MAX 1112#define KEY 75main()int i,child1,child2,running=1;/定义子进程号int id;int *list;id=shmget(KEY,sizeof(int)*MAX,IPC_CREAT|0666); /建立一块共享存储区,返回该共享存储区的描述符idlist=(int*)shmat(id,0,0); /将 list指针指向共享存储区if(child1=fork()=-1)printf("error in fork an");exit(1);if(child1=0) sleep(1);for(i

26、=0;i<=10;i+)printf("your message is: %d n",listi);exit(0);elseif(child2=fork()=-1)printf("error in fork an");exit(1);if(child2=0)i=0;while(1)listi=i; /向缓冲区里写入数据printf("the message sent is : %dn",listi);if(listi=10)break;i+;exit(0);elsewait(0);wait(0);shmdt(list); /将共

27、享存储区与进城断开shmctl(id,IPC_RMID,0);/将共享存储区标志为被销毁的exit(0);六、实验结果(1)消息的创建、发送和接收13第一个子进程一次发了 10 条消息,第二个子进程一次接收了 10 条消息,消息队列先进先出。(2)共享存储区的创建、附接和断接第一个子进程向共享存储区写入了 11 个数据,第二个子进程从共享存储区读取,两个进程之间是互斥执行的。七、实验感想通过本次实验, 我学会了如何用消息队列和共享内存的方式实现进程间的通信,掌握了Linux系统的消息通信机制和共享存储区的原理,并在实践过程中掌握了它们的使用方法。在编程和调试的过程中,我进一步熟悉了LINUX环

28、境下的编译过程和调试方法。实验五利用信号实现进程间通信14一、实验目的学习 UNIX 类操作系统信号机制,编写 Linux 环境下利用信号实现进程间通信的方法,掌握注册信号处理程序及 signal() 调用方法。二、实验内容编写一个程序,完成下列功能:实现一个SIGINT信号的处理程序,注册该信号处理程序,创建一个子进程,父子进程都进入等待。SIGINT信号的处理程序完成的任务包括打印接受到的信号的编号和进程PID 。编译并运行该程序,然后在键盘上敲Ctrl + C ,观察出现的现象,并解释。提示:参见 “五、补充材料 ”中的 signal() 的基本用法。三、实验要求按照要求编写程序,放在相

29、应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1、功能设计本实验要求利用信号实现进程间通信。为了实现实验目的,需要实现一个SIGINT 信号的处理函数func() 并注册该信号处理函数。信号处理函数需要完成的任务应包括打印接受到的信号的编号和进程的PID,所以 func() 函数应能实现打印当前进程的pid 以及根据接收到的信号的编号打印出该信号名称的功能。父进程和子进程分别接收两个不同的信号,因此两个进程调用signal()函数时应为不同的信号注册信号处理函数。本次实验采用了SIGINT 和SIGUSR1两个信号。为了让父子进程都能够接收到信号,在注册信号处

30、理函数后应让两个进程进入等待, 并且为了方便验证试验结果, 让父进程接收 SIGINT信号, 子进程接收 SIGUSR1 信号。2、数据结构信号 (SIGNAL): UNIX 系统含有 20 种信号。可以使用 signal()函数为每个信号注册信号处理函数。3、程序框图五、实验程序#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>void func(int i);int pid;int main()if(pid=fork()=0) /创建子进程printf

31、("sonpid:%dn",pid);/打印子进程号signal(SIGUSR1,func);/注册 SIGUSR1 的信号处理程序for ( ; ; )/子进程进入等待pause();elseprintf("fatherpid:%dn",pid);/打印父进程号signal(SIGINT,func);/注册 SIGINT 的信号处理程序for ( ; ; )/父进程进入等待pause();void func(int i)/信号处理函数printf("pid:%dn",pid);if (i = SIGUSR1)printf("

32、;received SIGUSR1n");else if (i = SIGUSR2)printf("received SIGUSR2n");else if(i = SIGINT)16printf("received SIGINT %dn", i);exit(1);exit(0);六、实验结果如图所示,第一次执行后打印父进程和子进程pid ,按 ctrl+c后,父进程接收信号,信号处理程序输出父进程号2472 和信号名称。第二次使用./shiyan5&后台运行此程序,使用 kill USR12472 时,子进程接收信号, 信号处理程序输出

33、子进程号0,并输出信号名称。七、实验心得通过本次实验,我掌握了注册信号处理程序及signal() 调用方法,并且了解了如何让程序在后台运行的方法。我也进一步了解了LINUX系统中进程同步与通信的原理。实验六线程的创建17一、实验目的编写 Linux 环境下的多线程程序, 了解多线程的程序设计方法, 掌握最常用的三个函数pthread_create, pthread_join 和pthread_exit 的用法。二、实验内容1、主程序创建两个线程myThread1 和 myThread2 ,每个线程打印一句话。使用pthread_create(&id,NULL,(void *) thre

34、ad,NULL)完成。2、创建两个线程,分别向线程传递如下两种类型的参数传递整型值传递字符三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1、创建两个进程每个进程打印一句话(1) 功能设计题目要求创建两个线程,每个线程打印一句话,可以认为两个线程的功能是相同的,故只需要写一个线程的运行函数 thread() ,在这个函数里有一个 printf 输出一句话即可。然后在 main 函数里分别创建两个线程,然后等待两个线程结束。(2) 数据结构线程:使用 pthread_create()创建。每个线程有相应的线程标示符,也有各自的属

35、性。线程可以和线程运行函数绑定,并可以在创建线程时确定该线程运行函数的参数。(3) 程序框图2、创建两个进程每个进程打印一句话分别向线程传递如下两种类型的参数:整型值、 字符(1)18题目要求创建两个线程,两个线程分别传递int型和 char 型数据给线程运行函数。所以 要 编 写 两 个 不 同 的 线 程 运 行 函 数 分 别 接 收int型 和char型 的 数 据 。 相 应 的pthread_create()函数中要给第四个参数,作为形参传进线程运行函数。(2) 数据结构线程:同 1,使用 pthread_create()创建。每个线程有相应的线程标示符,也有各自的属性。线程可以和

36、线程运行函数绑定,并可以在创建线程时确定该线程运行函数的参数。(3) 程序框图五、实验程序1、创建两个进程每个进程打印一句话#include <stdio.h>#include<stdlib.h>#include <pthread.h>void thread()/线程运行函数printf("This is a pthread.n"); /输出一句话int main()pthread_t id1,id2;/定义两个线程标识符int i,ret;ret=pthread_create(&id1,NULL,(void *) thread,

37、NULL);/创建线程标识为id1if(ret!=0)/线程创建失败printf ("Create pthread error!n");exit (1);ret=pthread_create(&id2,NULL,(void *) thread,NULL); /创建线程标识为id2if(ret!=0)/线程创建失败printf ("Create pthread error!n");19exit (1);printf("This is the main process.n");pthread_join(id1,NULL);/ 等待

38、第一个线程结束pthread_join(id2,NULL);/ 等待第二个线程结束return (0);2、创建两个进程每个进程打印一句话分别向线程传递如下两种类型的参数:整型值、 字符#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>void threadchar(char * c)/接收字符的线程运行函数 printf("receive a char:%cn",c);void threadint(int * i)/ 接收整

39、数的线程运行函数printf("receive a int:%dn",i);int main(void) pthread_t id1,id2; int ret;char c='t'char *a=c;/定义 char* 指针变量传参数用ret=pthread_create(&id1,NULL,(void *) threadchar,a);/创建线程1,第四个参数为char* 型变量用来传递字符if(ret!=0) /线程创建失败printf ("Create pthread error!n");exit (1);int i=99;

40、int *b=i;/定义 int* 指针变量传参数用ret=pthread_create(&id2,NULL,(void *) threadint,b);/创建线程2,第四个参数为int* 型变量用来传递字符if(ret!=0) / 线程创建失败printf ("Create pthread error!n");exit (1);printf("This is the main process.n");pthread_join(id1,NULL);/ 等待线程1 结束pthread_join(id2,NULL);/ 等待线程 2 结束return

41、 (0);六、实验结果由图可知两个线程主程序创建了两个进程这两个进程分别输出了一句话。主程序分别创建了两个线程并向线程 1 传递了 t 向线程 2 传递了 99,线程运行函数分别输出告知接收了这两个参数。七、实验感想通过本次实验, 我学会了如何使用LINUX 下的线程创建函数pthread_create()来创建线程,并且向线程传递参数。同时更加熟练的使用LINUX 。实验七利用信号量实现进程的控制21一、实验目的学习 UNIX 类操作系统信号量机制,编写 Linux 环境下利用信号量实现进程控制的方法,掌握相关系统调用的使用方法。二、实验内容创建 4 个线程, 其中两个线程负责从文件读取数据

42、到公共的缓冲区,区读取数据作不同的处理(加和乘运算)。使用信号量控制这些线程的执行。另两个线程从缓冲三、实验要求按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。四、实验设计1、功能设计题目要求创建 4 个线程, 其中两个负责从文件读数据到缓冲区, 另两个负责从缓冲区读数据进行加和乘的运算。我对这 4 个线程进行如下安排,线程 1 读后线程 2 才可以读,线程 2 读了后线程 3 才可以进行加的运算, 线程 3 加完了后线程 4 才能进行乘的运算, 线程 4 乘完后线程 1 才能继续读。故需 4 个信号量 sem1,sem2,sem3,sem4。线程 1 消费 sem1 生产 sem2,线程 2 消费 sem2 生产 sem3,线程 3 消费 sem3 生产 sem4,线程 4 消费 sem4 生产 sem1,形成一个循环,直到文件结束为止。2、数据结构信号量 (semaphore):数据类型为结构sem_t ,本质上是一个长整型的数。一共4 个公共缓冲区 (stack):采用 2 维数组的方式实现( stackNUM2 ) 。数组中的两列分别存储两个文件中的数据。该2 维数组还有一个索引:size ,指向 2 维数组的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论