山東大學作業系統實驗四
阿新 • • 發佈:2019-01-25
一.實驗內容:
ipc.c:
在linux系統中寫的中文拿到windows系統上是亂碼。
抽菸者問題。假設一個系統中有三個抽菸者程序,每個抽菸者不斷地捲菸並抽菸。抽菸者捲起並抽掉一顆煙需要有三種材料:菸草、紙和膠水。一個抽菸者有菸草,一個有紙,另一個有膠水。系統中還有兩個供應者程序,它們無限地供應所有三種材料,但每次僅輪流提供三種材料中的兩種。得到缺失的兩種材料的抽菸者在捲起並抽掉一顆煙後會發訊號通知供應者,讓它繼續提供另外的兩種材料。這一過程重複進行。 請用以上介紹的IPC同步機制程式設計,實現該問題要求的功能。
二.實驗思路:
1.生產者要能提供三種組合的原料:菸草,紙(SP),菸草,膠水(SG),或是紙和膠水(PG),這就需要一個隨機數,來決定提供哪種組合的原料。因為需要兩個供應者,所以要兩個生產者,兩個生產者生產的內容一樣,決定通過父子程序來實現。因為父子程序同時向一個臨界區裡寫東西,所以加上互斥。並且生產者能傳送三種訊號來喚醒不同的消費者。
2.需要三個消費者分別消費不同的內容,通過父程序建立兩個子程序來實現,父程序和兩個子程序分別執行不同的內容,這個和實驗一的內容很相似。三個程序在取東西對臨界區進行修改的時候要互斥。
3.因為開始時沒有資源,所以將喚醒消費者的三個訊號的訊號量初始值都設為0,因為生產者一次僅供應一個消費者,所以將消費者喚醒生產者的那個訊號量初始值設為1。控制互斥的兩個訊號量pmtx和cmtx都設為1。
程式碼如下:
ipc.h:
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<sys/sem.h> #include<sys/msg.h> #define BUFSZ 256 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:
producer.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))<(char*)0) { perror("get shareMemory error"); exit(EXIT_FAILURE); } for(i=0;i<shm_num;i++)shm_buf[i]=0; } if((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_flg) { int msq_id; if((msq_id=get_ipc_id("/proc/sysvipc/msg",msq_key))<0){ if((msq_id=msgget(msq_key,msq_flg))<0) { perror("messageQueue set error"); exit(EXIT_FAILURE); } } return msq_id; }
#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;
}
<pre name="code" class="objc">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系統上是亂碼。