《山东大学操作系统实验报告(共68页).docx》由会员分享,可在线阅读,更多相关《山东大学操作系统实验报告(共68页).docx(68页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、精选优质文档-倾情为你奉上操作系统实验报告计算机科学与技术学院目录一、 进程控制实验1.1 实验目的加深对于进程并发执行概念的理解。实践并发进程的创建和控制方法。观察和体验进程的动态特性。进一步理解进程生命期期间创建、变换、撤销状态变换的过程。掌握进程控制的方法,了解父子进程间的控制和协作关系。练习 Linux 系统中进程创建与控制有关的系统调用的编程和调试技术。1.2示例实验1.2.1实验内容以下实验示例程序应实现一个类似shell 子命令的功能,它可以从执行程序中启动另一个新的子进程并执行一个新的命令和其并发执行。1.2.2实验演示结果1.3独立实验1.3.1实验内容参考以上示例程序中建立
2、并发进程的方法,编写一个父子协作进程,父进程创建一个子进程并控制它每隔 3 秒显示一次当前目录中的文件名列表。1.3.2实验步骤1.3.2.1算法设计通过进程间的通讯,先创建一个父进程一个子进程,父进程沉睡3秒,子进程作为当前父进程再次创建一个他的子进程,当前子进程执行显示当前目录文件列表功能,执行execve()方法后死亡。While(1)在死循环里无限进行当前操作。即达到父进程创建一个子进程并控制它每隔3秒显示一次当前目录中的文件名列表的要求。1.3.2.2开发调试过程打开一终端命令行窗体,新建一个文件夹,在该文件夹中建立名为pctrl.c的C语言程序;再建立以下名为 pctrl.h 的
3、C 语言头文件;建立项目管理文件 Makefile;输入 make 命令编译连接生成可执行的 pctl 程序;执行 pctl 程序;再次执行带有子进程指定执行命令的 pctl 程序。1.3.2.3思考与分析1反映的进程的特征和功能,在真实的操作系统中是怎样实现和反映出教材中讲解的进程的生命期、进程的实体和进程状态控制的。对于进程概念和并发概念有哪些新的理解和认识?子进程是如何创建和执行新程序的?答:进程是一个可并发执行的程序在某数据集上的一次运行,是程序的一次运行过程。而程序只是进程的一个组成部分,进程是程序的执行过程。程序是静态的指令集合,而进程是动态的过程实体,是动态的产生、发展和消失。此
4、外所谓的进程并发执行是在宏观上并发,而在微观上交替执行。每个进程都用一个唯一的整数形式的进程标识符来标识,通过fork()系统调用,可创建新进程。新进程通过复制原来进程的地址空间而成。这种机制允许父子进程方便的进行通信。系统调用fork(),得到的子进程实际上是父进程的克隆体,要执行不同的新程序要使用系统调用exec(),以用新程序来取代进程的内存空间。其功能是根据参数指定的文件名找到程序文件,把它装入内存,覆盖原来进程的映像,形成一个不同于父进程的子进程。除了进程映像被更换之外,新进程的PID及其他PCB属性均保持不变,实际上是一个新进程“借壳”原来子进程开始运行。父进程可通过系统调用wai
5、tpid()来把自己移出就绪队列来等待子进程的终止。2信号的机理是什么?怎样利用信号实现进程控制?每个信号对应一个正整数常量(为signalnumber。定义在系统头文件中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。每个进程运行时,要通过信号机制来检查是否有信号到达。若有,中断正在执行的程序,转向该信号相对应的处理程序,已完成对事件的处理;处理结束后再返回到原来的断点继续执行。1.3.3实验演示结果1.3.4实验代码pctl.c文件:#include pctl.hint main()int pid_1,pid_2; /存放子进程号int status_
6、1,status_2; /存放子进程返回状态while(1)pid_1=fork() ; if(pid_10) / 建立子进程失败?printf(Create Process fail!n);exit(EXIT_FAILURE);if(pid_1 = 0) / 子进程执行代码段/报告父子进程进程号printf(I am Child-ls process %dnMy father is %dn,getpid(),getppid();/*getpid 返回当前进程的进程号,getppid 返回当前进程父进程的进程号*/pid_2=fork();if(pid_20)/ 建立子进程失败?printf(
7、Create Process fail!n);exit(EXIT_FAILURE);if(pid_2=0) / 子进程执行代码段/报告父子进程进程号printf(I am Child-ps process %dnMy father is %dn,getpid(),getppid();printf(%d child will Running: n,getpid(); /*子进程被键盘中断信号唤醒继续执行*/status_2=execve(/bin/ps,NULL,NULL);/装入并执行新的程序elseprintf(wait for the ps-child end%dn,pid_2);wait
8、pid(pid_2,&status_2,0);/等待子进程2结束/status 用于保留子进程的退出状态printf(%d child will Running: n,getpid(); /装入并执行新的程序char *argv=0,NULL;status_1 = execve(/bin/ls,argv,NULL);elseprintf(I am Parent process %dn,getpid();printf(wait for the ls-child end %dn,pid_1);waitpid(pid_1,&status_1,0);printf(child end,sleep.n);
9、sleep(3);/ sleep 函数会令调用进程的执行挂起睡眠3秒return EXIT_SUCCESS;pctl.h文件:#include #include #include #include #include #include /进程自定义的键盘中断信号处理函数typedef void (*sighandler_t) (int);void sigcat()printf(%d Process continuen,getpid();二、进程调度算法实验2.1 实验目的加深对进程调度概念的理解,体验进程调度机制的功能,了解 Linux 系统中进程调度策略的使用方法。 练习进程调度算法的编程和调
10、试技术。2.2示例实验2.2.1实验内容以下示例实验程序要测试在 linux 系统中不同调度策略和不同优先数的调度效果。2.2.2实验演示结果2.3独立实验2.3.1实验内容设有两个并发执行的父子进程,不断循环输出各自进程号、优先数和调度策略。进程初始调度策略均为系统默认策略和默认优先级。当某个进程收到 SIGINT信号时会自动将其优先数加 1,收到 SIGCSTP 信号时会自动将其优先数减 1。请编程实现以上功能。2.3.2实验步骤2.3.2.1算法设计建立一个父进程和一个子进程。通过第一章学习的进程控制相互发送信号。当按下 Ctrl+C 时,父进程实现优先级加 1。当按下Ctrl+Z 时,
11、子进程实现优先级减1。用 signal 系统调用将父进程注册一个本进程处理 SIGINT 的实现优先级加 1 的函数。子进程注册一个本进程处理SIGTSTP 的实现优先级减 1 的函数。当按下 Ctrl+Z 时,子进程做出响应,其优先级减 1;当按下Ctrl+C 时,父进程做出响应,父进程优先级加 1.然后再输出各自进程号、优先数和调度策略。以上行为通过 for()语句循环。2.3.2.2开发调试过程新建一个文件夹,在该文件夹中建立以下名为 pctl.c 的 C 语言程序。再建立以下名为pctl.h的 C 语言头文件。建立项目管理文件 Makefile 。输入 make 命令编译连接生成可执行
12、的pctl程序 。执行并调试 pctl程序2.3.2.3思考与分析进程调度调度策略和功能如下所示:SCHED_OTHER 默认的分时调度策略(值等于 0)SCHED_FIFO 先进先先出调度策略(值等于 1)SCHED_RR 时间片轮转调度策略(值等于 2)进程调度本质就是让谁先执行,让谁后执行。在真实的操作系统中,由调度策略和优先级决定谁先执行。Linux 的调度策略有三种,SCHED_OTHER 分时调度,SCHED_FIFO 先进先出,SCHED_RR 时间片轮转。后两种专用于对响应时间有特殊要求的进程,并且会抢先于 SCHED_OTHER 调度策略的进程而执行。通过这个系统调用设置进程
13、调度策略,intsched_setscheduler(pid_t pid,int policy,const struct sched_param *sp); 其中 pid 是进程号,policy 是以上说明的 3 种调度策略之一,sp 调度参数结构指针,调度参数结构主要存有调度优先数。进程优先数(prio)由静态优先级和动态优先级两部分组成。静态优先级与调度策略有关。动态优先级由以下系统调用设置,int setpriority(int which,int who,int prio);which 设置的对象。可以是:进程 PRIO_PROCESS进程组 PRIO_PGRP用户 PRIO_USER
14、who 对应设置对象的进程号或组号或用户号prio 要设置的进程优先数2.3.3实验演示结果2.3.4实验代码psched.c文件:#include#include#include#include #define SIGINT 2#define SIGTSTP 20void handler_sigint(int signo) /用于提升优先数printf(n%d 进程优先数增加 1n,getpid();setpriority(PRIO_PROCESS, getpid(),getpriority(PRIO_PROCESS,getpid() + 1);void handler_sigtstp(in
15、t signo) /用于降低优先数printf(n%d 进程优先数减小 1n,getpid();setpriority(PRIO_PROCESS, getpid(),getpriority(PRIO_PROCESS,getpid() - 1);int main() pid_t pid;if(pid = fork() 0) signal(SIGINT, handler_sigint); /父进程处理 Ctrl+Csignal(SIGTSTP, SIG_IGN); /忽略 Ctrl+Zelsesetpriority(PRIO_PROCESS, getpid(), 10); /设定子进程初始动态优先
16、级为 10,否则看不出效果signal(SIGTSTP, handler_sigtstp); /子进程处理Ctrl+Zsignal(SIGINT, SIG_IGN); /忽略 Ctrl+Cint i=1;while(i 0) printf(Im parent process, );elseprintf(Im child process, );printf(pid = %d, priority = %d, scheduler = %dn,getpid(), getpriority(PRIO_PROCESS,getpid(),sched_getscheduler(getpid();sleep(3)
17、;i+;其他文件同示例实验。二、 进程同步实验3.1 实验目的加深对并发协作进程同步与互斥概念的理解,观察和体验并发进程同步与互斥操作的效果,分析与研究经典进程同步与互斥问题的实际解决方案。了解 Linux 系统中 IPC 进程同步工具的用法,练习并发协作进程的同步与互斥操作的编程与调试技术。3.2示例实验3.2.1实验内容以下示例实验程序应能模拟多个生产/消费者在有界缓冲上正确的操作。它利用 N 个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。一旦缓冲区中有空单元,生产者进程就向空单
18、元中入写字符,并报告写的内容和位置。一旦缓冲区中有未读过的字符,消费者进程就从该单元中读出字符,并报告读取位置。生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。3.2.2实验演示结果3.3独立实验3.3.1实验内容抽烟者问题。假设一个系统中有三个抽烟者进程,每个抽烟者不断地卷烟并抽烟。抽烟者卷起并抽掉一颗烟需要有三种材料:烟草、纸和胶水。一个抽烟者有烟草,一个有纸,另一个有胶水。系统中还有两个供应者进程,它们无限地供应所有三种材料,但每次仅轮流提供三种材料中的两种。得到缺失的两种材料的抽烟者在卷起并抽掉一颗烟后会发信号通知供应者,让它继续提供另
19、外的两种材料。这一过程重复进行。 请用以上介绍的 IPC 同步机制编程,实现该问题要求的功能。3.3.2实验步骤3.3.2.1问题分析有两个供应者,有三个消费者。用于存放烟草,纸和胶水的公共缓冲区的大小是 3.存放顺序要指定。分别是烟草,纸和胶水。每一个供应者供应的物品有三种,(烟草+纸)(烟草+胶水)(纸+胶水) 。三个消费者分别需要三个里面的一种。约束:(1)某一时刻,只能有一个供应者,放入一对物品。(2) 某一时刻, 只能有一个消费者, 且要保证这个消费者恰好需要的就是刚刚生产的物品。(3)所有供应者提供这种物品之后,不论它要生产什么物品,只有等到消费者拿走了物品之后,才能继续生产。3.
20、3.2.2算法设计(1)供应者的上下文完全一样,在程序中 fork()子进程之后,让父进程和子进程并发执行供应者代码即可。(2)消费者有三个,且每个消费者需要的物品不同,所以不能使用同一个代码段。这样,就需要建立两个子进程和一个父进程同时并发执行。 然后在各自区域执行相似的但不同的代码段。(3)用信号灯实现同步和互斥约束。(4)创建公共缓冲区和指向首地址的指针/获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);/获取供应者放产品首位置指针 pput_ptrpput_ptr =
21、(int *)set_shm(pput_key,pput_num,shm_flg);3.3.2.3开发调试过程新建一个文件夹,在该文件夹中建立以下名为 ipc.h 的 C 语言头文件。再建立以下名为 ipc.c 的 C 语言头文件,实现头文件中申明的函数。再建立以下名为 producer.c 的 C 语言头文件,实现供应者的功能。再建立以下名为 consumer.c 的 C 语言头文件,实现消费者的功能。建立项目管理文件 Makefile 。输入 make 命令编译连接生成可执行的 producer 和 consumer 程序 。执行并调试 producer 和 consumer 程序。3.3
22、.2.4思考与分析进程之间的同步在该实验中是通过信号灯实现的。 进程之间为了同步而使用的信号灯,必须完全相同的在各自进程中创建。这样,这些信号灯就会被这些进程共享。然后通过执行信号灯的 up()和 down()操作.使得进程并发执行时保持同步。因为如果信号灯的值小于 0,那么这个进程会阻塞,这就是为什么能够同步。操作系统中,进程同步可以通过信号量机制实现。在本实验中,信号灯就是信号量 ,down()操作就是信号量的 wait 操作,up()操作就是信号量的 signal 操作。3.3.3实验演示结果3.3.4实验代码ipc.h文件:#include #include #include #inc
23、lude #include #include #include #define BUFSZ 256/建立或获取 ipc 的一组函数的原型说明int get_ipc_id(char *proc_file,key_t key);char *set_shm(key_t shm_key,int shm_num,int shm_flag);int set_msq(key_t msq_key,int msq_flag);int set_sem(key_t sem_key,int sem_val,int sem_flag);int down(int sem_id);int up(int sem_id);ty
24、pedef union semuns int val; Sem_uns;typedef struct msgbuf long mtype;char mtext1; Msg_buf;/生产消费者共享缓冲区即其有关的变量key_t buff_key;int buff_num;char *buff_ptr;/生产者放产品位置的共享指针key_t pput_key;int pput_num;int *pput_ptr;/消费者取产品位置的共享指针key_t cget_key;int cget_num;int *cget_ptr;/生产者有关的信号量key_t prod_key;key_t pmtx_k
25、ey;int prod_sem;int pmtx_sem;/消费者有关的信号量key_t c_PG_key;key_t c_TP_key;key_t c_TG_key;key_t cmtx_key;int c_PG_sem;int c_TP_sem;int c_TG_sem;int cmtx_sem;int sem_val;int sem_flg;int shm_flg;ipc.c文件:#include ipc.hint get_ipc_id(char *proc_file,key_t key)FILE *pf;int i,j;char lineBUFSZ,columBUFSZ;if(pf =
26、 fopen(proc_file,r) = NULL)perror(Proc file not open);exit(EXIT_FAILURE);fgets(line, BUFSZ,pf);while(!feof(pf)i = j = 0;fgets(line, BUFSZ,pf);while(linei = ) i+;while(linei != ) columj+ = linei+;columj = 0;if(atoi(colum) != key) continue;j=0;while(linei = ) i+;while(linei != ) columj+ = linei+;colum
27、j = 0;i = atoi(colum);fclose(pf);return i;fclose(pf);return -1;int down(int sem_id)struct sembuf buf;buf.sem_op = -1;buf.sem_num = 0;buf.sem_flg = SEM_UNDO;if(semop(sem_id,&buf,1) 0) perror(down error );exit(EXIT_FAILURE);return EXIT_SUCCESS;int up(int sem_id)struct sembuf buf;buf.sem_op = 1;buf.sem
28、_num = 0;buf.sem_flg = SEM_UNDO;if(semop(sem_id,&buf,1) 0) perror(up error );exit(EXIT_FAILURE);return EXIT_SUCCESS;int set_sem(key_t sem_key,int sem_val,int sem_flg)int sem_id;Sem_uns sem_arg;/测试由 sem_key 标识的信号灯数组是否已经建立if(sem_id = get_ipc_id(/proc/sysvipc/sem,sem_key) 0 )/semget 新建一个信号灯,其标号返回到 sem_
29、idif(sem_id = semget(sem_key,1,sem_flg) 0)perror(semaphore create error);exit(EXIT_FAILURE);/设置信号灯的初值sem_arg.val = sem_val;if(semctl(sem_id,0,SETVAL,sem_arg) 0)perror(semaphore set error);exit(EXIT_FAILURE);return sem_id;char * set_shm(key_t shm_key,int shm_num,int shm_flg)int i,shm_id;char * shm_bu
30、f;/测试由 shm_key 标识的共享内存区是否已经建立if(shm_id = get_ipc_id(/proc/sysvipc/shm,shm_key) 0 )/shmget 新建 一个长度为 shm_num 字节的共享内存,其标号返回到 shm_idif(shm_id = shmget(shm_key,shm_num,shm_flg) 0)perror(shareMemory set error);exit(EXIT_FAILURE);/shmat 将由 shm_id 标识的共享内存附加给指针 shm_bufif(shm_buf = (char *)shmat(shm_id,0,0) (
31、char *)0)perror(get shareMemory error);exit(EXIT_FAILURE);for(i=0; ishm_num; i+) shm_bufi = 0; /初始为 0/shm_key 标识的共享内存区已经建立,将由 shm_id 标识的共享内存附加给指针 shm_bufif(shm_buf = (char *)shmat(shm_id,0,0) (char *)0)perror(get shareMemory error);exit(EXIT_FAILURE);return shm_buf;int set_msq(key_t msq_key,int msq_
32、flg)int msq_id;/测试由 msq_key 标识的消息队列是否已经建立if(msq_id = get_ipc_id(/proc/sysvipc/msg,msq_key) 0 )/msgget 新建一个消息队列,其标号返回到 msq_idif(msq_id = msgget(msq_key,msq_flg) 0)perror(messageQueue set error);exit(EXIT_FAILURE);return msq_id;producer.c文件:#include ipc.hint main(int argc,char *argv)int rate;/可在在命令行第一
33、参数指定一个进程睡眠秒数,以调解进程执行速度if(argv1 != NULL) rate = atoi(argv1);else rate = 3; /不指定为 3 秒/共享内存使用的变量buff_key = 101;/缓冲区任给的键值buff_num = 3;/缓冲区任给的长度pput_key = 102;/生产者放产品指针的键值pput_num = 1; /指针数shm_flg = IPC_CREAT | 0644;/共享内存读写权限/获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址buff_ptr = (char *)set_shm(buff_key,buff_num,shm_
34、flg);/获取生产者放产品位置指针 pput_ptrpput_ptr = (int *)set_shm(pput_key,pput_num,shm_flg);/信号量使用的变量prod_key = 201;/生产者同步信号灯键值pmtx_key = 202;/生产者互斥信号灯键值c_PG_key = 301;/消费者同步信号灯键值c_TP_key = 302;/消费者互斥信号灯键值c_TG_key = 303;/消费者互斥信号灯键值sem_flg = IPC_CREAT | 0644;/生产者同步信号灯初值设为缓冲区最大可用量sem_val = 1;/获取生产者同步信号灯,引用标识存 pro
35、d_semprod_sem = set_sem(prod_key,sem_val,sem_flg);/消费者初始无产品可取,同步信号灯初值设为 0sem_val = 0;/获取消费者同步信号灯,引用标识存 cons_semc_PG_sem = set_sem(c_PG_key,sem_val,sem_flg);c_TP_sem = set_sem(c_TP_key,sem_val,sem_flg);c_TG_sem = set_sem(c_TG_key,sem_val,sem_flg);/生产者互斥信号灯初值为 1sem_val = 1;/获取生产者互斥信号灯,引用标识存 pmtx_sempm
36、tx_sem = set_sem(pmtx_key,sem_val,sem_flg);/循环执行模拟生产者不断放产品int pid;int i;pid = fork();if(pid = 0) while(1)int r = rand() % 3;if(r = 0) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr + 1 = P;buff_ptr*pput_ptr + 2 = G;sleep(rate);printf(%d 供 应 商
37、 提 供 : 纸 %c, 胶 水 %cn,getpid(),buff_ptr*pput_ptr +1 ,buff_ptr*pput_ptr + 2);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_PG_sem); else if(r = 1) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr = T;buff_ptr*pput_ptr + 2 = G;sleep(rate);printf(%d供应商提供:烟草%
38、c,胶水%cn,getpid(),buff_ptr*pput_ptr ,buff_ptr*pput_ptr + 2);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_TG_sem); else if(r = 2) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr + 1 = P;buff_ptr*pput_ptr = T;sleep(rate);printf(%d供应商提供:烟草%c,纸%cn,getpid(),
39、buff_ptr*pput_ptr ,buff_ptr*pput_ptr + 1);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_TP_sem); else while(1)int r = rand() % 3;if(r = 0) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr + 1 = P;buff_ptr*pput_ptr + 2 = G;sleep(rate);printf(%d 供 应 商 提 供
40、: 纸 %c, 胶 水 %cn,getpid(),buff_ptr*pput_ptr +1 ,buff_ptr*pput_ptr + 2);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_PG_sem); else if(r = 1) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr = T;buff_ptr*pput_ptr + 2 = G;sleep(rate);printf(%d供应商提供:烟草%c,胶水%
41、cn,getpid(),buff_ptr*pput_ptr ,buff_ptr*pput_ptr + 2);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_TG_sem); else if(r = 2) down(prod_sem);/如果另一生产者正在放产品,本生产者阻塞down(pmtx_sem);/用写一字符的形式模拟生产者放产品 ,报告本进程号和放入的字符及存放的位置buff_ptr*pput_ptr + 1 = P;buff_ptr*pput_ptr = T;sleep(rate);printf(%d供应商提供:烟草%c,纸%cn,getpid(),buff_
42、ptr*pput_ptr ,buff_ptr*pput_ptr + 1);/唤醒阻塞的生产者up(pmtx_sem);/唤醒阻塞的消费者up(c_TP_sem);return EXIT_SUCCESS;consumer.c文件:#include ipc.hint main(int argc,char *argv)int rate;/可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度if(argv1 != NULL) rate = atoi(argv1);else rate = 3; /不指定为 3 秒/共享内存 使用的变量buff_key = 101; /缓冲区任给的键值buff_n
43、um = 3; /缓冲区任给的长度cget_key = 103; /消费者取产品指针的键值cget_num = 1; /指针数shm_flg = IPC_CREAT | 0644; /共享内存读写权限/获取缓冲区使用的共享内存,buff_ptr 指向缓冲区首地址buff_ptr = (char *)set_shm(buff_key,buff_num,shm_flg);/获取消费者取产品指针,cget_ptr 指向索引地址cget_ptr = (int *)set_shm(cget_key,cget_num,shm_flg);/信号量使用的变量prod_key = 201; /生产者同步信号灯键值cm