여러 생산자와 여러 소비자문제...
글쓴이: jinguman / 작성시간: 화, 2008/11/18 - 10:07오후
혹시 위키백과에 나온..
--------------------------
* 생산자 프로세스
do {
...
아이템을 생산한다.
...
wait(empty); //버퍼에 빈 공간이 생길 때까지 기다린다.
wait(mutex); //임계 구역에 진입할 수 있을 때까지 기다린다.
...
아이템을 버퍼에 추가한다.
...
signal(mutex); //임계 구역을 빠져나왔다고 알려준다.
signal(full); //버퍼에 아이템이 있다고 알려준다.
} while (1);
* 소비자 프로세스
do {
wait(full); //버퍼에 아이템이 생길 때까지 기다린다.
wait(mutex);
...
버퍼로부터 아이템을 가져온다.
...
signal(mutex);
signal(empty); //버퍼에 빈 공간이 생겼다고 알려준다.
...
아이템을 소비한다.
...
} while (1);
-------------------------
위 알고리즘 써보신분 계신가요.. 그대로 프로그램을 짜서 테스트를 해 보면, 어느순간부터
세마포어 연산에러(정확히는 P연산에러)가 뜨는데, 도대체 이유를 모르겠네요;;;
사용 소스를 같이 올리니 검토 부탁드립니다.
------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#define MAX_Q_SIZE 10
#define MAX_PRODUCT_SIZE 1 // product process number
#define MAX_CUSTOMER_SIZE 1 // customer process number
#define MAX_PROCESS (MAX_PRODUCT_SIZE+MAX_CUSTOMER_SIZE)// total process number
/* init variable */
int sem_id; // for mutex, mutex = 1
int full_sem_id; // for empty semaphore, full = 0
int empty_sem_id; // for empty semaphore, empty = n
int temp = 0;
/* job process ft */
void tfunc_a(); // product process
void tfunc_b(); // customer process
/* sem ft */
int sysv_semget(char *tok, key_t sem_fixkey, int n_sem, int sem_value, int user_mode);
int sysv_semrm(int sem_id);
int sysv_semwait(int sem_id, int sem_idx);
int sysv_sempost(int sem_id, int sem_idx);
int sysv_semval(int sem_id, int sem_idx);
/* define of semaphore union struct */
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
/* Name : main
* Desc : Main function
* Argv : int argc, char *argv
* Ret : void
*/
int main(int argc,char *argv[])
{
int i,status;
/* sem id getting */
sem_id = sysv_semget(NULL, 0x12340001, 1, 1, 0660);
empty_sem_id = sysv_semget(NULL, 0x12340002, 1, MAX_Q_SIZE, 0660);
full_sem_id = sysv_semget(NULL, 0x12340003, 1, 0, 0660);
/* fork */
for (i=0;i<MAX_PROCESS;i++) {
switch(fork()) {
case 0: /* child */
/* decide of process content */
if ( i >= 0 && i < MAX_CUSTOMER_SIZE ) {
tfunc_b();
} else {
tfunc_a();
}
exit(0);
case -1:
perror("fork() error\n");
exit(-1);
default:
break;
}
}
/* wait for child process */
for (i=0;i<MAX_PROCESS;i++) {
waitpid(-1,&status,0);
}
/* sem remove */
if (sysv_semrm(sem_id) == -1) {
perror("FAIL: sysv_semrm"); return EXIT_FAILURE;
}
if (sysv_semrm(full_sem_id) == -1) {
perror("FAIL: sysv_semrm"); return EXIT_FAILURE;
}
if (sysv_semrm(empty_sem_id) == -1) {
perror("FAIL: sysv_semrm"); return EXIT_FAILURE;
}
return 0;
}
/* Name : tfunc_a
* Desc : action of item product (getting or creation)
* Argv : void
* Ret : void
*/
void tfunc_a()
{
while(1)
{
sysv_semwait(empty_sem_id, 0);
sysv_semwait(sem_id, 0);
temp++;
printf("TFUNC_A] insert %d\n",temp);
sysv_sempost(sem_id, 0);
sysv_sempost(full_sem_id, 0);
}
return;
}
/* Name : tfunc_b
* Desc : action of item consume
* Argv : void
* Ret : void
*/
void tfunc_b()
{
while(1)
{
sysv_semwait(full_sem_id, 0);
sysv_semwait(sem_id, 0);
temp++;
printf("\t\tTFUNC_B] pop %d\n",temp);
sysv_sempost(sem_id, 0);
sysv_sempost(empty_sem_id, 0);
}
return;
}
/* Name : sysv_shmget
* Desc : init shared memory (getting or creation)
* Argv : long key_shm, int n_size (byte), mode(octal notation)
* Ret : shm ID (if success), -1 (if fail)
*/
int sysv_shmget(char *tok, key_t shm_fixkey, int size, int user_mode)
{
key_t shm_key;
int shm_id;
if (tok != NULL) {
if ((shm_key = ftok(tok, 1234)) == -1) {
return -1;
}
} else {
shm_key = shm_fixkey;
}
if ((shm_id = shmget(shm_key, size, IPC_CREAT|user_mode)) == -1) {
if (errno == EEXIST) { /* already exist shm, just get ipc id */
shm_id = shmget(shm_key, 0, 0);
}
}
if (shm_id == -1)
fprintf(stderr,"FAIL: shmget():%s [%s:%d]\n", strerror(errno), __FUNCTION__, __LINE__);
return shm_id;
}
int sysv_shmrm(int shm_id)
{
int ret;
if ((ret = shmctl(shm_id, IPC_RMID, NULL)) == -1) {
fprintf(stderr,"FAIL: shmctl():%s [%s:%d]\n",
strerror(errno), __FUNCTION__, __LINE__);
return -1;
}
return ret;
}
/* Name : sysv_semget
* Desc : init semaphore (getting or creation)
* Argv : long key_sem, int n_sem, user_mode(octal notation)
* Ret : semaphore ID (if success), -1 (if fail)
*/
int sysv_semget(char *tok, key_t sem_fixkey, int n_sem, int sem_value, int user_mode)
{
int sem_id, i;
union semun semun;
unsigned short int *arr_semval = NULL;
key_t sem_key;
/* if tok is not NULL, we make IPC key for semaphore */
if (tok != NULL) {
if ((sem_key = ftok(tok, 1234)) == -1) {
return -1;
}
} else {
sem_key = sem_fixkey;
}
if ((sem_id = semget(sem_key, n_sem, IPC_CREAT|IPC_EXCL|user_mode)) == -1) {
if (errno == EEXIST) {
/* Is exist ? */
sem_id = semget(sem_key, n_sem, 0);
return sem_id;
}
}
if (sem_id == -1) {
fprintf(stderr,"FAIL: semget [%s:%d]\n", __FUNCTION__, __LINE__);
return -1;
}
/* init semaphore value */
if ((arr_semval = (unsigned short int *)malloc(sizeof(unsigned short int) * n_sem)) == NULL) {
fprintf(stderr, "FAIL: malloc [%s:%d]\n", __FUNCTION__, __LINE__);
return -1;
}
for(i=0; i<n_sem; i++) arr_semval[i] = sem_value;
semun.array = arr_semval;
if (semctl(sem_id, 0, SETALL, semun) == -1) {
fprintf(stderr, "FAIL: semctl [%s:%d]\n", __FUNCTION__, __LINE__);
if (arr_semval != NULL) free(arr_semval);
return -1;
}
if (arr_semval != NULL) free(arr_semval);
return sem_id;
}
/* Name : sysv_semrm
* Desc : remove specified semaphore with sem_id
* Argv : int sem_id
* Ret : 0 (if success), -1 (if fail)
*/
int sysv_semrm(int sem_id)
{
if (semctl(sem_id, 0, IPC_RMID) == -1) {
fprintf(stderr, "FAIL: semctl() 'IPC_RMID' [%s:%d]\n", __FUNCTION__, __LINE__);
return -1;
}
return 0;
}
/* Name : sysv_semwait
* Desc : P operation about specified SysV semaphore
* Argv : int sem_id, int sem_idx
* Ret : 0 (if success), -1 (if fail)
*/
int sysv_semwait(int _sem_id, int sem_idx)
{
struct sembuf sem_buf;
sem_buf.sem_num = sem_idx;
sem_buf.sem_flg = SEM_UNDO;
sem_buf.sem_op = -1;
if (semop(_sem_id, &sem_buf, 1) == -1) {
fprintf(stderr, "FAIL: semop() 'P' operation [%s:%d]\n", __FUNCTION__, __LINE__);
getchar();
return -1;
}
return 0;
}
/* Name : sysv_sempost
* Desc : V operation about specified SysV semaphore
* Argv : int sem_id, int sem_idx
* Ret : 0 (if success), -1 (if fail)
*/
int sysv_sempost(int _sem_id, int sem_idx)
{
struct sembuf sem_buf;
sem_buf.sem_num = sem_idx;
sem_buf.sem_flg = SEM_UNDO;
sem_buf.sem_op = 1;
if (semop(_sem_id, &sem_buf, 1) == -1) {
fprintf(stderr, "FAIL: semop() 'P' operation [%s:%d]\n", __FUNCTION__, __LINE__);
getchar();
return -1;
}
return 0;
}
/* Name : sysv_semval
* Desc : get specified semaphore value
* Argv : int sem_id, int sem_idx
* Ret : semaphore value (if success), -1 (if fail)
*/
int sysv_semval(int _sem_id, int sem_idx)
{
int semval;
if ((semval = semctl(_sem_id, sem_idx, GETVAL)) == -1) {
fprintf(stderr, "FAIL: semctl() 'GETVAL' [%s:%d]\n", __FUNCTION__, __LINE__);
return -1;
}
return semval;
}Forums:


댓글 달기