集美大学计算机工程学院实验报告课程名称:操作系统指导教师:王丰实验成绩:实验编号:实验三实验名称:进程同步班级:计算12姓名:学号:上机实践日期:2015.5上机实践时间:2学时一、实验目的1、掌握用Linux信号灯集机制实现两个进程间的同步问题。2、共享函数库的创建二、实验环境Ubuntu-VMware、Linux三、实验内容需要的信号灯:SystemV信号灯实现用于控制司机是否可以启动车辆的的信号灯S1=0用于控制售票员是否可以开门的信号灯S2=0SystemV信号灯实现说明□SystemV的信号灯机制属于信号灯集的形式,一次可以申请多个信号灯.□同样利用ftok()生成一个key:semkey=ftok(path,45);□利用key申请一个包含有两个信号灯的信号灯集,获得该集的idsemid=semget(semkey,2,IPC_CREAT|0666);□定义一个联合的数据类型unionsemun{intval;structsemid_ds*buf;ushort*array;};□利用semctl()函数对信号灯初始化,参数有:信号灯集的id:semid要初始化的信号灯的编号:sn要设定的初始值:valvoidseminit(intsemid,intval,intsn){unionsemunarg;arg.val=val;semctl(semid,sn,SETVAL,arg);}利用初始化函数,初始化信号灯:seminit(semid,0,0);//用来司机启动汽车的同步seminit(semid,0,1);//用来售票员开门的同步控制□利用semop()函数,对信号灯实现V操作:sembuf是一个在头部文件中的预定义结构、semid—信号灯集id,sn—要操作的信号灯编号voidsemdown(intsemid,intsn){/*definePoperating*/structsembufop;op.sem_num=sn;op.sem_op=-1;//P操作为-1op.sem_flg=0;semop(semid,&op,1);}2、Linux的静态和共享函数库·Linux生成目标代码:gcc-c源程序文件名(将生成一个与源程序同名的.o目标代码文件。)·直接用目标代码文件生成可运行文件:gcc–o可执行文件名目标代码文件目标代码文件……源程序文件。·LinuxC有两种风格的函数库:静态函数库、共享函数库·生成一个静态函数库arrlibtools.am1.om2.om3.o……ar--Linux的归档命令。r—表示生成一个名字为libtools.a的静态函数库·使用自己创建的静态函数库:gcc-o可执行文件名源程序目标模块静态函数库名·在链接时也可以使用如下参数:gcc源程序目标模块-L函数库位置-l函数库名·生成自己的共享函数库:生成共享函数库和生成一个程序一样简单。gccm1.om2.o……mn.o–shared-o共享函数库名·使用自己的共享函数库:在文件“/etc/ld.so.conf”设定(具有root权限)·运行/sbin/ldconfig,用文件/etc/ld.so.conf的内容更新缓存文件/etc/ld.so.cache四、实验步骤1、信号灯集机制实现司机与售票员问题#includesys/types.h#includesys/ipc.h#includesys/sem.h#includestdio.h#includetime.h#includestdlib.hunionsemun{intval;//仅用于SETVAL命令structsemid_ds*buf;//用于IPC_SET等命令ushort*array;//用于SETALL等命令};//用于信号灯初始化//semid--信号灯的ID//val--欲设置的信号灯初值//sn--信号灯集的分量voidseminit(intsemid,intval,intsn){unionsemunarg;arg.val=val;semctl(semid,sn,SETVAL,arg);};//实现信号灯的P操作//semid--信号灯的ID//sn--信号灯集的分量voidsemdown(intsemid,intsn){/*definePoperating*/structsembufop;op.sem_num=sn;op.sem_op=-1;//P操作为-1op.sem_flg=0;semop(semid,&op,1);}//实现信号灯的V操作seminit(semid,0,1);//对信号灯集的1号分量进行初始化if(fork()==0)//Createaprocess{//子进程作为驾驶员进程do{semdown(semid,0);//等待售票员关门printf(Driver(pid:%d):Startthebus.\n,getpid());printf(Driver(pid:%d):Traveling....\n,getpid());rrand=1+(int)(6.0*rand()/(RAND_MAX+1.0));//产生一个(1-6)的随机数表示车辆的行驶时间sleep(rrand);printf(Driver(pid:%d):Arriveatastation.stop!\n,getpid());semup(semid,1);//唤醒售票员}while(1);}else{//父进程作为售票员进程do{printf(Conductor(pid:%d):Closealldoors.\n,getpid());semup(semid,0);//唤醒司机printf(Conductor(pid:%d):Ticketing...\n,getpid());semdown(semid,1);//等待汽车到站printf(Conductor(pid:%d):Openalldoors.\n,getpid());sleep(1);}while(1);}}//semid--信号灯的ID//sn--信号灯集的分量voidsemup(intsemid,intsn){/*defineVoperating*/structsembufop;op.sem_num=sn;op.sem_op=1;//V操作为1op.sem_flg=0;semop(semid,&op,1);}main(){key_tsemkey;char*pathname=./driver.c;intsemid;intrrand;srand((int)time(0));//用于产生随机延时semkey=ftok(pathname,45);if(semkey==-1){printf(Error:createakeyerror!\n);exit(-1);}semid=semget(semkey,2,IPC_CREAT|0666);if(semid==-1){printf(Error:createsemaphoreerror!\n);exit(-1);}seminit(semid,0,0);//对信号灯集的0号分量进行初始化实验截图:2、创建静态函数库(1)vifuns.cgcc–cfuns.c生成–o文件(2)arrlibtools.afuns.o创建静态函数库文件,用artvlibtools.a显示库中目标模块的详细信息(3)vim1.c编写一个主函数,调用函数库gcc–om1ml.c–L.–ltools编译./m1运行文件创建共享函数库(1)gccfuns.o–shared–olibtoos.so创建共享函数库(2)gcc–om1ml.c–L.–ltools./ml优先连接动态函数库(3)vi/etc/ld.so.conf添加当前目录运行/sbin/ldconfig把设置的放入内存./m1:五、实验小结1、通过本次实验,掌握用Linux信号灯集机制实现两个进程间的同步问题以及共享函数库的创建。2、关于SystemV信号灯的知识掌握的不够全面,以致在实现同步的过程中花了很多时间,还需多加强。3、基本掌握了创建静态函数库和动态函数库的基本方法,但对Linux的函数库中静态和共享的区别理解的还不够透彻。