세마포어 관련

asleea의 이미지

IPC 세마포어를 이용하여 2개의 세마포어 배열을 만들어 사용해 보려고 하는데

0번째 세마포어는 lock unlock 동작을 하는데 1번째 세마포어가 lock부분에서 블록되어 멈춰있네요

책이나 인터넷에는 다 1개만 이용한 예제밖에 없어 혹시 제가 함수를 잘못 사용해서 초기화를 했나하고

세마포어 초기화 및 사용 부분만 복사해서 올려봅니다.

혹시 잘못 된 부분있나요 .?

void setsembuf(struct sembuf* s, int num, int op, int flg)
{
        s->sem_num = (short)num;
        s->sem_op = (short)op;
        s->sem_flg = (short)flg;
        return ;
}
static int semid;
static struct sembuf semlock;
static struct sembuf semunlock;
static struct sembuf donelock;
static struct sembuf doneunlock;
 
semid = semget(key, 2, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
 
setsembuf(&semlock, 0, -1, 0);
setsembuf(&semunlock, 0, 1, 0);
setsembuf(&donelock, 1, -1, 0);
setsembuf(&doneunlock, 1, 1, 0);
 
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
}arg;
rg.val = 1;
 
if(semctl(semid, 0, SETVAL, arg) == -1)
    return -1;
if(semctl(semid, 1, SETVAL, arg) == -1)
    return -1;
 
semop(semid, &donelock, 1);
.
.
.
semop(semid, &doneunlock, 1);
 
semop(semid, &semlock, 1);
.
.
.
semop(semid, &semunlock, 1);

이 부분은 전체 코드 혹시나 해서..(공유메모리 에서 세마포어 사용)

main에 getdone()함수 donelock 부분에서 블록 되어있습니다.

#include<stdio.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<time.h>
#include<signal.h>
#include<sys/sem.h>
#include<sys/shm.h>
#include<errno.h>
 
typedef struct 
{
	int done;
	int count;
	int sum;
	sig_atomic_t setdone;
}shared_arg;
 
void setsembuf(struct sembuf* s, int num, int op, int flg)
{
	s->sem_num = (short)num;
	s->sem_op = (short)op;
	s->sem_flg = (short)flg;
	return ;
}
 
static shared_arg *shared_memory;
static int semid;
static struct sembuf semlock;
static struct sembuf semunlock;
static struct sembuf donelock;
static struct sembuf doneunlock;
 
int initshared(int key)
{
	int shid = shmget(key, sizeof(shared_arg), IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
	if((shid == -1) && (!EEXIST))
		return -1;
	if(shid == -1)
	{
		shid = shmget(key, sizeof(shared_arg), S_IRUSR | S_IWUSR);
		if(shid == -1)
			return -1;
		shared_memory = (shared_arg*)shmat(shid, NULL, 0);
		if(shared_memory == (void*)-1)
			return -1;
	}
	else
	{
		shared_memory = (shared_arg*)shmat(shid, NULL, 0);
		if(shared_memory == (void*)-1)
			return -1;
		shared_memory->count = 0;
		shared_memory->sum = 0;
		shared_memory->done = 0;
	}
	fprintf(stderr, "shared memort OK\n");
	setsembuf(&semlock, 0, -1, 0);
	setsembuf(&semunlock, 0, 1, 0);
	setsembuf(&donelock, 1, -1, 0);
	setsembuf(&doneunlock, 1, 1, 0);
	struct timespec sleeptime;
	sleeptime.tv_sec = 0;
	sleeptime.tv_nsec = 10000000;
	semid = semget(key, 2, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
	if((semid == -1) && (!EEXIST))
		return -1;
	if(semid == -1)
	{
		semid = semget(key, 2, S_IRUSR | S_IWUSR);
		fprintf(stderr, "already sem exist and wait setdone\n");
		while(!shared_memory->setdone)
			nanosleep(&sleeptime, NULL);
		fprintf(stderr, "setdone OK\n");
	}
	else
	{
		fprintf(stderr, "new sem setting\n");
		union semun
		{
			int val;
			struct semid_ds *buf;
			unsigned short *array;
		}arg;
		arg.val = 1;
		if(semctl(semid, 0, SETVAL, arg) == -1)
			return -1;
		if(semctl(semid, 1, SETVAL, arg) == -1)
			return -1;
		shared_memory->setdone = 1;
	}
	return 0;
}
 
int getdone(int *done)
{
	if(semop(semid, &donelock, 1) == -1)
		return -1;
	fprintf(stderr, "doneloc\n");
	*done = shared_memory->done;
	if(semop(semid, &doneunlock, 1) == -1)
		return -1;
	fprintf(stderr, "doneunlock\n");
	return 0;
}
static int setdone(void)
{
	if(semop(semid, &donelock, 1) == -1)
		return -1;
	shared_memory->done = 1;
	if(semop(semid, &doneunlock, 1) == -1)
		return -1;
	return 0;
}
 
int add(int x)
{
	if(semop(semid, &semlock, 1) == -1)
		return -1;
	shared_memory->sum += x;
	shared_memory->count++;
	if(semop(semid, &semunlock, 1) == -1)
		return -1;
	return 0;
}
 
static int getsumandcount(int *sump, int *countp)
{
	if(semop(semid, &semlock, 1) == -1)
		return -1;
	*sump = shared_memory->sum;
	*countp = shared_memory->count;
	if(semop(semid, &semunlock, 1) == -1)
		return -1;
	return 0;
}
 
 
 
 
 
int main(int argc, char *argv[])
{
	if(argc != 2)
	{
		fprintf(stderr, "Usage: %s <key>\n", argv[0]);
		return 1;
	}
	int key = atoi(argv[1]);
	int doneflag = 0;
	int rtn;
	int count = 0;
	int sum = 0;
	if(initshared(key) == -1)
	{
		fprintf(stderr, "initshared error\n");
		return 1;
	}
	fprintf(stderr, "start adding x to sum\n");
	while(!doneflag)
	{
		rtn = add(1);
		fprintf(stderr, "add, ");
		if(rtn == -1)
		{
			fprintf(stderr, "[%ld]:add error\n", (long)getpid());
			return 1;
		}
		int rtn = getsumandcount(&sum, &count);
		fprintf(stderr, "getsumandcount, ");
		if(rtn == -1)
		{
			fprintf(stderr, "getsunadncount error\n");
			return 1;
		}
		fprintf(stderr, "sum: %d, count: %d\n", sum, count);
		sleep(1);
		rtn = getdone(&doneflag);
		fprintf(stderr, "getdone....\n");
		if(rtn == -1)
		{
			fprintf(stderr, "[%ld]:getdone error\n", (long)getpid());
			return 1;
		}
	}
	fprintf(stderr, "doneflag on, process exit!!\n");
	return 0;
}
 
Anti-Lock의 이미지

제가 잘 모르고 글을 쓴것 같네요.
내용 지웁니다ㅠ