/*
* src/process_control/producer_consumer.c
*
*
*/
#include <glib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <sys/sem.h>
#include "semun.h"
#undef P
#undef V
/*
* The following program is just for demonstrating
* producer-consumer model with pv-operation concurrently.
* This has been included by my libxyos, you can use it
* by linking this library and include the relevant header
* file. These codes are all under the GPL v3 or later
* version so feel free to change it for yourself.
*/
#if 0
#ifdef _SEMUN_H
#define _SEMNU_H
union semnu {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
#endif
#endif
/*
* p: the p operation for applying resource.
* @para semid: the semaphore's id.
* @para index: the semaphore's index.
* @return: if error happens return -1, return 0 is right.
*/
static int p(int semid, int index)
{
#if 1
struct sembuf buf = {
.sem_num = 0, /*semaphore number*/
.sem_op = -1, /*semaphore operation*/
.sem_flg = SEM_UNDO /*operation flags*/
};
#endif
if (0 > index) {
g_message("%s -- index of the semaphore is invalid!\n", __func__);
return -1;
}
buf.sem_num = index;
if (-1 == semop(semid, &buf, 1)) {
g_message("%s -- process %d p operation failed!\n", __func__, getpid());
return -1;
}
return 0;
}
/*
* v: the v operation for releasing resource.
* @para semid: the semaphore's id.
* @para index: the semaphore's index.
* @return: if error happens return -1, return 0 is right.
*/
static int v(int semid, int index)
{
#if 1
struct sembuf buf = {
.sem_num = 0,
/* release resource, add the buf.sem_op to semval */
.sem_op = 1,
.sem_flg = SEM_UNDO
};
#endif
if (0 > index) {
g_message("%s -- index of the semaphore is invalid!\n", __func__);
return -1;
}
buf.sem_num = index;
if (-1 == semop(semid, &buf, 1)) {
g_message("%s -- process %d v operation failed!\n", __func__, getpid());
return -1;
}
return 0;
}
/*
* producer_consumer_pv: use the pv operations for access cs.
* @para pid_num: the amount of accessing process.
* @return: if error happens return -1, return 0 is right.
*/
int producer_consumer_pv(uint32_t pid_num)
{
pid_t pid;
key_t key;
uint32_t i = 0;
uint32_t j = 0;
uint32_t proj_id = 2;
uint32_t semid = 0;
union semun arg;
// memset(&arg, 0, sizeof(union semun));
/* convert a pathname and a project identifier to a system v ipc key */
if (-1 == (key = ftok(".", proj_id))) {
g_message("%s -- generating IPC key failed!\n", __func__);
return -1;
}
/* get a semaphore set identifier */
if (-1 == (semid = semget(key, 1, IPC_CREAT | 0666))) {
g_message("%s -- creating semaphore set failed!\n", __func__);
return -1;
}
arg.val = 1;
/* semaphore control operations */
if (-1 == semctl(semid, 0, SETVAL, arg)) {
g_message("%s -- set semval failed!\n", __func__);
return -1;
}
for (i = 0; i < pid_num; i++) {
pid = fork();
if (0 > pid) {
g_message("%s -- fork error!\n", __func__);
return -1;
} else if (0 == pid) {
if (-1 == (semid = semget(key, 1, 0))) {
exit(EXIT_FAILURE);
}
#if defined(P)
if (-1 == p(semid, 0)) {
exit(EXIT_FAILURE);
}
#endif
g_print("%s -- process %d enter the critical section!!!\n", __func__, getpid());
sleep(1);
g_print("%s -- process %d access the critical section!!!\n", __func__, getpid());
sleep(1);
g_print("%s -- process %d leave the critical section!!!\n", __func__, getpid());
sleep(1);
#if defined(V)
if (-1 == v(semid, 0)) {
exit(EXIT_FAILURE);
}
#endif
return 0;
}
}
for (i = 0; i < pid_num; i++) {
wait(NULL);
}
if (-1 == semctl(semid, 0, IPC_RMID, 0)) {
g_message("%s -- destroy the sem set failed!\n", __func__);
return -1;
}
return 0;
}
--
Thanks.
Best Regards.
Harry Wei.
Do what u like!