메세지 큐의 통제 동작을 수행하기 위해, 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:
int get_queue_ds( int qid, struct msgqid_ds *qbuf ) { if( msgctl( qid, IPC_STAT, qbuf) == -1) { return(-1); } return(0); }
큐의 내부 자료 구조체의 복사본을 가지고 있을 때, 어떤 특성을 조종할 수 있고, 그것들을 어떻게 변경시킬 수 있는가? 자료 구조 안에서 오직 수정할 수 있는 아이템은 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); }
주의! 큐의 허가사항을 변경할 수 있고, 그렇게 해서 본의아니게 스스로를 차단시킬 수 있다. 기억하라, 이러한 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); }
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