Chinaunix首页 | 论坛 | 博客
  • 博客访问: 885263
  • 博文数量: 254
  • 博客积分: 5350
  • 博客等级: 大校
  • 技术积分: 2045
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 13:27
文章分类

全部博文(254)

文章存档

2015年(1)

2014年(9)

2013年(17)

2012年(30)

2011年(150)

2010年(17)

2009年(28)

2008年(2)

分类: C/C++

2012-02-15 14:16:07

进程同步实验

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

//ipc.h

#include
#include
#include
#include
#include
#include
#include
#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;

struct msgbuf {

long mtype;
int mtext[1];

}msg_buf;

key_t smoker_key;
int smoker_sem;

key_t supp_key;
int supp_sem;

key_t msg_key;
int msg_id;

int sem_val;
int sem_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\n");
    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\n");
    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);
    }
     if(semctl(sem_id,0,SETVAL,sem_arg) <0){
      perror("semaphore set error");
      exit(EXIT_FAILURE);
    }
   
}
return sem_id;
}
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;
}

//smoker.c

#include "ipc.h"
int main(int argc,char * argv[]){
int rate=3;
if(argv[1]!=NULL){
    rate=atoi(argv[1]);
}

smoker_key=101;
supp_key=201;
msg_key=301;
sem_flg=IPC_CREAT|0644;

sem_val=3;
smoker_sem=set_sem(smoker_key,sem_val,sem_flg);

sem_val=2;
supp_sem=set_sem(supp_key,sem_val,sem_flg);
msg_id=set_msq(msg_key,sem_flg);

while(1){
    down(supp_sem);
    msg_buf.mtype=3;
    msg_buf.mtext[0]=getpid();
    msgsnd(msg_id,&msg_buf,1,0);
    printf("Smoker %d just sent a request to the supply.\n",getpid());
    sleep(rate);
    msg_buf.mtype=2;
    msgrcv(msg_id,&msg_buf,1,2,0);
    printf("Smoker got ingredient from the supply %d.\n",msg_buf.mtext[0]);
    printf("Smoker %d just finished smoking.\n",getpid());
    up(smoker_sem);
}
return EXIT_SUCCESS;
}

//supply.c

#include "ipc.h"
int main(int argc,char *argv[]){
int rate=3;
if(argv[1]!=NULL){
    rate=atoi(argv[1]);
}

smoker_key=101;
supp_key=201;
msg_key=301;
sem_flg=IPC_CREAT|0644;

sem_val=3;
smoker_sem=set_sem(smoker_key,sem_val,sem_flg);

sem_val=2;
supp_sem=set_sem(supp_key,sem_val,sem_flg);
msg_id=set_msq(msg_key,sem_flg);

pid_t smk_pid;
while(1){
    msg_buf.mtype=3;
    msgrcv(msg_id,&msg_buf,1,3,0);
    smk_pid=msg_buf.mtext[0];
    printf("Supply %d just got a request from Smoker %d.\n",getpid(),smk_pid);
    down(smoker_sem);
    sleep(rate);
    msg_buf.mtype=2;
    msg_buf.mtext[0]=getpid();
    msgsnd(msg_id,&msg_buf,1,0);
    printf("Ingredient was sent from Supply %d to Smoker %d.\n",getpid(),smk_pid);
    up(supp_sem);
}
   
return EXIT_SUCCESS;
}

//removeipc.c

//删除已建立的消息队列和信号量。

#include "ipc.h"
int main(){
smoker_key=101;
supp_key=201;
msg_key=301;

int id;
Sem_uns sem_arg;
if((id=get_ipc_id("/proc/sysvipc/sem",supp_key))>=0){
    semctl(id,0,IPC_RMID,sem_arg);
}
if((id=get_ipc_id("/proc/sysvipc/sem",smoker_key))>=0){
    semctl(id,0,IPC_RMID,sem_arg);
}
if((id=get_ipc_id("/proc/sysvipc/msg",msg_key))>=0){
    msgctl(id,IPC_RMID,NULL);
}
return 0;
}
//Makefile

head = ipc.h
sup_srcs = supply.c ipc.c
sup_objs = supply.o ipc.o
smk_srcs = smoker.c ipc.c
smk_objs = smoker.o ipc.o
rm_srcs = removeipc.c ipc.c
rm_objs = removeipc.o ipc.o
opts = -g -c
all: supply smoker removeipc
smoker: $(smk_objs)
gcc $(smk_objs) -o smoker
supply: $(sup_objs)
gcc $(sup_objs) -o supply
removeipc: $(rm_objs)
gcc $(rm_objs) -o removeipc
removeipc.o: $(rm_srcs)
gcc $(opts) $(rm_srcs)
smoker.o: $(smk_srcs)
gcc $(opts) $(smk_srcs)
supply.o: $(sup_srcs)
gcc $(opts) $(sup_srcs)
clean:
rm *.o supply smoker

阅读(2529) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~