세마포어 관련

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의 이미지

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

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.