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

시스템 호출:msgctl() (SYSTEM CALL:msgctl())

이전에 wrapper 함수들의 개발이 제공되었지만, 응용프로그램에서 메세지 큐를 만들고, 활용하기 위한 간단하고 우아한 접근방법을 가지고 있다. 주어진 메세지 큐와 연관된 내부 구조체를 직접 조종하기 위한 토론에 들어가 보자.

메세지 큐의 통제 동작을 수행하기 위해, msgctl() 시스템 호출을 사용한다.


  SYSTEM CALL: msgctl();
  PROTOTYPE: int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
    RETURNS: 0 on success
             -1 on error: errno = EACCES (No read permission and cmd is IPC_STAT)
                                  EFAULT (Address pointed to by buf is invalid with IPC_SET and
                                          IPC_STAT commands)
                                  EIDRM  (Queue was removed during retrieval)
                                  EINVAL (msgqid invalid, or msgsz less than 0)
                                  EPERM  (IPC_SET or IPC_RMID command was issued, but
                                          calling process does not have write (alter)
                                          access to the queue)
  NOTES:

내부 커널 자료 구조의 직접적인 조종은 밤 늦도록 재미를 가져다 줄 수도 있다. 불행스럽게도, 프로그래머들의 일부에게 남겨진 임무는 잡동사니인 IPC subsystem을 좋아한다면 재미로 분류되어 질 수 있다. 선택된 명령어 집합을 가지고 msgctl()를 사용하여, 재난을 일으킬 가능성이 적은 아이템을 조종할 수 있는 능력을 갖는다.

IPC_STAT

큐에서 msqid_ds 구조체를 조회하여 버퍼 아규먼트의 주소지에 저장한다.

IPC_SET

큐의 msqid_ds 구조체의 ipc_perm 멤버의 값을 지정한다. 버퍼 아규먼트로 부터 값을 취한다.

IPC_RMID

커널로 부터 큐를 제거한다.

메세지 큐에 대한 내부 자료 구조(msqid_ds)에 대해 언급했던 내용을 상기하자. 커널은 시스템에 존재하는 각각의 큐에 대해 이러한 구조체를 하나씩 가지고 있다. IPC_STAT 명령어를 사용하여 검사를 위해 이 구조체의 복사본을 조회할 수 있다. 내부 구조를 조회하여 넘겨진 주소로 복사하는 빠른 wrapper 함수를 살펴보자.:


int get_queue_ds( int qid, struct msgqid_ds *qbuf )
{
        if( msgctl( qid, IPC_STAT, qbuf) == -1)
        {
                return(-1);
        }
        
        return(0);
}

내부 버퍼로 복사할 수 없다면 호출한 함수에게 -1이 반환된다. 모든 것이 잘 되면, 0값이 반환되고 넘겨진 버퍼는 넘겨받은 큐 확인자(queue identifier,qid)에 의해 대표되는 메세지 큐에 대한 내부 자료 구조의 복사본을 갖는다.

큐의 내부 자료 구조체의 복사본을 가지고 있을 때, 어떤 특성을 조종할 수 있고, 그것들을 어떻게 변경시킬 수 있는가? 자료 구조 안에서 오직 수정할 수 있는 아이템은 ipc_perm 멤버이다. 이것은 주인(owner)와 생성자(creator)에 대한 정보는 물론, 큐의 허가사항도 포함한다. 그렇지만 수정될 수있는 ipc_perm 구조체의 멤버들은 mode,uid,gid 뿐이다. 주인(owner)의 user id, 주인(owner)의 group id, 큐의 접근 허가사항(access permission)을 바꿀 수 있다.

큐의 모드(mode)를 바꾸도록 고안된 wrapper 함수를 만들어 보자. 모드(mode)는 문자 배열로 넘겨져야 한다 (i.e. "660").


