作業系統實驗之生產者和消費者程式
阿新 • • 發佈:2018-12-09
這是我的作業系統實驗課的實驗之一,實驗要求“實現生產者和消費者程式”。
老師給了我們示例程式,要求我們自己修改除錯。程式程式碼如下,已經在本地linux系統上能夠正確執行。
p是模擬生產者,c是模擬消費者,q是退出
但是有一點,如果不是用q退出而是中途用ctrl+c的話,再次執行程式就是顯示"segment:File exists"
解決的方法是:
ipcs -s 顯示已存在的訊號量
ipcrm -s 刪除指定訊號量
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/types.h> #include <sys/sem.h> #include "shmpc.h" /* ******************************************************************************** * Name: main * Description: entry point ******************************************************************************** */ //var used to shared memory int shmid; void *myshm; struct myshm_st *buf; //var used to semaphore int semid; //common var int i,n; void producer() { printf ( "Create a Producer Process Success,%d\n",getpid()); //attach share memory myshm=shmat(shmid,NULL,0); if(myshm==(void *)-1) { perror("shmat"); exit(-1); } buf=(struct myshm_st *)myshm; //produe a product for(n=0;n<NSIZE;n++) { while(buf->m_count==BUFSIZE) { printf("[%d/P/%d]:Blocked!\n",getpid(),n); sleep(5); } //P struct sembuf action; action.sem_num=0; action.sem_op=-1; action.sem_flg=SEM_UNDO; if(semop(semid,&action,1)==-1) { perror("semop"); exit(0); } buf->m_count++; buf->m_buf[buf->m_in]='A'; sleep(1); buf->m_in=(buf->m_in+1)%BUFSIZE; printf("[%d/P/%d]:",getpid(),n); for(i=0;i<10;i++) { if(buf->m_buf[i]=='A') printf("|A"); else printf("| "); } printf("|\n"); //V action.sem_op=1; if(semop(semid,&action,1)==-1) { perror("semop"); exit(0); } sleep(DELT); } if(shmdt(myshm)==-1) perror("shmdt"); exit(0); } void consumer() { printf ( "Create a Consumer Process Success,%d\n",getpid()); //attach share memory myshm=shmat(shmid,NULL,0); if(myshm==(void *)-1) { perror("shmat"); exit(-1); } buf=(struct myshm_st *)myshm; //consum a product for(n=0;n<NSIZE;n++) { while(buf->m_count==0) { printf("[%d/C/%d]:Blocked!\n",getpid(),n); sleep(5); } //P struct sembuf action; action.sem_num=0; action.sem_op=-1; action.sem_flg=SEM_UNDO; if(semop(semid,&action,1)==-1) { perror("semop"); exit(0); } buf->m_count--; buf->m_buf[buf->m_out]=' '; buf->m_out=(buf->m_out+1)%BUFSIZE; printf("[%d/C/%d]:",getpid(),n); for(i=0;i<10;i++) { if(buf->m_buf[i]=='A') printf("|A"); else printf("| "); } printf("|\n"); //V action.sem_op=1; if(semop(semid,&action,1)==-1) { perror("semop"); exit(0); } sleep(DELT); } if(shmdt(myshm)==-1) perror("shmdt"); exit(0); } int main(int argc, char *argv[]) { char t; int ppid,cpid; //create a shared memery printf("Begin...\n"); shmid=shmget(MYKEY,sizeof(struct myshm_st),IPC_CREAT|0770); if( shmid==-1 ) { perror("shmget"); exit(-1); } //attach shared memory myshm=shmat(shmid,NULL,0); if(myshm==(void *)-1) { perror("shmat"); exit(-1); } //init shared memory buf=(struct myshm_st *)myshm; buf->m_count=0; buf->m_in=0; buf->m_out=0; //create a semaphore semid=semget(MYKEY,1,IPC_CREAT|IPC_EXCL|0770); if( semid==-1 ) { perror("semget"); exit(0); } union semun init_val; init_val.val=1; if( semctl(semid,0,SETVAL,init_val )==-1) { perror("semctl"); exit(0); } for(;;) { t=getchar(); switch ( t ) { case 'p' : //create a producer process ppid=fork(); if( ppid==0 ) { producer(); } break; case 'c': cpid=fork(); if( cpid==0 ) { consumer(); } break; case 's': //please add stat code here case 'q': if(shmdt(myshm)==-1) perror("shmdt"); if(shmctl(shmid,IPC_RMID,0)==-1) perror("shmctl"); if(semctl(semid,1,IPC_RMID,NULL)==-1) perror("semctl"); exit(0); } } }