集美大学计算机工程学院实验报告
课程名称:操作系统 实验编号: 实验三 班级:计算12 上机实践日期:2015.5 一、实验目的
1、掌握用Linux信号灯集机制实现两个进程间的同步问题。 2、共享函数库的创建 二、实验环境
Ubuntu-VMware、Linux 三、实验内容
? 需要的信号灯: System V信号灯实现
? 用于控制司机是否可以启动车辆的的信号灯 S1=0 ? 用于控制售票员是否可以开门的信号灯 S2=0
指导教师:王丰 实验名称:进程同步 姓名:
上机实践时间: 2学时
实验成绩: 学号:
System V信号灯实现说明
□ System V的信号灯机制属于信号灯集的形式, 一次可以申请多个信号灯. □ 同样利用ftok()生成一个key: semkey=ftok(path,45); □ 利用key申请一个包含有两个信号灯的信号灯集, 获得该集的id semid=semget(semkey,2,IPC_CREAT | 0666); □ 定义一个联合的数据类型 union semun{ int val;
struct semid_ds *buf; ushort *array; };
□ 利用semctl()函数对信号灯初始化,参数有: 信号灯集的id: semid 要初始化的信号灯的编号:sn 要设定的初始值:val
void seminit(int semid, int val,int sn) {
union semun arg; arg.val=val;
semctl(semid,sn,SETVAL,arg);
}
? 利用初始化函数,初始化信号灯:
seminit(semid,0,0);//用来司机启动汽车的同步 seminit(semid,0,1);//用来售票员开门的同步控制
□ 利用semop()函数, 对信号灯实现V操作:sembuf是一个在头部文件中的预定义结构、semid—信号灯集id, sn—要操作的信号灯编号
void semdown(int semid,int sn) {/* define P operating*/ struct sembuf op; op.sem_num=sn;
op.sem_op=-1;//P操作为-1 op.sem_flg=0; semop(semid,&op,1); }
2、Linux的静态和共享函数库
·Linux生成目标代码: gcc -c 源程序文件名(将生成一个与源程序同名的.o目标代码文件。)
·直接用目标代码文件生成可运行文件:gcc –o可执行文件名 目标代码文件 目标代码文件 ?? 源程序文件。
·Linux C有两种风格的函数库:静态函数库、共享函数库 ·生成一个静态函数库
ar r libtools.a m1.o m2.o m3.o ?? ar --Linux的归档命令。
r—表示生成一个名字为libtools.a的静态函数库
·使用自己创建的静态函数库:gcc -o可执行文件名源程序 目标模块 静态函数库名 ·在链接时也可以使用如下参数:gcc 源程序 目标模块 -L函数库位置 -l函数库名 ·生成自己的共享函数库:
生成共享函数库和生成一个程序一样简单。
gcc m1.o m2.o ?? mn.o –shared -o共享函数库名
·使用自己的共享函数库:在文件“/etc/ld.so.conf”设定(具有root权限) ·运行/sbin/ldconfig,用文件/etc/ld.so.conf的内容更新缓存文件/etc/ld.so.cache
四、实验步骤
1、信号灯集机制实现司机与售票员问题
#include
int val;//仅用于SETVAL命令
struct semid_ds *buf;//用于IPC_SET等命令 ushort *array;//用于SETALL等命令 };
//用于信号灯初始化 //semid--信号灯的ID
//val--欲设置的信号灯初值 //sn--信号灯集的分量
void seminit(int semid,int val,int sn) {
union semun arg; arg.val=val;
semctl(semid,sn,SETVAL,arg); };
//实现信号灯的P操作 //semid--信号灯的ID //sn--信号灯集的分量
void semdown(int semid,int sn) {/* define P operating*/ struct sembuf op; op.sem_num=sn;
op.sem_op=-1;//P操作为-1 op.sem_flg=0;
semop(semid,&op,1); }
//实现信号灯的V操作
seminit(semid,0,1);//对信号灯集的1号分量进行初始化 if(fork()==0) //Create a process {//子进程作为驾驶员进程 do{
semdown(semid,0);//等待售票员关门
printf(\ printf(\
rrand=1+(int)(6.0*rand()/(RAND_MAX+1.0));//产生一个(1-6)的随机数表示车辆的行驶时间
sleep(rrand);
printf(\ semup(semid,1);//唤醒售票员 }while(1); } else
{//父进程作为售票员进程 do{
printf(\