1、北京工业大学操作系统实验报告0122 6000字 操作系统实验报告 专 业 计算机科学与技术 年 级 本科三年级 学 号 12070131 姓 名 樊文舟 目录: 一、实验一 -3 1.实验目的-3 2.实验内容-3 3.实验要求-3 4.实验设计-3 5.实验程序-3 6.实验结果-4 7.实验感想-4 1.实验目的-5 2.实验内容-5 3.实验要求-5 4.实验设计-5 5.实验程序-6 6.实验结果-7 7.实验感想-7 1.实验目的-8 2.实验内容-8 3.实验要求-8 4.实验设计-9 5.实验程序-10 6.实验结果-11 7.实验感想-11 1.实验目的-12 2.实验内容-
2、12 3.实验要求-12 4.实验设计-12 5.实验结果-12 6.实验感想-12 二、实验二 -4 三、实验三 -8 四、实验四 -12 个人总结 -12 实验一 unix/linux入门 一、 实验目的 了解unix/linux运行环境,熟悉unix/linux的常用基本命令,熟悉和掌握unix/linux下c语言程序的编写、编译、调试和运行方法。 二、 实验内容 1、熟悉unix/linux的常用基本命令如ls、who、pwd、ps等。(常用linux命令在附录中列出,请参阅。) 2、熟悉unix/linux下c语言编译器cc/gcc的使用方法。编写一个简单的显示“hello,worl
3、d!”c语言程序,用gcc编译并观察编译后的结果,然后运行它。 具体方法如下: (1)开机选择linux操作系统进入,根据要求输入用户名root,密码rootroot。 (2)尝试使用实验指导书中提供的各种指令。步骤如下: 如果你机器是英文系统,找applications?accessories ?terminal,并运行。 如果你机器是中文系统,找 应用?附件?终端,并运行。 注意:terminal是一个命令行系统,尝试运行相关的命令。 (3)尝试写一个hello world程序。步骤如下: a) 选择一个目录下创建一个文件example.c b) 双击代表example.c的图标进入编辑器
4、并输入hello world代码 c) 保存并退出 d) 在终端(terminal)中对example.c进行编译。编译命令为: gcc example.c o example e) 运行编译好的程序。指令为: ./example 三、 实验要求 按照要求编写程序,放在相应的目录中,编译成功后执行。 四、 实验设计 linux 系统常用命令格式: 五、 实验程序 #include <stdio.h> #include <stdlib.h> int main(void) printf (hello world!n); system (pause); return 0; 六
5、、 实验结果 七、 实验感想 通过第一次室验,熟悉了linux系统的操作,终端的使用,gcc编译c程序 实验二 进程管理 一、实验目的 加深对进程概念的理解,明确进程与程序的区别;进一步认识并发执行的实质。 二、实验内容 (1)进程创建 编写一段程序,使用系统调用fork()创建两个子进程。当此程序运行时,在系统中有一个父进程和两个子进程活动。让每一个进程在屏幕上显示一个字符:父进程显示“a“;子进程分别显示字符”b“和字符“c”。试观察记录屏幕上的显示结果,并分析原因。(提示:对每个进程的打印循环执行10次,则可以发现执行顺序的不同) (2)进程控制 修改已编写的程序,将每一个进程输出一个字
6、符改为用一个循环输出1000个字符(父进程输出1000个“a”,子进程分别输出1000个“b”和“c”),再观察程序执行时屏幕上出现的现象,并分析原因。 (3)进程的管道通信 编写程序实现进程的管道通信。使用系统调用pipe()建立一个无名管道,二个子进程p1和p2分别向管道各写一句话: child 1 is sending a message! child 2 is sending a message! 父进程从管道中读出二个来自子进程的信息并显示(要求先接收p1的消息,再接收p2的消息)。 三、实验要求 按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验
7、报告。 四、实验设计 1、功能设计 实验要求建立一个管道实现父进程和子进程间的通信,子进程有两个,子进程向管道里写数据,父进程从管道里读出数据。管道的作用是将两个缓冲区相关连起来,使得一个缓冲区写的东西可以从另一个缓冲区读出来,遵循先进先出的顺序。 程序的顺序是这样的:先创建子进程1,向管道写入一句话,子进程1结束后创建子进程2,向管道写入一句话,最后父进程从管道中读出。 2、数据结构 子进程:使用pid_t fork()函数创建,返回值为子进程号。 管道:使用int pipe(int filedis2)创建无名管道,filedis2为两个文件描述符。 3、程序框图 五、实验程序 #inclu
8、de<stdio.h> #include<string.h> #include<unistd.h> int pipe(int filedis2); #define input 0 #define output 1 int main() int file_descriptors2; pid_t pid1,pid2; /定义子进程 char buf256; int returned_count; pipe(file_descriptors);/创建无名管道 if(pid1=fork()=-1) /创建子进程1 printf(error on forkn); ex
9、it(1); if(pid1=0) printf(in the spawned(child1)processn); close(file_descriptorsinput); /关闭通道的读端 write(file_descriptorsoutput,child1 is sending message,strlen(child1 is sending message);/向管道中写一句话 exit(0); else if(pid2=fork()=-1) /创建子进程2 printf(error on forkn); exit(1); if(pid2=0) printf(in the spawn
10、ed(child2)processn); close(file_descriptorsinput); /关闭通道的读端 write(file_descriptorsoutput,child2 is sending message,strlen(child1 is sending message);/向管道中写一句话exit(0); else /父进程 printf(in the parent processn); close(file_descriptorsoutput); /关闭管道的写端 returned_count=read(file_descriptorsinput,buf,sizeo
11、f(buf); printf(%d bytes of data received from spawned process:%s n,returned_count,buf);/父进程从管道中读出数据 return 0; 六、实验结果 由图可知,父进程先后接受了子进程向管道写入的两句话,并成功地打印出来。 两个子进程分别向管道写入了25个字符,并且是子进程1先写的,子进程2后写的,故输出的顺序也是如此。 七、实验感想 通过本次实验,我们对进程的概念加深了理解,熟悉了进程的创建方法与作用机制,明确了进程与程序的异同。同时,我们掌握了使用管道通信的机制,进一步认识了并发执行的实质。 实验三 线程的管
12、理 一、实验目的 编写linux环境下的多线程程序,了解多线程的程序设计方法,掌握最常用的三个函数pthread_create,pthread_join和pthread_exit的用法 二、实验内容 1、 主程序创建两个线程mythread1和mythread2,每个线程打印一句话。使用 pthread_create(&id,null,(void *) thread,null)完成。 提示: 先定义每个线程的执行体,然后在main中()创建几个线程,最后主线程等待子线程结束后再退出。 2、创建两个线程,分别向线程传递如下两种类型的参数 ? 传递整型值 ? 传递字符 三、实验要求 按照要
13、求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。 四、实验设计 1、创建两个进程每个进程打印一句话 (1)功能设计 题目要求创建两个线程,每个线程打印一句话,可以认为两个线程的功能是相同的,故只需要写一个线程的运行函数thread(),在这个函数里有一个printf输出一句话即可。然后在main函数里分别创建两个线程,然后等待两个线程结束。 (2)数据结构 线程:使用pthread_create()创建。每个线程有相应的线程标示符,也有各自的属性。线程可以和线程运行函数绑定,并可以在创建线程时确定该线程运行函数的参数。 (3)程序框图 4)程序 #incl
14、ude <stdio.h> #include <pthread.h> void thread(void) /线程运行函数 printf(this is a pthread.n); /输出一句话 int main(void) pthread_t id1,id2; /定义两个线程标识符 int i,ret; ret=pthread_create(&id1,null,(void *) thread,null);/创建线程标识为id1 if(ret!=0) /线程创建失败 printf (create pthread error!n); exit (1); ret=pt
15、hread_create(&id2,null,(void *) thread,null); /创建线程标识为id2 if(ret!=0) /线程创建失败 printf (create pthread error!n); exit (1); printf(this is the main process.n); pthread_join(id1,null); /等待第一个线程结束 pthread_join(id2,null); /等待第二个线程结束 return (0); 2、创建两个进程每个进程打印一句话分别向线程传递如下两种类型的参数 :整型值、字符 (1)功能设计 题目要求创建两个
16、线程,两个线程分别传递int型和char型数据给线程运行函数。所以要编写两个不同的线程运行函数分别接收int型和char型的数据。相应的pthread_create()函数中要给第四个参数,作为形参传进线程运行函数。 (2)数据结构 线程:同1,使用pthread_create()创建。每个线程有相应的线程标示符,也有各自的属性。线程可以和线程运行函数绑定,并可以在创建线程时确定该线程运行函数的参数。 (3)程序框图 (4)程序 #include <pthread.h> #include <stdio.h> #include <stdlib.h> #incl
17、ude <unistd.h> void threadchar(char * c) /接收字符的线程运行函数 printf(receive a char:%cn,c); void threadint(int * i) /接收整数的线程运行函数 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,
18、a); /创建线程1,第四个参数为char*型变量用来传递字符 if(ret!=0) /线程创建失败 printf (create pthread error!n); exit (1); int i=99; 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 p
19、rocess.n); pthread_join(id1,null); /等待线程1结束 pthread_join(id2,null); /等待线程2结束 return (0); 五、实验结果 由图可知两个线程主程序创建了两个进程这两个进程分别输出了一句话 第 11 页 共 11 页 主程序分别创建了两个线程并向线程1传递了t向线程2传递了99,线程运行函数分别输出告知接收了这两个参数。 六、实验感想 通过本次实验,我学会了如何使用linux下的线程创建函数pthread_create()来创建线程,并且向线程传递参数。同时更加熟练的使用linux。 实验四 利用信号量实现进程控制 一、实验目的
20、 学习unix类(system v)操作系统信号量机制,编写linux环境下利用信号量实现进程控制的方法,掌握相关系统调用的使用方法。 二、实验内容 创建4个线程,其中两个线程负责从文件读取数据到公共的缓冲区,另两个线程从缓冲区读取数据作不同的处理(加和乘运算)。使用信号量控制这些线程的执行。 提示: (1)参见“四、补充材料”中的相关系统调用的基本用法。 (2)创建4个线程,其中2个线程用于从文件中读数据到缓冲区中(例如:一个进程读 1.dat文件,另一个进程读2.dat文件),另2个线程从缓冲区中取数据作处理。 事先编辑好数据文件如:1.dat和2.dat,假设它们的内容分别为1 2 3
21、4 5 6 7 8 9 10和 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 ,然后运行你编写的程序,应得到如下类似的结果:multiply:-1*-2=2 plus:-1+-2=-3 第 12 页 共 12 页 multiply:9*10=90 plus:-9+-10=-19 multiply:-7*-8=56 plus:-5+-6=-11 multiply:-3*-4=12 plus:9+10=19 plus:7+8=15 plus:5+6=11 三、实验要求 按照要求编写程序,放在相应的目录中,编译成功后执行,并按照要求分析执行结果,并写出实验报告。 四、实验设计 1、功
22、能设计 题目要求创建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个 公共缓冲区(
23、stack):采用2维数组的方式实现(stacknum2)。数组中的两列分别存储两个文件中的数据。该2维数组还有一个索引:size,指向2维数组的顶部。读线程每次从文件读出两个数放到stacknum0和stacknum1 3、程序框图 第 14 页 共 14 页 五、实验程序 #include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<semaphore.h> #define maxstack 20 int stackmaxstack; int a=0; int b=0; s
24、em_t sem,sem1; void readdata1(void) ) file *fp=fopen(1.dat,r); /从文件中读数据 sem_wait(&sem1); int i; for(i=0;i<10;i+) fscanf(fp,%d,&stacka+); sem_post(&sem1); sem_post(&sem); fclose(fp); void readdata2(void) file *fp=fopen(2.dat,r); sem_wait(&sem1); int i; sem_post(&sem1); sem_post(&sem); fclose(fp); void handledata1(void) int i; sem_wait(&sem); /等,读完了加到1才能处理 for(i=0;i<5;i+) int m=stackb+; int n=stackb+; printf(plus:%d+%d=%dn,m,n,m+n); 第 15 页 共 15 页 void handledata2(void) int i;