山东大学linux实验报告,山东大学操作系统实验四

一.实验内容:

抽烟者问题。假设一个系统中有三个抽烟者进程,每个抽烟者不断地卷烟并抽烟。抽烟者卷起并抽掉一颗烟需要有三种材料:烟草、纸和胶水。一个抽烟者有烟草,一个有纸,另一个有胶水。系统中还有两个供应者进程,它们无限地供应所有三种材料,但每次仅轮流提供三种材料中的两种。得到缺失的两种材料的抽烟者在卷起并抽掉一颗烟后会发信号通知供应者,让它继续提供另外的两种材料。这一过程重复进行。 请用以上介绍的IPC同步机制编程,实现该问题要求的功能。

二.实验思路:

1.生产者要能提供三种组合的原料:烟草,纸(SP),烟草,胶水(SG),或是纸和胶水(PG),这就需要一个随机数,来决定提供哪种组合的原料。因为需要两个供应者,所以要两个生产者,两个生产者生产的内容一样,决定通过父子进程来实现。因为父子进程同时向一个临界区里写东西,所以加上互斥。并且生产者能发送三种信号来唤醒不同的消费者。

2.需要三个消费者分别消费不同的内容,通过父进程创建两个子进程来实现,父进程和两个子进程分别执行不同的内容,这个和实验一的内容很相似。三个进程在取东西对临界区进行修改的时候要互斥。

3.因为开始时没有资源,所以将唤醒消费者的三个信号的信号量初始值都设为0,因为生产者一次仅供应一个消费者,所以将消费者唤醒生产者的那个信号量初始值设为1。控制互斥的两个信号量pmtx和cmtx都设为1。

代码如下:

ipc.h:

#include#include#include#include#include#include#include#define BUFSZ256

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);

typedef union semuns{

int val;

}Sem_uns;

typedef struct msgbuf{

long mtype;

char mtext[1];

}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;

//producer semaphore

key_t prod_key;

key_t pmtx_key;

int prod_sem;

int pmtx_sem;

//consumer semaphore

key_t c_PG_key;

key_t c_SG_key;

key_t c_SP_key;

key_t cmtx_key;

int c_PG_sem;

int c_SG_sem;

int c_SP_sem;

int cmtx_sem;

int sem_val;

int sem_flg;

int shm_flg;

ipc.c:

#include "ipc.h"

int get_ipc_id(char *proc_file,key_t key)

