求助:LINUX下关于进程同步(生产者-消费者)问题

xiangsoft2009 2011-10-27 09:11:03
上操作系统课,老师出了一个问题关于进程同步(生产者-消费者)
以下是题目:


实验内容:创建生产者和消费者两个进程,生产者
生产数据,消费者消费数据,使用信号
量保证生产者和消费者之间的同步和互
斥。
实验要求:调整每个进程的睡眠时间;
把每个进程中输出改为循环多次输出。

之后老师写出了部分代码,让我们根据下面的代码改写出符合要求的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include<sys/mman.h> //提供了共享内存的相关操作
#include<fcntl.h>
#include<sys/stat.h>

union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;

//生成信号量
int sem_creat(key_t key, int value)
{
union semun sem;
int semid;
sem.val = value;
semid = semget(key, 1, IPC_CREAT|0666);
if (-1 == semid)
{
printf("create semaphore error\n");
exit(-1);
}
semctl(semid, 0, SETVAL, sem);
return semid;
}

//删除信号量
void del_sem(int semid)
{
union semun sem;
sem.val = 0;
semctl(semid, 0, IPC_RMID, sem);
}

//p操作
int p(int semid)
{
struct sembuf sops={0, -1, SEM_UNDO};
return (semop(semid, &sops, 1));
}
//v操作
int v(int semid)
{
struct sembuf sops={0, +1, SEM_UNDO};
return (semop(semid, &sops, 1));
}

int buffer;
int *pData;
int value_read = 0, value_write = 0;
int full, empty;

void producer(key_t, key_t); //生产者所执行的代码
void consumer(int, int);

int main(void)
{
key_t keyFull, keyEmpty;
int fd;
pid_t pid;
void *ptr; //指向共享内存的指针

/* shm_open是一个POSIX函数,用来打开或创建一个与“/shm”关联的共享内存区 */
if((fd = shm_open("/shm", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
{
printf("shm_open error\n"); /* 出错提示 */
}
if(ftruncate(fd, sizeof(int)) == -1) /* 截短共享内存的长度到我们所需要的长度 */
{
printf("ftruncate error\n");
}
if((ptr = mmap(0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) /* 将共享内存映射到进程地址空间 */
{
printf("mmap error");
}

pData = (int *)ptr;
keyFull = ftok("/", 0);
keyEmpty = ftok("/", 1);
full = sem_creat(keyFull, 0);
empty = sem_creat(keyEmpty, 1);

switch(pid = fork())
{
case -1: /* 生成子进程失败 */
break;
case 0: /* 子进程 */
producer(keyFull, keyEmpty); /* 子进程是生产者 */
sleep(2);
break;
default:
consumer(full, empty); /* 父进程是消费者 */
break;
}

wait(0);
shm_unlink("/shm"); /* 删除共享内存区,程序中基本上保证了子进程先退出,因此父进程中无wait操作且这部操作放在父进程这里 */
//shmctl(shmid,IPC_RMID,&buf);
//del_sem(semid);
return 0;
}

/* 生产者写5次后退出 */
void producer(key_t keyFull, key_t keyEmpty)
{
full = semget(keyFull, 1, 0);
empty = semget(keyEmpty, 1, 0);

while(value_write < 5) /* 退出条件判定 */
{
printf("Prepare Write\n");
printf("empty Write P1 : %d\n", semctl(empty, 0, GETVAL, 0));
p(empty); /* 是否有空缓冲区,有则占有,无则被挂起,是原子操作 */
printf("empty Write P2 : %d\n", semctl(empty, 0, GETVAL, 0));
value_write++;
*pData = value_write;
printf("Write : %5d\n", *pData);
printf("full Write V1 : %d\n", semctl(full, 0, GETVAL, 0));
v(full); /* 写完一个缓冲区,释放信号量full(值加1) */
printf("full Write V2 : %d\n", semctl(full, 0, GETVAL, 0));
printf("Write Finish\n");
//sleep(1);
}
}

/* 消费者读5次后退出 */
void consumer(int full, int empty)
{
while(value_read < 5) /* 退出条件判定 */
{
printf("Prepare Read\n");
printf("full Read P1 : %d\n", semctl(full, 0, GETVAL, 0));
p(full); /* 获取信号量 */
printf("full Read P1 : %d\n", semctl(full, 0, GETVAL, 0));
printf("Read : %5d\n", *pData);
printf("empty Read V1 : %d\n", semctl(empty, 0, GETVAL, 0));
v(empty); /* 读完一个缓冲区,释放信号量empty(值加1) */
printf("empty Read V1 : %d\n", semctl(empty, 0, GETVAL, 0));
value_read ++;

printf("Read Finish\n");
}
}

...全文
276 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
modicum_lf 2011-10-28
  • 打赏
  • 举报
回复

实在很简单 ,两个线程 几条C语句 !
liang_cheng_jie 2011-10-28
  • 打赏
  • 举报
回复
我也不会,看高人援手
qq120848369 2011-10-28
  • 打赏
  • 举报
回复
感情楼主的仓库容量就1啊,真无聊,改大点撒.
缺媳妇的郝 2011-10-28
  • 打赏
  • 举报
回复
Mark
taylor_1313 2011-10-28
  • 打赏
  • 举报
回复
楼主加油,这还不是最难的那道题呢
dclchj 2011-10-28
  • 打赏
  • 举报
回复
又不难,还要别人帮你做作业么?
liutengfeigo 2011-10-28
  • 打赏
  • 举报
回复
才几行代码啊.
仔细看书看代码吧.
xiangsoft2009 2011-10-28
  • 打赏
  • 举报
回复
有哪位大牛知道啊 帮帮我呗
马上要交作业了啊

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