[Tip] semop() 세마포어 값을 변경
--------------------------------------------------------------------------------------------------------------------------
설명
--------------------------------------------------------------------------------------------------------------------------
semop() 함수는 세마포어의 값을 변경합니다. 세마포어를 사용하기 위해서는
먼저 세마포어 값을 1 감소시키고, 사용 후에는 1 증가시키는데, 이렇게 세마포어값을 증감하는 것을 요청하는 함수입니다.
--------------------------------------------------------------------------------------------------------------------------
헤더
--------------------------------------------------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
--------------------------------------------------------------------------------------------------------------------------
형태
--------------------------------------------------------------------------------------------------------------------------
int semop ( int semid, struct sembuf *sops, unsigned nsops )
--------------------------------------------------------------------------------------------------------------------------
인수
--------------------------------------------------------------------------------------------------------------------------
int semid 시스템에서 세머포어를 식별하는 집합 번호
struct sembuf *sops
세마포어 값을 계사하기위한 설정 값
struct sembuf {
short sem_num; 세마포어 번호
short sem_op; 세마포어 증감값
short sem_flg; 옵션
}
sem_flg sem_flg 내용
IPC_NOWAIT
호출 즉시 실행하지 못했을 경우 기다리지 않고 실패로 바로 복귀합니다.
SEM_UNDO 프로세스가 종료되면 시스템에서 세마포어 설저을 원래 상태로 되돌립니다. 그러므로 보통 이 옵션을 사용합니다.
unsigned nsops
변경하려는 세마포어 개수로 변경하려는 세마포어 개수가 여러 개일 때 사용합니다.
예를 들어 변경하려는 세마포어 개수가 한 개라면
struct sembuf sbuf = { 0, -1, 0};
semop( semmop, &sbuf, 1);
이렇게 값이 1이 되지만 한번에 2개 이상의 세마포어를 변경한다면,
struct sembuf pbuf[2] = {
{ 0, 1, 0} , // 첫번째 세마포어 값을 1 증가
{ 1, -1, 0} // 두번째 세마포어 값을 1 감소
}
semop( semmop, pbuf, 2);
--------------------------------------------------------------------------------------------------------------------------
반환
--------------------------------------------------------------------------------------------------------------------------
0 성공
-1 실패
--------------------------------------------------------------------------------------------------------------------------
예제
--------------------------------------------------------------------------------------------------------------------------
예제에서는 두개의 쓰레드를 만들어 첫번째 쓰레드는 카운터 값을 증가 시키고 두번째 쓰레드는 카운터를 화면에 출력합니다.
카운터가 5 이상의 값이 되면 두 개의 쓰레드는 모두 종료하고 프로그램이 종료되면서 세마포어를 삭제합니다.
여기서 세마포어는 각각의 쓰레드가 독립적으로 실행될수 있음을 보장하는 역할을 수행한다.
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int cnt = 0;
static int semid;
void p()
{
struct sembuf pbuf;
pbuf.sem_num = 0;
pbuf.sem_op = -1;
pbuf.sem_flg = SEM_UNDO;
if ( -1 == semop(semid, &pbuf, 1))
printf( "p()-semop() 실행 오류\n");
}
void v()
{
struct sembuf vbuf;
vbuf.sem_num = 0;
vbuf.sem_op = 1;
vbuf.sem_flg = SEM_UNDO;
if ( -1 == semop( semid, &vbuf, 1))
printf( "v()-semop() 실행 오류\n");
}
void *fun_thread1(void *arg)
{
while( 1)
{
p();
printf( "thread1 실행\n");
if ( 5 < cnt)
{
printf( "thread1 완전 종료\n");
v();
break;
}
else
{
cnt++;
usleep( 100);
printf( "thread1 완료\n");
}
v();
}
return NULL;
}
void *fun_thread2(void *arg)
{
while( 1)
{
p();
printf( "thread2 실행\n");
if ( 5 < cnt)
{
printf( "thread2 완전 종료\n");
v();
break;
}
else
{
printf( "카운터= %d\n", cnt);
usleep( 100);
printf( "thread2 완료\n");
}
v();
}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t thread1;
pthread_t thread2;
union semun{
int val;
struct semid_ds *buf;
unsigned short int *arrary;
} arg;
if ( -1 == (semid = semget( IPC_PRIVATE, 1, IPC_CREAT | 0666)))
{
printf( "semget() 실행 오류\n");
return -1;
}
arg.val = 1; // 세마포어 값을 1로 설정
if ( -1 == semctl(semid, 0, SETVAL, arg))
{
printf( "semctl()-SETVAL 실행 오류\n");
return -1;
}
pthread_create(&thread1, NULL, fun_thread1, NULL);
pthread_create(&thread2, NULL, fun_thread2, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
if ( -1 == semctl(semid, 0, IPC_RMID, arg))
{
printf( "semctl()-IPC_RMID 실행 오류\n");
return -1;
}
printf( "프로그램 종료\n");
return 0;
}
]$ gcc main.c -lpthread // 소스에 쓰레드를 이용하므로 옵션에 -lpthread를 추가
]$ ./a.out
thread1 실행
thread1 완료
thread2 실행
카운터= 1
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 2
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 3
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 4
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 5
thread2 완료
thread1 실행
thread1 완료
thread2 실행
thread2 완전 종료
thread1 실행
thread1 완전 종료
프로그램 종료
]$
'c 언어 > 중급과정' 카테고리의 다른 글
[카카오 코딩테스트] 자연수 자릿수의 합 구하기 (0) | 2019.10.30 |
---|---|
[카카오 코딩테스트] 다트 게임 (0) | 2019.10.30 |
OS Common, strstr로 해결이 안되는 부분에서는 strchr로 (0) | 2019.10.30 |
pointer memory use instead of structure stack memory (0) | 2019.10.29 |
gcc -o sample sample.o -lm 시에 m의 의미는? (0) | 2019.10.29 |