通过msgctl()函数,我们可以直接控制消息队列的行为。它在系统库linux/msg.h 中的
定义是这样的: 系统调用: msgctl() 函数声明: int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ) 返回值: 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) 函数的第一个参数msgqid 是消息队列对象的标识符。 第二个参数是函数要对消息队列进行的操作,它可以是: IPC_STAT 取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构 中。 IPC_SET 设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds 结构给出。 IPC_EMID 将队列从系统内核中删除。 这三个命令的功能都是明显的,所以就不多解释了。唯一需要强调的是在IPC_STAT 命令中队列的msqid_ds 数据中唯一能被设定的只有msg_perm 成员,其是ipc_perm 类型的 数据。而ipc_perm 中能被修改的只有mode,pid 和uid 成员。其他的都是只能由系统来设定 的。 最后我们将使用msgctl()函数来开发几个封装函数作为本节的例子: IPC_STAT 的例子: int get_queue_ds( int qid, struct msgqid_ds *qbuf ) { if( msgctl( qid, IPC_STAT, qbuf) == -1) { return(-1); } return(0); } IPC_SET 的例子: int change_queue_mode( int qid, char *mode ) { struct msqid_ds tmpbuf; /* Retrieve a current copy of the internal data structure */ get_queue_ds( qid, &tmpbuf); /* Change the permissions using an old trick */ sscanf(mode, "%ho", &tmpbuf.msg_perm.mode); /* Update the internal data structure */ if( msgctl( qid, IPC_SET, &tmpbuf) == -1) { return(-1); } return(0); } IPC_RMID 的例子: int remove_queue( int qid ) { if( msgctl( qid, IPC_RMID, 0) == -1) { return(-1); } return(0); } |
|