23,114
社区成员
发帖
与我相关
我的任务
分享
#include "apue.h"
#include <assert.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#define N 10
#define MUTEX 0
#define FULL 1
#define EMPTY 2
typedef union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
};
int num = 0;
int init_sem(int, int , int);
int up(int, int);
int down(int, int);
void producer(int);
void consumer(int);
int main (int argc, char *argv[])
{
int semid;
pid_t pid1, pid2;
if ((semid = semget(IPC_PRIVATE, 3, 0660)) < 0)
err_sys("semget error");
init_sem(semid, MUTEX, 1); /* mutex */
init_sem(semid, FULL, 0); /* full */
init_sem(semid, EMPTY, N); /* empty */
if ((pid1 = fork()) < 0 ) {
err_sys("fork error");
} else if( pid1 == 0) {
producer(semid); /* child1 producer */
} else {
if((pid2 = fork()) < 0 ){
err_sys("fork error");
} else if ( pid2 == 0) { /* child2 consumer */
consumer(semid);
} else {
if (waitpid(pid1, NULL, 0) != pid1 ||
waitpid(pid2, NULL, 0 ) != pid2)
err_sys("waitpid error");
}
}
if (semctl(semid, 0, IPC_RMID) < 0)
err_sys("semctl error");
exit(0);
}
int init_sem(int semid, int semnum, int val)
{
union semun unarg;
unarg.val = val;
if (semctl(semid, semnum, SETVAL, unarg) < 0)
err_sys("semctl error");
return 0;
}
int up(int semid, int semnum)
{
struct sembuf semoparray[1];
semoparray[0].sem_num = semnum;
semoparray[0].sem_op = 1;
semoparray[0].sem_flg = 0;
if (semop(semid, semoparray, 1) < 0)
err_sys("semop error");
return 0;
}
int down(int semid, int semnum)
{
struct sembuf semoparray[1];
semoparray[0].sem_num = semnum;
semoparray[0].sem_op = -1;
semoparray[0].sem_flg = 0; /* IPC_NOWAIT, SEM_UNDO(这个宏有什么作用?) */
if (semop(semid, semoparray, 1) < 0)
err_sys("semop error");
return 0;
}
void producer(int semid)
{
int i = 1000;
int sem1, sem2;
while (i--) {
assert((sem1 = semctl(semid, EMPTY, GETVAL, NULL))<= 10);
assert((sem2 = semctl(semid, FULL, GETVAL, NULL)) >= 0);
down(semid, EMPTY);
down(semid, MUTEX);
num++;
printf("producer num = %i \n", num);
printf("EMPTY = %i ; FULL = %i ; \n", sem1, sem2);
up(semid, MUTEX);
up(semid, FULL);
}
exit(0);
}
void consumer(int semid)
{
int i = 1000;
int sem1, sem2;
while (i--) {
assert((sem1 = semctl(semid, EMPTY, GETVAL, NULL))<= 10);
assert((sem2 = semctl(semid, FULL, GETVAL, NULL)) >= 0);
down(semid, FULL);
down(semid, MUTEX);
num--;
printf("consumer num = %i \n", num);
printf("EMPTY = %i ; FULL = %i ; \n", sem1, sem2);
up(semid, MUTEX);
up(semid, MUTEX);
up(semid, EMPTY);
}
exit(0);
}