다음 위로 이전 목차 리눅스 프로그래머를 위한 가이드

내부와 사용자 자료 구조 (Internal and User Data Structures)

시스템 V IPC와 같이 복잡한 주제를 충분히 이해하기 위한 열쇠는 한정된 커널 안에 존재하는 다양한 내부 자료 구조와 직접적으로 친해지는 것이다. 나머지들이 더 낮은 단계이 존재하고 있는 한, 이러한 구조에 대한 직접적인 접근은 가장 기본적인 동작에서 필요하다.



메세지 버퍼 (Message buffer)

가장 처음으로 만날 구조는 msgbuf 구조이다. 이 특별한 자료 구조는 메세지 자료를 위한 템플릿(template)라 생각할 수 있다. 프로그래머가 이러한 타입의 구조를 정의하여 사용하지 않는 한, msgbuf 타입의 구조를 실제적으로 이해하는 것은 필수적이다. linux/msg.h에 다음과 같이 선언되어 있다.:


/* message buffer for msgsnd and msgrcv calls */
/* msgsnd와 msgrcv 호출을 위한 메세지 버퍼 */
struct msgbuf {
	long mtype;	/* type of message 메세지 타입 */
	char mtext[1];	/* message text 메세지 내용 */
};

msgbuf 구조에는 두개의 멤버가 있다.:

mtype

양수로 표현되는 메세지 타입. 반드시 양수여야 한다.

mtext

메세지 자료 자체.

주어진 메세지에 타입을 부여하는 능력은 본질적으로 단일 큐에서의 다중(multiplex) 메세지들을 수용할 능력을 부여한다. 예를 들면, 클라이언트 프로세스들은 매직번호 (magic number)를 할당받을 수 있고 이것은 서버 프로세스로 부터 보내진 메세지들에 대해 메세지 타입처럼 사용될 수 있다. 서버는 자체적으로 몇몇의 다른 번호를 사용할 수 있고, 클라이언트는 그번호로 메세지를 보내기 위해 사용할 수 있다. 또 다른 시나리오에서는 응용프로그램은 에러 메세지에 대해 메세지 타입 '1'를 요청 메세지(request message)에 대해 메세지 타입 '2'를 표시할 수 있다. 이러한 가능성은 끝이 없다.

또 다른 방법은 대개 메세지 자료 요소 (mtext)에 매우 서술적인 이름을 부여하여 현혹되지 않도록 하는 것이다. 이 필드는 꼭 문자들의 배열이여야 할 필요는 없다. 어떤 형태의 어떤 자료이든 상관없다. 이 구조는 응용프로그램 프로그래머에 의해 재정의될 수 있으므로, 필드 그 자체만으로도 실제로 완전히 마음대로이다.


struct my_msgbuf {
	long	mtype;		/* Message type  메세지 타입 */
	long	request_id;	/* Request identifier 요청 확인자 */
	struct	client info;	/* Client information structure 클라이언트 정보 구조 */
};

전과 같은 메세지 타입을 볼 수 있지만, 구조의 나머지는 두개의 다른 요소로 바뀌었다. 그 중 하나는 또 다른 구조체(structure)이다! 이것이 메세지 큐의 장점이다. 커널은 자료가 무엇이든 자료의 변환을 일으키지 않는다. 어떤 정보든지 보내질 수 있다.

주어진 메세지의 최대 크기에 대한 내부적인 제한은 없다. 리눅스에서는 linux/msg.h에 다음과 같이 정의되어 있다.:

#define	MSGMAX	4056	/* <= 4056 */	/* max size if message (bytes) 메세지의 최대 크기 */

메세지는 길이가 4바이트(long)인 mtype 멤버를 포함하여 총 크기 4,056바이트보다 클 수 없다.


커널 msg 구조 (Kernel msg structure)

커널은 각각의 메세지를 msg 구조체의 모앙으로 큐안에 저장한다. 이것은 linux/msg.h에 다음과 같이 정의되어 있다.


/* 각 메세지에 대한 한개의 메세지 구조체 */
struct msg {
	struct	msg *msg_next;	/* 큐에서의 다음 메세지 */
	long	msg_type;
	char	*msg_spot;	/* 메세지 내용 주소 */
	short	msg_ts;		/* 메세지 내용 크기 */
};

msg_next

이것은 큐안에서의 다음 메세지에 대한 포인터이다. 이것은 커널의 주소매겨진 공간 (kernel addressing space)안에 한줄로 연결된 목록(singly linked list)처럼 저장되어 있다.

msg_type

이것은 사용자 구조체인 msgbuf에 할당된 메세지 타입이다.

msg_spot

메세지 본체의 시작점을 가리키는 포인터

msg_ts

메세지 내용 또는 본체의 길이

커널 msqid ds 구조 (Kernel msqid ds structure)

