Unix System Programming 7 - 김성호(moohou) :namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
_________________________________________________________________________
제7장. 프로세스간 통신 : 2
7.1. 서론
제 6 장에서 살펴본 프로세스간의 통신방법은 대부분이 여러 해 동안 UNIX 상
에서 유용하게 사용된 것들이다. 시스템 V 에서는 몇가지 새로운 기능이 도입
되어 AT&T 의 시스템 V 인터페이스 정의에 수록되었다. 우선 가장 간단한 것은
레코드 록킹(record locking)으로서 이는 직접적인 프로세스 통신형태가 아니
라 프로세스들의 협력방법이다. 이것은 프로세스가 자신의 배타적인 사용을 위
해 화일의 일부를 입시로 보존할 수 있게 하여, 데이타 베이스관리의 몇가지
어려운 문제 를 해결하게 한다. 시스템 V 의 새로운 프로세스간 통신방법 중
다른 것들은 조금은 이색적이며, 시스템 V 의 기본설비(facility)를 확장한 것
으로 생각할수 있다. 일반적으로 이들 새기능들은 IPC(IPC 는 프소세스간 통신
을 의미한다)라 한다.
1. 메시지 전달(Message Passing)
메시지 전달 설비는 프로세스가 메시지를 주고 받을 수 있게 한다. 이때 메
시지란 입의의 문자열이나 바이트열이다.
2. 세마포어(Semaphore)
메시지 전달과 비교하면, 세마포어는 프로세스 동기화를 위한 보다 하부적
인 수단을 제공하는 것이며, 많은 양의 정보를 전달하는 것에는 적합하지
않다.
3. 공유메모리(Shared Memory)
이것은 두 개 이상의 프로세스가 특정 메모리 세그먼트에 있는 자료를 공유
할 수 있게 된다. 물론 프로세스의 자료 영역은 보통 자신만이 사용할 수
있다. 이 기능은 IPC 방법중 가장 빠르지만 약간의 하드웨어 지원을 필요로
한다.
7.2. 레코드 록킹
7.2.1. 동기
록은 화일 내용을 건드리지는 않으며, 다른 프로세스들에게 해당 데이타가 사
용중임을 나타내는 것이다. 이는 하나의 논리적 작업 또는 트랜잭션을 구성하
는 일련의 처리 과정 도중에 다른 프로세스들이 뛰어드는 것을 막는다. 이러한
유형의 방법을 레코드 록킹이라 하며, 이때의 레코드는 화일의 임의적의 일부
를 지칭한다. 완벽을 기하기 위해서는 록킹 작업이 원자화 되어야 한다. 즉,
이는 다른 프로세스에 의한 모순되는 록킹 시도와는 병행될 수 없다.
7.2.2. lockf 호출
#include <unistd.h>
int filedes, purpose, status;
long recsize;
.
.
status = lockf(filedes, purpose, recsize);
lockf 는 SVID 에 정의된 레코드 록킹 기법 중 가장 단순한 것이다. lockf(그
리고 fcntl)에 의한 록킹은 단지 권고용(advisory)이다. 이는 화일 허가만 있
으면 프로세스는 화일에서 록이 된 것으로 알려진 부분을 수정할 수 있다는 것
을 의미한다. lockf 의 첫번째 인수 filedes 는 개방된 화일 기술어라야 한다.
이는 록이 수행될 화일을 지정하고, O_WRONNLY 나 O_RDWR 를 사용하여 개방된
것이라야 한다. purpose 인수는 lockf 가 실제로 무엇을 수행할 것인가를 결정
한다. 이를 위해 허용된 값들은 화일 unistd.h 에 다름과 같이 정의되어 있다.
#define F_ULOCK 0 /*Unlock a locked record
*/
#define F_LOCK 1 /*lock a record for excl
usive use */
#define F_TLOCK 2 /*test for lock, lock if
none */
#define F_TEST 3 /*test for existing lock
only */
lockf 의 마지막 인수 recsize 는 록(lock), 해제(unlock), 또는 단순히 검사
될 영역(section)의 크기를 지정한다. 이 영역의 시작위치는 화일의 읽기-쓰기
포인터의 현재위치와 같다. 이러한 이유로, lockf 는 lseek 다음에 호출된다.
F_LOCK
purpose 값을 F_LOCK 으로하여 lockf 를 호출하면, 시스템은 화일의 읽기-쓰
기 포인터와 recsize 로 정의되는 영역에 록을 하려 시도한다.
lockf(fdes, F_LOCK, 512L);
는 현재의 읽기-쓰기 포인터의 위치에서 시작하여 512 바이트에 록을 건다.
F_ULOCK
F_ULOCK 은 호출프로세스에 의해 전에 록된 영역을 해제(unlock)한다. 이는
보통 F_LOCK 이나 F_TLOCK 이 요청된 후에 사용된다. 만약 방금 해제된 영역을
록하려고 기다리던 프로세스가 있다면, 그 중 하나가 다시 시작할 수 있다.
F_TEST
F_TEST 는 다른 프로세스에 의해 해당 영역이 록 되었는 지를 검사하는 것이
다. 이영역도 역시 화일의 현재 위치와 인수 recsize 에 의해 지정된다. 록 되
어 있지 않다면 lockf는 0 을 돌려준다.
F_TLOCK
이 요청은 F_TEST 와 F_LOCK 을 결합한 것으로, 화일에서 기존에 록된 영역
을 다시 록하려 할때, 프로그램이 수행을 중지하지 않고 다른 행동을 계속하려
는 경우에 유용하다. 록 되지 않은 영역에 대해 F_TLOCK 이 사용되면, F_LOCK
과 같이 록이 적용된다. 록된 영역에 대해서는, lockf 는 -1 을 돌려주고
error 를 EACCES (UNIX 의 미래 버전에는 EAGAIN)로 한다.
recsize 인수가 0 값을 갖는 경우
만약 lockf 의 인수 recsize 의 값이 0 이라면, 록되는 화일의 영역은 화일
의 현재 위치부터 화일 크기의 최대 한계(이는 각 구현마다 다르다)까지로 정
해진다.
lseek(fd, 0L, 0);
lockf(fd, F_LOCK, 0L);
이것은 간단히 화일 전체를 록한다.
교학상태
두 프로세스 PA 와 PB 가 같은 화일에서 작업중이라 하자. 또 PA 가 F_LOCK
요청이 이러한 교착상태를 유발하려 한다면, 호출은 실패하여 -1 을 돌려주고
errno 값을 EDEADLK 으로 한다.(EDEADLK 은 시스템 록 테이블이 가득찬 경우
도 의미할 수 있다.)
7.2.3. fcntl 을 사용한 레코드 록킹
우리는 이미 화일제어호출 fcntl 을 소개했다. 보통의 기능과는 별도로 fcntl
은 lockf 보다 일반적인 형태의 레코드 록킹을 수행하는데 사용될 수 있다. 이
는 두가지 형태의 록을 제공한다.
1. 읽기 록
읽기 록은 단순하게 다른 프로세스들이 쓰기 록이라는 두번째 형태의 록을
못하도록 한다.
2. 쓰기 록
쓰기 록은 다른 프로세스들이 해당구역에 읽기나 쓰기 록을 할 수 없도록
한다.
레코드 록킹을 위해 fcntl 을 다음과 같이 사용된다.
#include <fcntl.h>
struct lock ldata;
int filedes, cmd, status;
.
.
status = fcntl(filedes, cmd, &ldata);
filedes 인수는 역시 유효한 개방된 화일 기술어라야 한다. 읽기 록을 위해서
는 filedes 는 O_RDONLY 나 O_RDWR 을 이용해서 개방되어야 한다. 따라서
creat 에 의한 화일 기술어는 사용될 수 없다. 쓰기 록을 위해서는 filedes 는
O_WRONLY 나 O_RDWR 을 사용해 개방되어야 한다. 레코드 록킹에대한 인수 cmd
의 값은 다음의 3 개이다.
F_GETLK
ldata 인수를 통해 전달된 데이타에 기초해서 록 정보를 얻는다.(되돌아오는
정보는 ldata 에 기술된 록을 '블럭(block)'하는 첫번째 록을 가리킨다.
F_SETLK
화일에 록을 시도하고, 불가능하면 즉시 되돌아온다. 활동중인 록을 제거하
는 데도 사용된다.
F_SETLKW
화일에 록을 시도하고, 이것이 만약 다른 프로세스 소유의 록에 의해 블럭되
면 수행을 중지한다. lockf 에 F_LOCK 를 사용한 경우와 같이 fcntl 록에 의
해서 수행이 중단된 프로세스는 시그널에 의해 인터럽트 될 수 있다.
구조(structure) ldata 는 록 기술어이다. 이의 자료형 flock 은 fcntl.h 에
다음과 같이 정의되어 있다.
short l_type;
short l_whence; /*offset type, like lseek
*/
long l_start;
long l_len;
short l_pid;
l_whence, l_start 그리고 l_len 은 록, 검사, 또는 해제되어절 화일의 구역
을 지정한다. l_whence 는 lseek 의 세번째 인수와 매우 유사하다. 즉 값으로
서 0,1,2 를 갖는 경우에 각각 화일의 처음, 읽기-쓰기 포인터가 가리키는 현
재의 위치, 그리고 화일의 끝을 변위(offset)의 기준점으로서 나타낸다.
l_start 는 구역의 시작 위치를 l_whence 에 대한 상대위치로서 나타낸다.
l_len 은 바이트 단위로서의 구역의 길이이다. lockf 의 경우와 같이 이 값이
0 이면, 세그먼트의 길이는 가능한 최대의 변위가 된다. l_type 은 적용되는
록의 형태를 지시한다. 이에 대한 값들은 fcntl.h 에 다음과 같이 정의되어 있
다.
F_RDLCK 적용되는 록이 읽기 록이다.
F_WRLCK 적용되는 록이 쓰기 록이다.
F_UNLCK 특정 구역에 대한 록을 해제한다.
l_pid 는 fcntl 의 명령으로 F_GETLK 이 선택된 경우에만 유효하다. 현재 시
도하는 록이 기존의 록에 의해 블럭되는 경우, l_pid 는 기존의 록 을 지정한
프로세스의 프로세스 식별번호값을 갖는다.
7.3. IPC 설비
7.3.1. 소개와 기본개념
UNIX 시스템 V 는 IPC 설비라는 새롭고 다양한 프로세스간 통신 방법을 제공
한다. 단위 작업들이 서로 협력하는 시스템을 프로그램할 때 다양한 종류의 방
법론적인 접근이 가능 하게 되었다. 반면에 IPC 에 대한 인터페이스는 보통의
UNIX 개념과는 맞지 않아서, 해당 부분은 시스템의 다른 부분과 부조화를 이룬
다. IPC 설비는 다음의 세 부류로 나뉜다.
1. 메시지 전달
2. 세마포어
3. 공유메모리
IPC 설비 키
가장 중요한 공통 기능은 IPC 설비 키이다. 키란 화일 이름이 화일을 지정하
는 것과 마찬가지로 UNIX 시스템의 IPC 객체를 지정하는 데 사용하는 숫자이
다. 즉 키는 여러 프로세스사이에 IPC 자원이 쉽게 공유되도록 해준다. 지정될
수 있는 객체로는 메시지 큐, 세마포어의 접합, 또는 공유 메모리 세그먼트 등
을 들 수 있다. 키의 실제 자료형은 구현에 좌우되는 자료형 key_t 에 의해 결
정된다. key_t 는 시스템 헤더화일 types.h 에서 정의된다. UNIX 의 어떤 버젼
은 화일의 경로이름을 키로 변환해주는 단순한 라이브러리 함수를 제공한다.
이 루틴의 이름은 ftok 이다.
#include <sys/types.h>
#include <sys/ipc.h>
key_t keyval, ftok();
char *path, id;
.
.
keyval = ftok(path, id);
이루틴은 화일 path 에 관련된 정보에 기초해서 키 값을 돌려준다. 같은 path
값에 대해서라도 id 값이 다르면 다른 키 값이 산출된다. ftok 가 가장 유용한
응용분야는, 명명된 화일 들을 조작하는데 IPC 기능들이 사용될 경우, 또는 필
수 불가결하고 영구적이면서 불변하는 화일에 대한 이름이 주어진 경우이다.
IPC get 연산
프로그램은 IPC 객체를 생성하거나 기존의 것에 접근하려 할 때 key 를 사용
한다. 두가지 모두 IPC get 연산으로 호출된다. 한번 생성된 IPC 설비 식별자
는 유일하다. 즉, 서로 다른 프로세스라도 동일한 IPC 객체를 위해서는 같은
값을 사용한다. 예를 들면, 다음의 문장은 IPC 호출 msgget을 사용하여 새로
운 메시지 큐를 생성한다.
msg_qid = msgget((key_t)0100, 0644|IPC_
CREAT|IPC_EXCL);
msgget 의 첫 인수는 메시지 큐의 키이다.
그밖의 IPC 연산
IPC 설비와 같이 사용되는 연산에는 다음의 두가지 유형이 있다. 하나는 상
태정보를 얻거나 제어 값을 지정하는 제어 연산이다. 이에 속하는 호출로는
msgctl, semctl, shmctl 등이 있다. 다른 하나는 좀 더 특수한 연산으로서,
비록 각각의 호출은 서로 다른 이름을 갖고 있지만, 표준형 매뉴얼에서는 이들
을 msgop, oemop, shmop 이라는 표제하에 모아놓고 있다. 예를 들면, msgop 에
는 다음의 두 함수가 있다. msgsnd 는 메시지 큐에 메시지를 전달하고, msgrcv
는 메시지 큐에서 메시지를 읽어들인다.
상태자료구조
IPC 객체가 생성되면 시스템은 IPC 설비 상태 구조를 만들어서 해당 객체와
관련된 각종 관리 정보를 수록한다. 상태 자료 구조의 자료 형은 메시지, 세마
포어, 공유 메모리마다 하나씩 존재한다. 세가지의 상태 구조 자료형은 모두
공통적으로 허가 구조를 포함한다. 이 허가구조는 다음과 같이 구성되며 태그
(tag) ipc_perm 으로 식별된다.
ushort cuid; /*user-id of creator of IPC
object*/
ushort cgid;
ushort uid;
ushort gid;
ushort umode;
이 상태 자료 구조는 사용자가 IPC 객체를 읽어서 해당 정보를 얻을 수 있는
지, 또는 그 객체에 정보를 쓸 수 있는지를 결정한다.
7.3.2. 메시지 전달
메시지란 본질적으로 문자나 바이트의 열이다.(반드시 널 문자로 끝날 필요는
없다.) 메시지는 프로세스 간에 메시지 큐를 통해 전달되며,메시지큐는 msgget
프리미티브에 의해 생성되고 접근된다. 일단 큐가 만들어지면, 적당한 권리를
가진 프로세스가 msgrcv 에 의해 이 메시지를 큐에 남길 수 있다. 다른 프로세
스는 msgrcv 에 의해 이 메시지를 큐로부터 제거한뒤 읽어들일 수 있다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msg_qid, permflags;
key_t key;
.
.
msg_qid = magget(key, permflags);
의 호출은 두 기능 open 과 creat 를 동시에 수행하는 것과 같이 생각되어질
수 있다. permflags 인수는 msgget 이 수행해야 할 작업을 정확히 결정한다.
이돠 관련이 있는 두개의 상수가 ipc.h 화일에 정의되어 있는데, 이들은 독립
적으로 사용될 수도 있고, 비트끼리 OR 될 수도 있다.
IPC_CREAT
이것은 key 에 해당하는 메시지 큐가 존재하지 않는 경우에 msgget 가 이를
생성하도록 지시한다.
IPC_EXCL
IPC_CREAT 와 이것이 동시에 지정된 경우의 호출은 단지 하나의 메시지 큐
를 생성한다.
msgop 루틴들 : msgsnd 와 msgrcv
일단 큐가 생성되면, 두 개의 msgop 프리미티브를 사용하여 이를 다룰수 있
다. 첫번 것은 msgsnd 이다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msg_qid, size, flags, retval;
struct my_msg{
long mtype;
char mtext[SOMEVALUE];
}message;
.
.
retval = msgsnd(msg_qid, &message, size,
flags);
msgsnd 는 msgget 으로부터 얻은 msg_qid 가 가리키는 큐에 메시지를 보낸다.
메시지 자체는 놀라웁게도 사용자가 제공하는 구조로 선언된 변수 message 에
담겨져 있다.
struct my_msg{
long mtype;
char mtext[SOMEVALUE];
};
msgsnd 의 인수 flags 는 단 하나의 의미있는 값을 갖는데 이는 IPC_NOWAIT
이다. IPC_NOWAIT 가 0 인 경우에는 메시지 전달에 필요한 시스템 자원이 없을
때 호출 프로세스의 수행이 중단된다. msgop 유형에 속하는 또 하나의 함수는
msgrcv 이다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msg_qid, size, flags, retval;
struct my_msg{
long mtype;
char mtext[SOMEVALUE];
}message;
long msg_type;
.
.
retval = msgrcv(msg_qid, &message, size,
msg_type, flags);
msgrcv 가 사용되면, 큐의 사용 허가에 저촉되지 않는 한, msg_id 가 가리키
는 큐로 부터 메시지를 읽어들인다. 메시지를 큐에서 읽게 되면 이는 큐에서
자동적으로 제거된다. 이때 message 변수는 받아들인 메시지를 저장하고, size
변수는 이 구조에 담아둘 수 있는 정보의 최대길이를 지정한다. 호출이 성공하
면 받아들인 메시지의 길이가 retval 에 지정된다. msg_type 인수는 실제로 어
떤 메시지를 받아들 일지를 결정한다. 선택을 하는 기준은 메시지의 mtype 필
드이다. msg_type 의 값이 0 인 경우는 큐의 제일 첫번째 메시지, 즉 가장 일
찍들어온 메시지를 읽어들인다. msg_type 의 값이 0 보다 큰 경우는 해당 값을
가진 메시지의 첫번째 것을 읽는다. 마지막으로 msg_type 이 0 보다 작은 경우
가 있다. 이때는 메시지의 mtype 값이 msg_type 의 절대값보다 작거나 같은 것
중에서 최소값을 갖는 첫번째 메시지를 읽어들인다. 마지막 인수 flags 는 제
어정보를 갖게된다. 유효한 값으로는 IPC_NOWAIT 와 MSG_NOERROR 값을 단독으
로 혹은 OR 해서 사용할 수 있다. MSG_NOERROR 가 지정된 경우, 메시지의 내용
이 size 보다 길면 초과분을 제거한다. 지정되지 않았을 경우에는 msgrcv 가
실패하게 된다.
msgctl 시스템 호출
msgctl 에는 세가지 목적이 있다. 이들은 각각 프로세스에게 메시지 큐의 상
태정보를 주고, 메시지 큐에 관련된 제한사항을 변경할 수 있게 하고, 시스템
상에서 큐를 제거할 수 있게 하는 것이다.
#include <sys/type.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msg_qid, command, retval;
struct msqid_ds msq_stat;
.
.
retval = msgctl(msg_qid, command, &msq_stat
);
물론 msg_qid 는 유효한 메시지 큐 식별자이다. &msq_stat 는 msgid_ds 구조
를 갖는 변수의 주소이다. 이 구조는 msg.h 에 다음과 같이 정의 되어 있다.
struct
ipc_perm msg_perm;
ushort msg_qnum;
ushort msg_qbytes; /*max. no. bytes for
queue*/
ushort msg_lspid;
ushort msg_lrpid;
time_t msg_stime;
time_t msg_rtime;
time_t msg_ctime;
ipc_perm 구조는 앞에서 설명했듯이 메시지 큐와 관련된 소유권과 사용허가를
저장한다. msg_ctl 의 command 인수는 수행될 작업을 표시한다. 사용 가능한
값은 3 개가 있는데 이들은 IPC 기능 3 개에 모두 적용될 수 있다. 이 값들은
ipc.h 에 상수로 정의되어 있다.
IPC_STAT
메시지 큐의 상태정보를 msg_stat 에 담는다.
IPC_SET
msg_stat 에 있는 정보를 바탕으로 메시지 큐에 대한 제어 변수들의 값을
지정한다.
IPC_RMID
이는 메시지 큐를 시스템에서 삭제하게 한다.
7.3.3. 세마포어
이론적 형태의 세마포어
세마포어 sem 이란 다음과 같은 연산이 허용된 :namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />정수형 변수를 말한다(p 와 v
란 이름은 wait 와 signal 이란 말의 네덜란드어에서 나온 것으로 이때 signal
이란 물론 UNIX 의 signal호출과는 다른 것이다).
p(sem) or wait(sem)
if(sem != 0)
decrement sem by one
else
wait until ssem becomes no-zero
v(sem) or signal(sem)
if( queue of waiting processes not
empty)
restart first process in wait
queue
else
increment sem by one
두 연산은 모두 원자화되어야 한다. 즉 sem 을 변경할 수 있는 프로세스는 한
순간에 오직 하나 뿐이다. 세마포어의 좋은 점은 다음의 사실이 항상 만족된다
는 것이다.
(semaphore's initial value
+ number of v operations
- number of completed p operations) >= 0
이를 세마포어의 불변특성(unvatiant)이라 한다. 전산 과학자들은 이러한 불
변 특성을 선호하는데 이는 프로그램을 체계적이고 엄격하게 검정할 수 있도록
하기 때문이다.
UNIX 시스템 V 에서 구현된 세마포어는 이러한 개념에 기초했지만 보다 일반
적인(그리고 아마도 복잡한) 기능을 제공한다. 우선 semget 과 semctl 을 살펴
보자.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
key_t key;
int sem_id, nsems, permflags, command;
int retval, sem_num;
union semun{
int val;
struct semid_ds *stat;
ushort *array;
} ctl_arg;
.
.
sem_id = semget(key, nsems, permflags);
retval = semctl(sem_id, sem_num, command,
ctl_arg);
semget 호출은 msgget 과 유사하다. 인수 nsems는 세마포어 집합에 필요한 세
마포어의 갯수를 나타낸다. semget 호출이 성공하면 세마포어 집합 식별자라는
메시지 큐 식별자와 유사한 역할을 하는 값이 돌아온다. C 언어의 관습을 따라
서 세마포어 집합에 대한 첩자는 0 부터 nsems-1 까지 있을 수 있다. 집합 내
의 각 세마포어는 다음과 같은 값들을 갖게 된다.
semval
세마포어의 값으로서 항상 양수가 지정된다.
sempid
세마포어에 접근했던 최근의 프로세스의 프로세스 식별번호이다.
semncnt
세마포어의 값이 현재보다 증가하기를 기다리는 프로세스의 갯수
semzcnt
세마포어의 값이 0 으로 되기까지 기다리는 프로세스의 갯수
정의에서 알 수 있듯이 함수 semctl 은 msgctl보다 훨씬 복잡하다. sem_id 는
유효한 세마포어 식별자라야 한다. command 는 msgctl 에서와 같이 수행해야
할 정확한 기능을 명시한다.
semctl 기능코드
--------------------------------------------
표준 IPC 기능(semid_ds 구조는 sem.h에 정의됨
--------------------------------------------
IPC_STAT 상태정보를 ctl_arg.stat 에 저장
IPC_SET ctl_arg.stat 에 저장된 형태로 소유
권과 사용 허가권을 지정
IPC_RMID 시스템에서 해당 세마포어의 집합을
삭제
--------------------------------------------
단일 세마포어 연산
( retval 에서 넘어온 값 sem_unm 을 사용 )
--------------------------------------------
GETVAL 세마포어의 값 semval 을 돌려준다.
SETVAL 세마포어 값을 ctl_arg.val 로 지정
GETPID sempid 의 값을 돌려준다.
GETNCNT semncnt 를 돌려준다.
GETZCNT semzcnt 를 돌려준다.
--------------------------------------------
전체 세마포어 연산
--------------------------------------------
GETALL 모든 senvals 의 값을 ctl_arg.array
에 저장한다.
SETALL ctl_arg.array 의 값을 사용하여 모든
semvals 값을 지정한다.
--------------------------------------------
세마포어 연산 : semop 호출
semop 호출 semop 은 기본적인 세마포어 연산을 실제로 수행하는 시스템호출
이다. 이때 semop 은 메뉴얼의 항목이 아니라 실제 함수이름이다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int retval, sem_id;
struct sembuf op_array[SOMEVALUE];
.
.
retval = semop(sem_id, op_array, SOME
VALUE);
sem_id 는 세마포어 집함 식별어로서 이전에 semget 호출을 통해 값이 지정되
어야한다. op_array 는 sembuf 구조의 배열로서 sembuf 구조는 sem.h 에 정의
되어 있다. SOMEVALUE 는 임의의 정수형 상수이다. 각각의 sembuf 구조 변수는
세마포어에 대해 수행할 연산을 지정한다. sembuf 구조를 좀더 자세히 보면 다
음과 같다.
short sem_num;
short sem_op;
short sem_flg;
sem_num 는 집합 내의 세마포어에 대한 첨자를 저장한다. 만약 집합의 원소가
하나뿐이라면 sem_num 의 값은 0 이어야한다. sem_op 는 함수 semop 이 수행해
야 하는 기능을 정수로서 나타낸다.
SEM_UNDO 플래그
이것은 sembuf 구조의 구성요소 sem_flg 에 있는 플래그의 하나이다. 이는
프로세스의 수행이 끝났을 때 시스템이 수행된 연산을 자동적으로 취소하도록
지시한다.
7.3.4. 공유 메모리
공유 메모리 연산은 둘 이상의 프로세스가 실제 메모리의 일부를 공유하게 해
준다(물론 보통의 경우에는 서로 다른 프로세스의 자료영역은 완전히 독립적이
다). 이 기법은 세가지 IPC 기능 중에서 가장 효율적이다. 모든 공유 메모리
연산은 특별한 하드웨어의 지원을 필요로 한다.
sbmget 와 shmop 시스템 호출
공유하는 메모리 영역은 shmget 호출을 통해 생성된다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
key_t key;
int size, permflags, shm_id;
.
.
shm_id = shmget(key, size, permflags);
이는 msgget 이나 semget 과 대응된다. 인수 size 는 공유할 메모리 영역의
필요한 최소 크기를 바이트 단위로 나타낸 커서이다. key 는 영역을 식별하기
위한 키 값이다. permflag 는 메모리 영역에 대한 사용 허가권으로서, msgget
이나 semget 의 경우돠 같이 IPC_CREAT 와 IPC_EXCL 를 사용하여 지정할 수 있
다. 생성 되는 메모리 영역은 프로세스의 논리적 자료 영역이 아니라 실제 메
모리의 일부이다.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shm_id, shmflags;
char *memptr, *daddr, *shmat();
.
.
memptr = shmat(shm_id, daddr, shmflags);
shmat 는 shm_id 가 지정하는 메모리 영역(shmget 호출에 의해 얻어짐)과 호
출 프로세스 의 유효한 주소를 연관 짓는다. daddr 는 호출에서 선택되는 주소
를 프로그래머 가 제어할 수 있게 한다. shmflags 의 값은 두 개의 플래그
SHM_RDONLY 와 SHM_RND 를 조합하 여 정해진다.
shmctl 시스템 호출
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shm_id, retval, command;
struct shmid_ds shm_stat;
.
.
retval = shmctl(shm_id, command, &shm_stat
);
이것은 msgctl 과 정확히 일치한다. command 가 취할 수 있는 값은 IPC_STAT,
IPC_SET 그리고 IPC_RMID 이다.
7.3.5. ipcs 와 ipcrm 명령
IPC 설비를 이용하기 위해 쉘 수준에서는 두개 의 명령어를 제공한다. 첫째는
ipcs 로서 IPC 설비의 현재 상태 정보를 출력한다. 둘째는 ipcrm 명령으로서
시스템에서 IPC 객체 를 제거하기 위해 사용된다. 예를 들어,
$ipcrm -s 0
는 식별자 0 과 연관된 세마포어를 제거한다.또
$ipcrm -S 200
는 키값이 200 인 세마포어를 제거한다.
'Academy I > Tech Academy' 카테고리의 다른 글
Linux make 사용법 [I] (0) | 2014.12.18 |
---|---|
Unix System Programming 10 (0) | 2014.12.16 |
Unix System Programming 9 (0) | 2014.12.16 |
Unix System Programming 8 (0) | 2014.12.16 |
Unix System Programming 6 (0) | 2014.12.16 |
Unix System Programming 5 (0) | 2014.12.16 |
Unix System Programming 4 (0) | 2014.12.16 |
Unix System Programming 3 (0) | 2014.12.16 |