本文共 3920 字,大约阅读时间需要 13 分钟。
这是我的操作系统实验课的实验之一,实验要求“实现生产者和消费者程序”。
老师给了我们示例程序,要求我们自己修改调试。程序代码如下,已经在本地linux系统上能够正确运行。
p是模拟生产者,c是模拟消费者,q是退出
但是有一点,如果不是用q退出而是中途用ctrl+c的话,再次运行程序就是显示"segment:File exists"
解决的方法是:
ipcs -s 显示已存在的信号量
ipcrm -s 删除指定信号量
#include#include #include #include #include #include #include #include "shmpc.h"/* ******************************************************************************** * Name: main * Description: entry point ******************************************************************************** *///var used to shared memoryint shmid;void *myshm;struct myshm_st *buf;//var used to semaphoreint semid;//common varint 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 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 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); } }}
shampc.h
/* * Description limited buffer */#define BUFSIZE 10#define MYKEY 9000#define MUTEX 9001#define FULL 9002#define EMPTY 9003#define NSIZE 5 //number of item each child #define DELT 1 //interval between two itemstruct myshm_st{ int m_count; int m_in; int m_out; char m_buf[BUFSIZE];};union semun{ int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */};