세마포에대해...질문!

익명 사용자의 이미지

다음 세마포가 작동을 하지 않는데요
a.c b.c가 동시에 "file"에 사이좋게
100번씩 값을 1증가시키면서
쓰는건데...

결과적으로 최종값이 116정도 나왔습니다.
이론적으로 200이 나와야 정상인데..
이유가 뭔지 궁금합니다.
file에
0이란값이 초기에 쓰여있고,
a.c와 b.c는 이미 생성된 세마포ID를 인수로 넘겨받습니다.

---------a.c -----------
(b.c도 동일함.)

#include
#include
#include
#include
#include
#include
#include

union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
}; /* 1. 이부분을 이처럼 명시적으로 User가 define해주어야 하는지요?
*/

FILE *fp;
int main( int argc , char *argv[] )
{
int i, j , value;
int semid;
struct sembuf sem_open = { 0 , -1 , SEM_UNDO };
struct sembuf sem_close= { 0 , 1 , SEM_UNDO };
union semun ctlarg;
char buf[255];
if ( argc < 2 )
{
fprintf( stderr , "exe semid\n" );
exit( 1 );
}
semid = atoi( argv[1] );
ctlarg.val = 1;
j = semctl( semid , 0 , SETVAL , ctlarg ); /* 세마포값을 1로 부
여 */
fatal( j , "semctl-SETVAL" );
/* 100 iteration */
for ( i = 0 ; i < 100 ; i++ )
{
j = semop( semid , &sem_open , 1 );
fatal( j , "semop-p operation" );
fp = fopen("file" , "r+" );
fgets( buf , sizeof buf , fp );
buf[ strlen(buf) -1 ] = 0x00;
value = atoi(buf);
fseek( fp , 0 , SEEK_SET );
fprintf( fp , "%03d\n" , ++value );
fprintf( stderr , "a%03d\n" , value ); /* b.c는 b%03d 로 표
시됨 */
fclose( fp );
j = semop( semid , &sem_close , 1 );
fatal( j , "semop-v operation" );
}
return 0;
}

쉘(ex.sh)를 다음처럼
a 2 &
b 2 &
만든후 동시실행했습니다.
인수 2는 이미생성된 세마포 ID입니다.

솔라리스 8에서 테스트한 실행결과입니다.
a001
a002
a003
a004
a005
a006
a007
a008
a009
a010
a011
a012b0
11a0
13
b0a01414

b0a01515

b0a016
16
b017a017

a0b01818

a0b01919

a0b02020

a0b021
21
a0b022
22
a0b023
23
a0b024
24
a025b025

a0b02626

a0b027
27
a0b028
28
a029
b029
a030
b030
a031
b031
a032
b032
a033
b033
a034
b034
a035
b035
a036
b036
a037
b037
a038
b038
a039
b039
a040
b040
a041
b041
a042
b042
a043
b043
a044
b044
a045
b0a046
45a0
47
b0a04848

b0a04949

b0a050
50
b0a051
51
b052
a052
b053
a053
b054
a054
b055
a055
b056
a056
b057
a057
b058
a058
b059
a059
b060
a060
b061
a061
b062
a062
b063
a063
b064
a064
b065
a065
b066
a066
b067
a067
b068
a068
b069
a069
b070
a070
b071
a071
b072
a072
b073
a073
b074
a074
b075
a075
b076
a076
b077
a077
b078
a078
b079
a079
b080
a080
b081
a081
b082
a082
b083
a083
b084
a084
b085
a085
b086
a086
b087
a087
b088
a088
b089
a089
b090
a090
b091
a091
b092
a092
b093
a093
b094
a094
a095
a0b096
a096
97
b0a09898

b0a099
99
b100
a100
b101
b102
b103
b104
b105
b106
b107
b108
b109
b110
b111
b112
b113
b114
b115
b116

익명 사용자의 이미지

질문 1에 대한 답변은 네 그 구조체 자체가 헤더 파일에 없기 때문에 해
주어야 합니다.

그리고 이렇게 에러가 나는이유는 세마포를 사용하는 목적이 동기화인데

세마포 값이 0,1 이라고 볼때 0일때 1일때로 바뀔때까지 기다리는 루틴이
없기 때문에 이런 결과가 나는 것 같네요.

while문으로 기다려 줘야 겠지요..

자세한건 semtool.c 로 구글 검색해서 되는 소스 찾아 보셔두 되고요. 근
데 이건 조금 힘들더군요.. 소스가 안돌아 가는 것들이 있어서

세마포 예제 제대로 돌아가는건 Begging Linux Programming (정보문화사)
13장 참고 하시면 됩니다.

아래 예제는 제가 사용하는 세마포 함수 루틴입니다.
기존의 semtool 이용해서 my_lock() my_unlock()로 구현한것입니다.

/********************************************************************
*********
Excerpt from "Linux Programmer's Guide - Chapter 6"
(C)opyright 1994-1995, Scott Burkett

*********************************************************************
********
MODULE semtool.c

*********************************************************************
********
A command line tool for tinkering with SysV style Semaphore Sets


*********************************************************************
********/

#include
#include
#include
#include
#include
#include
#include
#include
//#include

#include "lock.h"

#define SEM_RESOURCE_MAX 1 /* Initial value of all
semaphores */
#define SEMMSL 250 /* <= 8 000 max num of semaphores
per id */
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
key_t key = 1111;
int semset_id;

/*
void opensem(int *sid, key_t key);
void createsem(int *sid, key_t key, int members);
void locksem(int sid, int member);
void unlocksem(int sid, int member);
void removesem(int sid);
unsigned short get_member_count(int sid);
int getval(int sid, int member);
void dispval(int sid, int member);
void changemode(int sid, char *mode);
void usage(void);
*/

void
my_lock(int num)
{

/* Create unique key via call to ftok() */
//key = ftok(".", 's');

my_opensem(&semset_id,key,6);

opensem(&semset_id, key);
locksem(semset_id, num);
}

void
my_unlock(int num)
{
//key_t key;
//int semset_id;
/* Create unique key via call to ftok() */
//key = ftok(".", 's');
//key=1234;

opensem(&semset_id, key);
unlocksem(semset_id, num);
}

void my_opensem(int *sid, key_t key,int member)
{
/* Open the semaphore set - do not create! */

if((*sid = semget(key, 0, 0666)) == -1)
{
createsem(sid,key,member);
}


}

void opensem(int *sid, key_t key)
{
/* Open the semaphore set - do not create! */

if((*sid = semget(key, 0, 0666)) == -1)
{
printf("Semaphore set does not exist!\n");
exit(1);
}


}

void createsem(int *sid, key_t key, int members)
{
int cntr;
//union semnum semopts;
union semun semopts;

if(members > SEMMSL) {
printf("Sorry, max number of semaphores in a set is %
d\n",
SEMMSL);
exit(1);
}

printf("Attempting to create new semaphore set with %d
members\n",
members);

if((*sid = semget(key, members, IPC_CREAT|IPC_EXCL|0666))
== -1)
{
fprintf(stderr, "Semaphore set already exists!\n");
exit(1);
}

semopts.val = SEM_RESOURCE_MAX;

/* Initialize all members (could be done with SETALL)
*/
for(cntr=0; cntr semctl(*sid, cntr, SETVAL, semopts);
}

void locksem(int sid, int member)
{
struct sembuf sem_lock={ 0, -1, IPC_NOWAIT};
int t=1;

if( member<0 || member>(get_member_count(sid)))
{
fprintf(stderr, "semaphore member %d out of
range\n", member);
fprintf(stderr, "semaphore member %d out of
range\n", get_member_count(sid));

return;
}

/* Attempt to lock the semaphore set
if(!getval(sid, member))
{
fprintf(stderr, "Semaphore resources exhausted (no
lock)!\n");
exit(1);
}
*/
/* Attempt to lock the semaphore set */
while(!getval(sid, member))
{
//fprintf(stderr, "Semaphore resources exhausted (no
lock)!\n");
//exit(1);
sleep(t%10);
t++;
}

sem_lock.sem_num = member;

if((semop(sid, &sem_lock, 1)) == -1)
{
fprintf(stderr, "Lock failed\n");
exit(1);
}
else
printf("Semaphore resources decremented by one
(locked)\n");


dispval(sid, member);
}

void unlocksem(int sid, int member)
{
struct sembuf sem_unlock={ member, 1, IPC_NOWAIT};
int semval;

if( member<0 || member>(get_member_count(sid)))
{
fprintf(stderr, "semaphore member %d out of
range\n", member);
return;
}

/* Is the semaphore set locked? */
semval = getval(sid, member);
if(semval == SEM_RESOURCE_MAX) {
fprintf(stderr, "Semaphore not locked!\n");
exit(1);
}

sem_unlock.sem_num = member;

/* Attempt to lock the semaphore set */
if((semop(sid, &sem_unlock, 1)) == -1)
{
fprintf(stderr, "Unlock failed\n");
exit(1);
}
else
printf("Semaphore resources incremented by one
(unlocked)\n");

dispval(sid, member);
}

void removesem(int sid)
{
semctl(sid, 0, IPC_RMID, 0);
printf("Semaphore removed\n");
}

unsigned short get_member_count(int sid)
{
union semun semopts;
struct semid_ds mysemds;

semopts.buf = &mysemds;

/* Return number of members in the semaphore set */
return(semopts.buf->sem_nsems);
}

int getval(int sid, int member)
{
int semval;

semval = semctl(sid, member, GETVAL, 0);
return(semval);
}

void changemode(int sid, char *mode)
{
int rc;
union semun semopts;
struct semid_ds mysemds;

/* Get current values for internal data structure */
semopts.buf = &mysemds;

rc = semctl(sid, 0, IPC_STAT, semopts);

if (rc == -1) {
perror("semctl");
exit(1);
}

printf("Old permissions were %o\n", semopts.buf-
>sem_perm.mode);

/* Change the permissions on the semaphore */
sscanf(mode, "%ho", &semopts.buf->sem_perm.mode);

/* Update the internal data structure */
semctl(sid, 0, IPC_SET, semopts);

printf("Updated...\n");

}

void dispval(int sid, int member)
{
int semval;

semval = semctl(sid, member, GETVAL, 0);
printf("semval for member %d is %d\n", member, semval);
}

void usage(void)
{
fprintf(stderr, "semtool - A utility for tinkering with
semaphores\n");
fprintf(stderr, "\nUSAGE semtool4 (c)reate \n");
fprintf(stderr, " (l)ock \n");
fprintf(stderr, " (u)nlock \n");
fprintf(stderr, " (d)elete\n");
fprintf(stderr, " (m)ode \n");
exit(1);
}

---------------------------------------------------------------
---------------------------------------------------------------
lock.h
#include
void my_lock(int num);
void my_unlock(int num);
void my_opensem(int *sid, key_t key,int member);
void opensem(int *sid, key_t key);
void createsem(int *sid, key_t key, int members);
void locksem(int sid, int member);
void unlocksem(int sid, int member);
void removesem(int sid);
unsigned short get_member_count(int sid);
int getval(int sid, int member);
void dispval(int sid, int member);
void changemode(int sid, char *mode);
void usage(void);

익명 사용자의 이미지

먼저답변감사드리고요...

원래소스에서 SETVAL 하는부분을 없앴습니다.
그것은 세마포 생성할때 해주는걸로 했고요.
그래서 소스가

----------------a.c----------------------
(b.c도 동일)

#include
#include
#include
#include
#include
#include
#include

union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
};

FILE *fp;
int main( int argc , char *argv[] )
{
int i, j , value;
int semid;
struct sembuf sem_open = { 0 , -1 , SEM_UNDO };
struct sembuf sem_close= { 0 , 1 , SEM_UNDO };
union semun ctlarg;
char buf[255];
if ( argc < 2 )
{
fprintf( stderr , "exe semid\n" );
exit( 1 );
}
semid = atoi( argv[1] );
/* 100 iteration */
for ( i = 0 ; i < 100 ; i++ )
{
j = semop( semid , &sem_open , 1 );
fatal( j , "semop-p operation" );
fp = fopen("file" , "r+" );
fgets( buf , sizeof buf , fp );
buf[ strlen(buf) -1 ] = 0x00;
value = atoi(buf);
fseek( fp , 0 , SEEK_SET );
fprintf( fp , "%03d\n" , ++value );
/* b.c는 a%03d ---> b%03d */
fprintf( stderr , "a%03d\n" , value );
fclose( fp );
j = semop( semid , &sem_close , 1 );
fatal( j , "semop-v operation" );
}
return 0;
}

이것을 쉘로 (ex.sh)
#!/bin/ksh -f
a 2 &
b 2 &
실행시킬때
원하는 최종결과 200은 얻었지만

a001
a002
a003
a004
a005
a006
a007
a008
a009
a010
a011
a012
a013
a014
a015
a016
a017
a018
a019
a020
a021
a022
a023
a024
a025
a026
a027
a028
a029
a030
a031
a032
a033
a034
a035
a036
a037
a038
a039
a040
a041
a042
a043
a044
a045
a046
a047
a048
a049
a050
a051
a052
a053
a054
a055
a056
a057
a058
a059
a060
a061
a062
a063
a064
a065
a066
a067
a068
a069
a070
a071
a072
a073
a074
a075
a076
a077
a078
a079
a080
a081
a082
a083
a084
a085
a086
a087
a088
a089
a090
a091
a092
a093
a094
a095
a096
a097
a098
a099
a100
b101
b102
b103
b104
b105
b106
b107
b108
b109
b110
b111
b112
b113
b114
b115
b116
b117
b118
b119
b120
b121
b122
b123
b124
b125
b126
b127
b128
b129
b130
b131
b132
b133
b134
b135
b136
b137
b138
b139
b140
b141
b142
b143
b144
b145
b146
b147
b148
b149
b150
b151
b152
b153
b154
b155
b156
b157
b158
b159
b160
b161
b162
b163
b164
b165
b166
b167
b168
b169
b170
b171
b172
b173
b174
b175
b176
b177
b178
b179
b180
b181
b182
b183
b184
b185
b186
b187
b188
b189
b190
b191
b192
b193
b194
b195
b196
b197
b198
b199
b200

이렇게 a 프로세스 일방적으로 먼저 쓰고
다음에 b 프로세스가 쓰는 걸로 나오네요.
a, b가 동시경쟁하다가 a가 먼저 세마포를 가져갔더라도
a가 쓰고서 세마포를 돌려주는 순간
이전에 블로킹되어있던 b가 세마포를 가져가는게 옳지 않나요?
아시는분은 답변부탁드립니다.
제 생각엔
a001
b002
a003
b004
a005 이런식으로 예상했거든요.

익명 사용자의 이미지

음냐... 일단... 어떤 프로세스가 세마포어를 획득할지에 대해서는

학실히 아는 방법이 없습니다. 즉, A, B 두 개의 프로세스가 있을 때,

A가 세마포어를 가지고 있다가 풀어다고 해서, B 가 무조건 가져간다는

것이 아닙니다. while 루프에서 세마포어를 얻는 부분이 있다면, A가

풀고 다시 A가 바로 가져갈 수 가 있습니다. A,B,A,B 순차적인 실행을

원하신다면, 프로세스의 끝에 sleep 명령을 이용하여 강제적으로 쉬게

하면 가능합니다. sleep 이라는 명령이 강제적으로 쉬게 되면서 제어권을

다른 프로세스에게 넘기기 때문에, 어느 정도의 시간을 sleep 으로 쉬게

되면, 다른 프로세스가 그 세마포어를 획득할 것입니다. 그럼 고운 하루

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.