int change_queue_mode( int qid, char *mode )
{
        struct msqid_ds tmpbuf;

	/* 내부 자료 구조의 현재 복사본을 조회한다 */
        get_queue_ds( qid, &tmpbuf);

	/* 옛날의 기교를 사용하여 허가사항(permission)을 수정한다 */
        sscanf(mode, "%ho", &tmpbuf.msg_perm.mode);

	/* 내부 자료 구조를 수정한다 */
        if( msgctl( qid, IPC_SET, &tmpbuf) == -1)
        {
                return(-1);
        }
        
        return(0);
}

get_queue_ds wrapper 함수를 간단히 호출하여 내부 자료 구조의 현재 복사본을 조회한다. 연관된 msg_perm 구조의 mode 멤버를 변경하기 위해 sscanf()를 호출한다. 새 복사본을 내부 버전에 업데이트하기 전에는 아무런 변화도 일어나지 않는다. 이러한 일은 IPC_SET 명령어를 사용하여 msgctl()를 호출하여 수행할 수 있다.

주의! 큐의 허가사항을 변경할 수 있고, 그렇게 해서 본의아니게 스스로를 차단시킬 수 있다. 기억하라, 이러한 IPC 객체들은 적당히 제거하거나 시스템을 재부팅하지 않으면 없어지지 않는다. 따라서 ipcs를 가지고 큐를 볼 수 없다고 하여 존재하지 않는다는 것을 의미하지는 않는다.

이 점을 설명하기 위해, 다소 재미있는 일화를 소개하겠다. South Florida 대학에서 유닉스 내부를 가르치는 동안, 나는 아주 당황스럽고 어리둥절한 차단(Blocking)에 직면했다. 지난밤에 나는 일주일간의 수업에서 사용된 연구박업을 테스트하고 컴파일하기 위해 연구실 서버에 접속했다. 테스트를 하는 동안에 나는 코드안에 메세지 큐의 허가사항(permission)을 변경하는 타입을 만들었다는 사실을 깨달았다. 나는 간단한 메세지 큐를 만들었고, 아무런 사고없이 주고 받을 수 있는지를 테스트 했다. 그렇지만, 내가 큐의 모드를 "660"에사 "600"으로 수정하려고 했을 때, 내 자신의 큐로 부터 나 자신을 막아버리는 결과를 초래했다. 결과적으로 나는 내 소스 디렉토리의 같은 영역에서 메세지 큐 연구작업을 테스트 할 수 없었다. 내가 IPC 키를 만들기 위해 ftok() 함수를 사용했기에, 내가 큐에 접근하려고 할 때 나는 적당한 허가사항(permission)을 갖고 있지 못했다. 수업이 있는 아침에 결국 나는 지역 시스템 관리자에게 메세지 큐가 무엇인지와 왜 그가 나를 위해 ipcrm 명령어를 수행시켜야 하는지를 한시간동안 설명하고 접속을 끝냈다.
큐로부터 성공적으로 메세지를 받은 후, 메세지는 제거된다. 앞에서도 언급했던 것처럼, IPC 객체는 명백히 제거되거나 시스템을 재부팅하지 않는 한 시스템에 남아 있는다. 그러므로, 우리의 메세지 큐는 여전히 커널안에 존재하고 단일 메세지가 사라진 후에도 계속 사용할 수 있다. 메세지 큐의 생명 주기(life cycle)를 완성하기 위해 IPC_RMID 명령어를 사용하여 msgctl()를 호출에 의해 제거되어야 한다.:


int remove_queue( int qid )
{
        if( msgctl( qid, IPC_RMID, 0) == -1)
        {
                return(-1);
        }
        
        return(0);
}

이 wrapper 함수는 큐가 사고없이 제거되면 0을 반환하고 아니면 -1을 반환한다. 큐의 제거는 자연적으로 atomic하고 어떤 목적에서건 큐에 대한 어떤 일련의 접근도 형편없이 실패할 것이다.


이전:시스템 호출:msgsnd() 다음:msgtool:상호작용 메세지 큐 조종자

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