IPC 객체의 세가지 타입의 각각은 커널에 의해 유지되는 내부 자료 구조를 가진다. 메세지 큐에서는 msq_id 구조이다. 커널은 시스템 상에서 생성되는 모든 메세지 큐에 대해 이러한 구조를 하나씩 만들어 저장하고 관리한다. linux/msg.h에 다음과 같이 정의되어 있다.:


/* 시스템상에서 각 큐에 대한 msqid 구조 */
struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg *msg_first;  /* first message on queue 큐의 처음 메세지*/
    struct msg *msg_last;   /* last message in queue 큐의 마지막 메세지*/
    time_t msg_stime;       /* last msgsnd time 마지막으로 msgsnd가 수행된 시간*/
    time_t msg_rtime;       /* last msgrcv time 마지막으로 msgrcv가 수행된 시간*/
    time_t msg_ctime;       /* last change time 마지막으로 change가 수행된 시간*/
    struct wait_queue *wwait;
    struct wait_queue *rwait;
    ushort msg_cbytes;    
    ushort msg_qnum;     
    ushort msg_qbytes;      /* max number of bytes on queue 큐의 최대 바이트 수*/
    ushort msg_lspid;       /* pid of last msgsnd 마지막으로 msgsnd를 수행한 pid*/
    ushort msg_lrpid;       /* last receive pid 마지막으로 받은 pid*/
};

이 구조체의 대부분의 멤버들에 대해 관심을 갖는 일은 거의 없지만, 우리들의 여행을 완성시키기 위해 각각에 대해 간단히 설명하겠다.

msg_perm

ipc_perm 구조체의 하나로 linux/ipc.h에 정의되어 있다. 이것은 접근 허가사항(access permissions)과 큐의 생성자(creator)에 대한 정보(uid, etc)를 포함하는 메세지 큐의 허가사항 정보를 가지고 있다.

msg_first

큐의 첫번째 메세지와 연결되어 있다.(the head of the list)

msg_last

큐의 마지막 메세지와 연결되어 있다.(the tail of the list)

msg_stime

큐에 보내진 마지막 메세지의 시간 기록(Timestamp)

msg_rtime

큐로 부터 조회된 마지막 메세지의 시간 기록(Timestamp)

msg_ctime

큐에서 일어난 마지막 변화(change)의 시간 기록(Timestamp) (more on this later)

wwait

and

rwait

커널의 대기 큐(wait queue)를 가리키는 포인터. 메세지 큐에 있는 동작이 프로세스가 sleep 상태로 들어가는 것으로 간주할 때 사용된다. (i.e. 큐가 가득차서 프로세스가 열리기(opening)를 기다리고 있는 경우)

msg_qnum

현재 큐에 들어 있는 메세지의 갯수

msg_qbytes

큐 상의 최대 바이트 수

msg_lspid

마지막 메세지를 보낸 프로세스의 PID

msg_lrpid

마지막 메세지를 조회한 프로세스의 PID


커널 ipc perm 구조 (Kernel ipc perm structure)

커널은 ipc_perm 타입의 구조체 안에 IPC 객체의 허가사항(permission) 정보를 저장한다. 예를 들면, 앞에서 설명한 메세지 큐의 내부 구조에서는 msg_perm 멤버가 이런 타입이다. linux/ipc.h 안에 다음과 같이 선언되어 있다.:


struct ipc_perm
{
  key_t  key;
  ushort uid;   /* owner euid and egid */
  ushort gid;
  ushort cuid;  /* creator euid and egid */
  ushort cgid;
  ushort mode;  /* access modes see mode flags below */
  ushort seq;   /* slot usage sequence number */
};

위의 내용등은 모두 명백히 자기 해석적이다. 객체의 IPC 키를 가지고 저장되어 있는 것은 그 객체의 생성자(creator)와 주인(owner)에 대한 정보이다. (creator와 owner는 서로 다를 수 있음) 8진 접근 모드(the octal access mode) 또한 usigned short형태로 여기에 저장되어 있다. 마지막으로 slot usage sequence 번호가 끝에 저장되어 있다. 매번 IPC 객체는 시스템 호출 (destroyed)을 경유하여 닫힌다. 이 값은 시스템 안에 존재할 수 있는 IPC 객체의 최대수에 의해 증가된다. 이 값에 대해 우리가 관심을 가져야 하는가? 아니다.

NOTE:Richard Stevens의 UNIX Network Programming 125쪽에 이 주제에 대한 자세한 내용과 이것의 존재와 동작의 보안 이유등이 잘 설명되어 있다.


이전:기본 개념 (Basic Concepts) 다음:시스템 호출:msgget() (SYSTEM CALL:msgget())

Copyright (c) 1996,1997 by Euibeom.Hwang & SangEun.Oh All Rights Reserved

Email To:Webmaster , Another address
LAST UPDATE Nov 18,1997
Created Nov 17,1997