华科操作系统实验报告Word下载.docx
《华科操作系统实验报告Word下载.docx》由会员分享,可在线阅读,更多相关《华科操作系统实验报告Word下载.docx(27页珍藏版)》请在冰点文库上搜索。
3.1.2实验内容........................................................................................13
3.2实验过程...............................................................................................13
3.2.1预备知识........................................................................................13
3.2.2实验测试与结果............................................................................14
3.3实验总结...............................................................................................15
3.4源代码...................................................................................................15
实验一Linux线程及信号灯
1.1实验目的与内容
1.1.1实验目的
1、熟悉Linux线程接口。
2、熟悉Linux信号灯编程。
3、了解Linux进程同步与通信的主要机制,并通过信号灯操作实现进程间的同步与互斥。
1.1.2实验内容
1、编程模拟实现飞机售票:
创建多个售票线程;
使用公用全局变量保存已售票数量;
创建互斥信号灯;
对售票线程临界区实施P、V操作;
2、编程模拟实现双线程单缓冲区的合作
创建一个计算线程与一个输出线程;
创建同步信号灯;
缓冲区用全局公用数组变量;
对计算线程与输出线程实施P、V操作;
1.2实验过程
1.2.1预备知识
Linux下的信号灯及其P、V操作:
表1.1P、V操作定义
voidp(intsemid,intsemno)
{
structsembufsop;
sop.sem_num=semno;
sop.sem_op=-1;
sop.sem_flg=0;
semop(semid,&
sop,1);
}
voidv(intsemid,intsemno)
sop.sem_op=1;
线程:
表1.2线程相关函数
线程创建
pthread_create(pthread_t*thread,pthread_attr_t*attr,
void*(*start_routine)(void*),void*arg);
线程挂起
pthread_join(pthread_tth,void**thread_retrun);
共享内存:
使用共享内存是运行在同一计算机上的进程进行进程间通信的最快的方法,shmget与shmat系统调用。
进程控制:
fork与execv系统调用;
编译、编辑、调试
表1.3编译、编辑、调试
编译
cc–otest-gtest.c–lpthread
cc–osub1sub1.c
编辑
vi
调试
gdb
1.2.2实验测试与结果
测试结果:
模拟售票
说明(图1.1.1和1.1.2):
共有300张票,有三个线程分别代表三个售票窗口
图1.1.1
图1.1.2
说明(图1.1.3和1.1.4):
每个窗口每次只卖出一张,直到卖完
图1.1.3图1.1.4
双线程单缓冲区的合作
图1.2
1.3实验总结
本次实验刚做的时候用三个线程做依次访问卖几张来卖出,后来老师让我改成每次买一张直到卖完,做出来了,但是我加的循环体加的位置不对,运行一两次可能没问题,但运行几万次可能会出现问题,此bug老师给我指出的,程序还有待优化。
1.4源代码
1:
#include<
stdio.h>
pthread.h>
linux/sem.h>
sys/types.h>
stdlib.h>
intticket=300;
intmutex;
voidp(intsemid,intsemno)
voidv(intsemid,intsemno)
voidthread1(void)
inti;
p(mutex,0);
printf("
窗口1:
本航班共有%d个座位,请问您需要买几张?
\n"
ticket);
scanf("
%d"
&
i);
if(i>
ticket)
剩余票数不够"
);
else
ticket=ticket-i;
v(mutex,0);
voidthread2(void)
窗口2:
voidthread3(void)
窗口3:
intmain()
pthread_tid1,id2,id3;
intret1,ret2,ret3;
unionsemunarg;
mutex=semget(IPC_PRIVATE,IPC_CREAT);
arg.val=1;
semctl(mutex,0,IPC_RMID,0);
ret1=pthread_create(&
id1,NULL,(void*)thread1,NULL);
ret2=pthread_create(&
id2,NULL,(void*)thread2,NULL);
ret3=pthread_create(&
id3,NULL,(void*)thread3,NULL);
if(ret1!
=0){
Creat1stpthreaderror!
exit
(1);
}
if(ret2!
Creat2stpthreaderror!
if(ret3!
Creat3stpthreaderror!
pthread_join(id1,NULL);
pthread_join(id2,NULL);
pthread_join(id3,NULL);
return0;
2:
#include<
intq[100];
intm;
intw=0;
voidP(intsemid,intsemno)
structsembufsop;
sop.sem_num=semno;
sop.sem_op=-1;
sop.sem_flg=0;
semop(semid,&
voidV(intsemid,intsemno){
sop.sem_op=1;
voidpa(){
P(m,1);
w++;
q[w]+=1;
V(m,0);
voidpb
(){
P(m,0);
printf("
jieguo=%d\n"
q[w]);
w--;
V(m,1);
intmain(void){
pthread_tid1;
pthread_tid2;
pthread_tid3;
pthread_tid4;
inti,ret1,ret2;
unionsemunarg;
arg.val=0;
m=semget(IPC_PRIVATE,2,IPC_CREAT|066);
semctl(m,0,SETVAL,arg);
arg.val=1;
semctl(m,1,SETVAL,arg);
ret1=pthread_create(&
id1,NULL,(void*)pa,NULL);
if(ret1!
createpthreaderror!
exit
(1);
idis%d\n"
id1);
ret2=pthread_create(&
id2,NULL,(void*)pb,NULL);
if(ret2!
id2);
pthread_join(id1,NULL);
pthread_join(id2,NULL);
return0;
实验二Linux进程及同步
2.1实验目的与内容
2.1.1实验目的
了解并掌握Linux进程及同步
2.2.2实验内容
编程模拟实现誊抄;
创建三个誊抄进程;
基于共享内存建立缓冲区;
创建同步信号灯;
对各誊抄进程施加P、V操作;
2.2实验过程
2.2.1预备知识
①并发程序的誊抄:
get程序:
负责从输入序列f中读取字符并送到缓冲区s中;
copy程序:
把缓冲区s中的数据复制到缓冲区t中去;
put程序:
从缓冲区t中取出数据打印;
②誊抄的实现:
在相应的圆圈对应的进程中,通过修改箭头上对应序号的信号灯控制进程的运行,设有4个信号灯分别为0、1、2、3
在进程中对信号灯的控制可简写为:
get()
p(0);
get操作;
v
(2);
copy()
p
(1);
p
(2);
copy操作;
v(0);
v(3);
put()
p(3);
put操作;
v
(1);
通过设置信号灯0的初值和利用copy对信号灯0做v操作,使得当信号灯0的资源个数>
0时,可以进行get操作
通过设置信号灯1、2的初值和利用put对信号灯1做v操作、利用get对信号灯2做v操作,使得当信号灯1和信号灯2的资源个数均>
0时,可以进行copy操作
通过设置信号灯3的初值和利用copy对信号灯3做v操作,使得当信号灯3的资源个数>
0时,可以进行put操作
2.2.2实验测试与结果
运行结果:
图2
使用./main打开程序
2.3实验总结
通过此次实验了解了进程的创建,知道了进程与线程的区别。
编写的程序输出固定的几个字符,功能上没做好,欠佳,有待优化。
2.4源代码
头文件m.h
sys/sem.h>
semaphore.h>
sys/stat.h>
fcntl.h>
sys/shm.h>
#defineLOOPS10
#defineIPCKEY(key_t)0x11
#defineSHMKEY1(key_t)0x222
#defineSHMKEY2(key_t)0x333
voidP(intsemid,intindex);
voidV(intsemid,intindex);
intsemid;
voidV(intsemid,intindex)
structsembufsem;
sem.sem_num=index;
/*信号灯数组灯的一个索引,指明哪个信号灯*/
sem.sem_op=1;
/*加到当前信号灯的数值*/
sem.sem_flg=0;
sem,1);
return;
}
voidP(intsemid,intindex)
sem.sem_op=-1;
Main.c
#include"
m.h"
intmain(void)
intres,i;
structshmid_ds*buf;
intcmd;
intshmid1,shmid2;
char*s,*t;
pid_tp1,p2,p3;
semid=semget(IPCKEY,4,IPC_CREAT|0666);
res=semctl(semid,0,SETVAL,0);
res=semctl(semid,1,SETVAL,1);
res=semctl(semid,2,SETVAL,0);
res=semctl(semid,3,SETVAL,1);
shmid1=shmget(SHMKEY1,sizeof(char),IPC_CREAT|0666);
shmid1);
s=(char*)shmat(shmid1,NULL,NULL);
shmid2=shmget(SHMKEY2,sizeof(char),IPC_CREAT|0666);
t=(char*)shmat(shmid2,NULL,NULL);
if((p1=fork())==0){
execv("
./get"
NULL);
{
if((p2=fork())==0){
./copy"
if((p3=fork())==0){
./put"
p1=wait(&
p1);
p2=wait(&
p2);
p3=wait(&
p3);
if(semctl(semid,0,IPC_RMID,0)<
0)
error"
shmctl(shmid1,IPC_RMID,0);
shmctl(shmid2,IPC_RMID,0);
Get.c
inti=0;
intshmid1;
char*s,*t,str[]="
linux!
"
;
do
P(semid,1);
*s=str[i];
get\n"
i++;
V(semid,0);
}while(s[0]!
='
\0'
Copy.c
intj=0;
t=(char*)shmat(shmid2,NUL