여러 생산자와 여러 소비자문제...
글쓴이: 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:
댓글 달기