[xyos]信号量实现PV操作

9 views
Skip to first unread message

harryxiyou

unread,
Sep 24, 2011, 5:42:38 AM9/24/11
to xiyouo...@googlegroups.com
以下是以信号量的形式实现的PV操作,如有不足之处,请指正。

/*
 *  src/process_control/producer_consumer.c
 *
 *
 *  Harry Wei <harry...@gmail.com> (C) 2011
 */
#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!


Reply all
Reply to author
Forward
0 new messages