操作系统第五个实验报告 15.docx
- 文档编号:29040385
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:14
- 大小:51.97KB
操作系统第五个实验报告 15.docx
《操作系统第五个实验报告 15.docx》由会员分享,可在线阅读,更多相关《操作系统第五个实验报告 15.docx(14页珍藏版)》请在冰豆网上搜索。
操作系统第五个实验报告15
甘肃政法学院
本科生实验报告
(五)
姓名:
xxx
学院:
信息工程学院
专业:
计算机科学与技术
班级:
2013级计算机科学与技术本科班
实验课程名称:
操作系统
实验日期:
2016年5月20日
开课时间:
2015-2016学年第二学期
甘肃政法学院实验管理中心印制
实验题目
进程的共享主存通信、进程的信号量通信
小组合作
否
姓名
谢慧敏
班级
2013级计算机科学与技术本科班
学号
201381010144
一、实验目的
1、了解和熟悉了共享存储机制;
2、加深对进程通信的理解。
3、熟悉消息通信机制、共享存储器通信机制,进一步认识其与信号量通信的区别。
二.实验环境
Windows7操作系统
Vmware软件
Redhatlinux操作系统
三、实验内容与步骤
一、进程的共享主存通信
1.共享主存段使用的数据结构
(1)共享主存段控制块(或共享主存段头)
每个共享主存段都有一个控制块,用来描述共享主存段的一些属性,共享主存段控制块定义在sys/shm.h中,其结构如下:
structshmid_ds
{
structipc_permshmperm;/*共享主存段访问控制结构*/
intshmsegsz;/*共享段以字节为单位的长度*/
structptentry*shmptbl;/*共享页表始址*/
ushortshmlpid;/*最近执行共享段操作的进程标识*/
ushortshmcpid;/*创建共享段的进程标识*/
ushortshmnattch;/*当前附件段号*/
ushortshmcnattch;/*主存中的附加段号*/
time_tshmatime;/*最近一次附件操作的时间*/
time_tshmdtime;/*最近一次与进程分离操作的时间*/
time_tshmctime;/*最近一次修改时间*/
}
为了便于管理,系统将维持的共享主存段组成一个表,共有SHMMNI=100个元素,其结构如下:
structshmid_dsshmen[SHMMNI];/*共享段表*/
其访问控制结构定义如下:
structipc_perm
{
key_tkey;
ushortuid;/*ownereuidandegid*/
ushortgid;
ushortcuid;
ushortcgid;
ushortmode;/*lower9bitsofshmflg*/
ushortseq/*sequencenumber*/
};
(2)共享主存段的数据结构
每个共享主存段都对应一个页表和允许的存取权限,结构如下;
structshmptds
{
intshmspte;/*开始也表项*/
intshmsflg;/*对共享段的读/写权限*/
}
每个进程最多允许6个共享主存段(SHMSEG=6).
2.申请一个共享主存段
参与通信的进程,通信前要先申请一个共享主存段,若是第一次申请,则要为其分配一个主存空间及页表,并对共享主存区控制块进行初始化,申请共享主存段调用语法如下:
#include
#include
intshmget(key_tkey,size_tsize,intshmflg)
其中,key为共享主存段的关键字,size是共享主存段字节长度,shmflg为创建和访问标志。
返回值:
成功时,为与key值相关的共享主存段的标识号,且大小是页对齐;失败时,为-1。
如果key的值为IPC_PRIVATE,或不为IPC_PRIVATE,创建的共享段与key无关,关键字由系统分配。
Shmflg由如下成分组成:
.IPC_CREAT,创建一个新段。
如果该标志没有设置,将查找与key相关的段,且该段允许用户访问。
.IPC_EXCL,与IPC_CREAT一起使用,确保创建一个新的共享段。
若该段已经存在,出错。
低9位为三类用户的访问方式的定义。
3.将共享段附加到申请通信的进程空间
对于已申请通信所需的共享段,进程需把它附加到自己的虚拟空间后才能对其进行读写,将共享段附加到申请通信的进程空间的函数调用语法:
#include
voidshmat(intshmid,void*shmadd,intshmflg);
这里shmid是进程调用shmget后返回的共享段标识号;shmadd是给出的应附加到进程虚空间的地址;shmflg为允许对共享段的访问方式。
返回值:
成功时为附加到进程地址空间的虚地址,失败时为-1。
连接到进程虚空间的地址规则为:
.shmadd为0,则将该共享段附加到系统选择的进程的第一个可用地址之后。
.shmadd为非0,如果shmflg指定了SHM_RND标志,则将该共享段附加shmadd取整后指定的地址上。
.shmadd为非0,如果shmflg未指定SHM_RND标志,则将该共享段附加shmadd指定的地址上。
通常将shmadd指定为0,由系统安排连接地址。
4.将共享段与进程之间解除链接
当进程不再需要共享段时,将其从它的地址空间拆下,调用语法为:
#include
intshmdt(void*shmaddr);
其中,shmaddr是共享段在进程地址空间的虚地址。
返回值为0。
5.对共享段进行控制
#include
intshmctl(intshmid,intcmd,struct_ds*buf);
返回值:
成功时为0,失败时为-1。
系统调用shmctl根据控制命令cmd对共享段进行控制。
cmd可能的取值有:
.IPC_STAT,将有关共享段的信息复制到具有shmid_ds结构的buf中;
.IPC_SET,用于用户和用户组,或对其存取权限进行修改,要求用户必须为超级用户或拥有者;
.IPC_RMID,用于标志删除共享段。
在共享段与所有进行分离时,实际进行删除;
.IPC_LOCK,在Linux环境下,将共享段锁在主存中;
.IPC_UNLOCK,在Linux环境下,允许将共享段锁换出主存。
二、进程的信号量
【预备知识】
在Linux中,一个或多个信号量构成一个信号量集合。
使用信号量机制用来实现进程之间的同步和互斥,允许并发进程一次对一组信号量进行相同或不同的操作。
每个P、V操作不限于减1或加1,而是可以加减任何整数。
在进程终止时,系统可根据需要自动消除所有被进程操作过的信号量的影响。
1.信号量机制中使用的数据结构
系统中的每个信号量都有一个数据结构定义在sys/sem.h中。
结构定义如下:
structsem
{
ushortsemval;/*信号量的当前值*/
shortsempid;/*最近一次对该信号操作的进程标识*/
ushortsemncnt;/*等待信号量值增加的进程数*/
ushortsemzcnt;/*等待信号量值等于0的进程数*/
}
2.信号量集合的数据结构
系统为每个信号集合保持一个头文件定义在sys/sem.h中。
结构定义如下:
structsemid_ds
{
structipc_permsem_perm;/*对信号量的访问方式,见消息缓冲*/
time_tsem_otime;/*最后操作信号量集合的时间*/
time_tsem_ctime;/*最后修改信号量集合的时间*/
structsem*sem_base;/*指向集合中第一个信号量的指针*/
ushortsem_nsems;/*集合中的信号量个数*/
}
3.信号量集合的建立
任何进程在使用信号量之前,通过使用如下函数申请建立一个信号量集合:
#include
#include
#include
intsemget(key_tkey,intnsems,intsemflg)
其中,key为用户进程指定的信号量集合的关键字,nsems为信号量集合中的信号量数,semflg为访问标志。
返回值:
成功时,返回信号量集合的标识号,失败时,返回-1。
semflg由以下成分组成:
·IPC_CREAT,创建一个新的信号量集合。
如果该标志没有设置,将查找于key相关的信号量集合。
·IPC_EXCL,与IPC_CREAT一起使用,确保创建一个新的信号量集合。
若该段已经存在,出错。
低9位为三类用户的访问方式的定义。
4.对信号量的操作
通过调用semop()函数,进程对一信号量集合中的一个或多个信号执行P/V操作,其操作命令由用户提供的信号操作模版(sembuf)定义,该模版的结构如下:
Structsembuf
{
ushortsem_num;/*信号量的序号*/
shortsem_op/*具体执行的操作(即P或V操作)*/
shortsem_flg;/*访问标志*/
}
调用语法为:
#include
intsemop(intsemid,structsembuf*sops,unsignednsops);
其中,semid是进程调用semget后返回的信号量集合的标识,sops是用户提供的信号量操作模版数组(sembuf)的指针,nsops为数组sembuf中的元素数(即一次需进行的操作数)。
正常返回值为0。
5.对信号量执行控制操作
当要读取和修改信号量集合的有关状态信息,或撤销信号量集合时,调用命令semctl()对信号量执行控制操作。
其调用语法为:
intsemctl(intsemid,intsemnum,intcmd,unionsemunarg);
其中,semid是信号量集合的标识,semnum是要处理信号量集合中的信号量序号,cmd为要执行的操作命令,arg为控制操作需要的参数,是一个指向联合semun的指针。
函数semctl成功返回时为0。
semun定义为:
unionsemun
{
intval;/*valueforSETVAL*/
structsemid_ds*buf;/*bufferforIPC_SET&IPC_STAT*/
ushortarray[];/*bufforforIPC_INFO*/
}arg;
cmd的可能取值有:
GETPID返回最近一个队信号量操作的进程标识
GETVAL返回索引为semnum的信号量的值
GETALL返回一个集合中所有信号量的值到arg.array中
GETNCNT返回睡眠等待信号量值为正的进程的数
GETZCNT返回睡眠等待信号量值为0的进程数
SETVAL设置索引为semnum的信号量的值为arg.val
SETALL按照数组arg.array,设置一个集合中所有信号量的值
IPC_STAT若为读,可将指定semid的信号量头结构读入arg.buf中获得信号量的值
IPC_SET按照arg.buf设置用户标识、组标识和访问权限。
若不是给定的有效用户标识,立即返回
IPC_RMID删除指定标识的信号量集合
四、实验过程与分析
一、进程的共享主存通信
1、编程实现一个是进程向共享段写信息的例子。
程序源代码:
#include
#include
#include
#defineSHMKEY75
#defineK1024
intshmid;
main()
{
inti,*pint;
char*addr;
externchar*shmat();
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);
/*申请创建一个16K大小的共享存储段,其标识号为SHMKEY*/
addr=shmat(shmid,0,0);/*缺省地址将共享段附加到系统指定位置*/
printf(“addrox%x\n”,addr);/*打印附加到进程地址空间的地址*/
pint=(int*)addr;
for(i=0;i<256;i++)
*pint++=i;/*向共享主存段写入0~255个数*/
pint=(int*)addr;
*pint=256;/*共享段第一个字中写入信息长度256,以便接收进程读*/
pause();/*暂停等待接收进程读*/
}
运行结果:
2、编程实现从共享段读信息的例子
程序源代码:
#include
#include
#include
#defineSHMKEY75
#defineK1024
intshmid;
main()
{
inti,*pint;
char*addr;
externchar*shmat();
shmid=shmget(SHMKEY,8*K,0777);/*由SHMKEY得到共享段标识号*/
addr=shmat(shmid,0,0);/*将共享段与本进程相连*/
pint=(int*)addr;
while(*pint==0);/*若共享区无信息时,在此等待*/
for(i=0;i<256;i++)
printf(“%d\n”,*pint++);
}
运行结果:
二、进程的信号量通信
1、编程实现多个进程对同一文件的互斥写入。
程序源代码:
#include
#include
#include
#include
#include
#include
#include
#defineNUM_PROCS5
#defineSEM_ID250
#defineFILE_NAME”/tmp/sem_MUTEX”/*互斥共享写入的文件名称*/
#defineDELAY400000
//各子进程互斥写文件的通用函数
voidupdate_file(intsem_set_id,char*file_name_path,intnumber)
{
structsembufsem_op;
FILE*file;
//相当于执行P操作,申请写文件
sem_op.sem_num=0;
sem_op.sem_op=-1;
sem_op.sem_flg=0;
semop(sem_set_id,&sem_op,1);
//向文件写,写入的数据是进程的标识
file=fopen(file_name_path,”w”);
if(file)
{
fprintf(file,”%d\n”,number);
printf(“%d\n”,number);
fclose(file);
}
//相当于执行V操作,释放文件的使用权
sem_op.sem_num=0;
sem_op.sem_op=1;
sem_op.sem_flg=0;
semop(sem_set_id,&sem_op,1);
}
//子进程准备写文件的通用函数
voiddo_child_loop(intsem_set_id,char*file_name)
{
pid_tpid=getpid();//得到本进程的标识
inti,j;
for(i=0;i<3;i++)
{
update_file(sem_set_id,file_name,pid);
for(j=0;j<200000;j++);/*暂停一段时间*/
}
}
//主函数
intmain(intargc,char**argv)
{
Intsem_set_id,child_pid;
unionsemunsem_val;
inti,rc;
//创建一个信号量集合,标识为225,只有一个信号量
sem_set_id=semget(SEM_ID,1,IPC_CREAT|0600);
if(sem_set_id==-1)
{
perror(“main’ssemgeterror”);
exit
(1);
}
//把该信号量的值设置为1
sem_val,val=1;
rc=semctl(sem_set_id,0,SETVAL,sem_val);
if(rc==-1)
{
perror(“main:
setcl”);
exit
(1);
}
//建立一些子程序,以便竞争并互斥地向文件中写
for(i=0;i { child_pid=fork(); switch(child_pid){ case-1: perror(“fork()”); exit(0); case0: do_child_loop(sem_set_id,FILE_NAME); exit(0); default: break; } }//创建子进程的循环结束 //父进程等待子进程结束 for(i=0;i<10;i++) { intchild_status; wait(&child_status); } printf(“mainisdone”); fflush(stdout); return0; } 运行结果: 实验分析 一、进程的共享主存通信 实验一该进程创建了长度为16K的共享主存段,并将共享段附加到了地址空间为addr的地址上。 然后从共享段的起始单元写入0~255个自然数,等待接收进程读。 实验二实验分析: 该进程先将所示进程创建的共享段连接到自己的地址空间(这里只共享其中的8K空间)。 之后,判断共享段是否有信息,若无,则等待,否则,读信息并进行显示。 二、进程的信号量通信 实验一实验分析: 该进程实现多个进程对同一文件的互斥写入。 五、实验总结 通过本次实验,我加深了对进程通信的理解;通过实验过程中熟悉和了解了消息通信机制、共享存储器通信机制,进一步认识其与信号量通信的区别。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统第五个实验报告 15 操作系统 第五 实验 报告