{

FILE *pf;

int i,j;

char line[BUFSZ],colum[BUFSZ];

if((pf=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(line[i]==' ') i++;

while(line[i]!=' ') colum[j++]=line[i++];

colum[j]='\0';

if(atoi(colum)!=key) continue;

j=0;

while(line[i]==' ') i++;

while(line[i]!=' ') colum[j++]=line[i++];

colum[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_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;

if((sem_id=get_ipc_id("/proc/sysvipc/sem",sem_key))<0)

{

if((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_buf;

if((shm_id=get_ipc_id("/proc/sysvipc/shm",shm_key))<0)

{

if((shm_id=shmget(shm_key,shm_num,shm_flg))<0)

{

perror("shareMemory set error");

exit(EXIT_FAILURE);

}

if((shm_buf=(char*)shmat(shm_id,0,0))producer.c:

#include"ipc.h"

int main(int argc,char*argv[]){

int rate;

if(argv[1]!=NULL) rate=atoi(argv[1]);

else rate=3;

buff_key=101;

buff_num=8;

pput_key=102;

pput_num=1;

shm_flg=IPC_CREAT|0644;

buff_ptr=(char*)set_shm(buff_key,buff_num,shm_flg);

pput_ptr=(int*)set_shm(pput_key,pput_num,shm_flg);

prod_key=201;

pmtx_key=202;

c_PG_key=301;

c_SP_key=302;

c_SG_key=303;

sem_flg=IPC_CREAT|0644;

sem_val=1;

prod_sem=set_sem(prod_key,sem_val,sem_flg);

sem_val=0;

c_PG_sem=set_sem(c_PG_key,sem_val,sem_flg);

c_SG_sem=set_sem(c_SG_key,sem_val,sem_flg);

c_SP_sem=set_sem(c_SP_key,sem_val,sem_flg);

sem_val=1;

pmtx_sem=set_sem(pmtx_key,sem_val,sem_flg);

int pid;

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渚涘簲鍟嗘彁渚涳細绾?c,鑳舵按%c\n",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]='S';

buff_ptr[*pput_ptr+2]='G';

sleep(rate);

printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+2);

up(pmtx_sem);

up(c_SG_sem);

}

else if(r==2){

down(prod_sem);

down(pmtx_sem);

buff_ptr[*pput_ptr]='S';

buff_ptr[*pput_ptr+1]='P';

sleep(rate);

printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,绾?c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+1);

up(pmtx_sem);

up(c_SP_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渚涘簲鍟嗘彁渚涳細绾?c,鑳舵按%c\n",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]='S';

buff_ptr[*pput_ptr+2]='G';

sleep(rate);

printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,鑳舵按%c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+2);

up(pmtx_sem);

up(c_SG_sem);

}

else if(r==2){

down(prod_sem);

down(pmtx_sem);

buff_ptr[*pput_ptr]='S';

buff_ptr[*pput_ptr+1]='P';

sleep(rate);

printf("%d渚涘簲鍟嗘彁渚涳細鐑?c,绾?c\n",getpid(),buff_ptr[*pput_ptr],buff_ptr[*pput_ptr]+1);

up(pmtx_sem);

up(c_SP_sem);}}

}

return EXIT_SUCCESS;

}

consumer.c:

#include"ipc.h"

int main(int argc,char*argv[]){

int rate;

if(argv[1]!=NULL) rate=atoi(argv[1]);

else rate=3;

buff_key=101;

buff_num=3;

cget_key=103;

cget_num=1;

shm_flg=IPC_CREAT|0644;

buff_ptr=(char*)set_shm(buff_key,buff_num,shm_flg);

cget_ptr=(int*)set_shm(cget_key,cget_num,shm_flg);

prod_key=201;

pmtx_key=202;

c_PG_key=301;

c_SP_key=302;

c_SG_key=303;

sem_flg=IPC_CREAT|0644;

sem_val=1;

prod_sem=set_sem(prod_key,sem_val,sem_flg);

sem_val=0;

c_PG_sem=set_sem(c_PG_key,sem_val,sem_flg);

c_SG_sem=set_sem(c_SG_key,sem_val,sem_flg);

c_SP_sem=set_sem(c_SP_key,sem_val,sem_flg);

sem_val=1;

cmtx_sem=set_sem(cmtx_key,sem_val,sem_flg);

int pid1,pid2;

if((pid1=fork())==0){

while(1){

down(c_PG_sem);

down(cmtx_sem);

sleep(rate);

printf("%d鏈夌儫鑽夌殑鍚哥儫鑰呬粠渚涘簲鍟嗗緱鍒扮焊%c,鑳舵按%c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr+1],buff_ptr[*cget_ptr]+2);

up(cmtx_sem);

up(prod_sem);}}

else if((pid2=fork())==0){

while(1){

down(c_SG_sem);

down(cmtx_sem);

sleep(rate);

printf("%d鏈夌焊鐨勫惛鐑熻€呬粠渚涘簲鍟嗗緱鍒扮儫%c,鑳舵按%c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr],buff_ptr[*cget_ptr]+2);

up(cmtx_sem);

up(prod_sem);}}

else{

while(1){

down(c_SP_sem);

down(cmtx_sem);

sleep(rate);

printf("%d鏈夎兌姘寸殑鍚哥儫鑰呬粠渚涘簲鍟嗗緱鍒扮儫%c,绾?c寮€濮嬪惛鐑焅n",getpid(),buff_ptr[*cget_ptr],buff_ptr[*cget_ptr]+1);

up(cmtx_sem);

up(prod_sem);}}

return EXIT_SUCCESS;

}

在linux系统中写的中文拿到windows系统上是乱码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3.4 独立实验 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 父进程收到 进程收到 由键盘 由键盘 Ctrl+CCtrl+C Ctrl+C 发 出的 SIGINT SIGINTSIGINTSIGINTSIGINT信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 1,子进程 子进程 收到 由键盘 由键盘 Ctrl+ZCtrl+Z Ctrl+Z发出的 SIG SIGTSTP STP信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 1。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值