複製鏈接
請複製以下鏈接發送給好友

msgctl

鎖定
msgctl()定義在sys/msg.h中,其函數原型為:int msgctl(int msqid,int cmd,struct msqid_ds *buf),msgctl系統調用對msqid標識的消息隊列執行cmd操作列。
中文名
msgctl
調用原型
int msgctl
返回值
0 ,如果成功
使用命令
IPC_STAT

msgctl系統調用

我們先來説一下,隊列的msqid_ds結構,對於每一個隊列都有一個msqid_ds來描述隊列當前的狀態。結構定義如下:
struct msqid_ds {//Linux系統中的定義
struct ipc_perm msg_perm; /* Ownership and permissions
time_t msg_stime; /* Time of last msgsnd() */
time_t msg_rtime; /* Time of last msgrcv() */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes inqueue (non-standard) */
msgqnum_t msg_qnum; /* Current number of messagesin queue */
msglen_t msg_qbytes; /* Maximum number of bytesallowed in queue */
pid_t msg_lspid; /* PID of last msgsnd() */
pid_t msg_lrpid; /* PID of last msgrcv() */
};//不同的系統中此結構會有不同的新成員
下面我們繼續討論如何使用一個給定的消息隊列的內部數據結構。我們可以使用系統調用msgctl ( )來控制對消息隊列的操作。

msgctl調用原型

int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );

msgctl頭文件:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

msgctl返回值:

0 ,如果成功。
- 1,如果失敗:errno = EACCES (沒有讀的權限同時cmd 是IPC_STAT )
EFAULT (buf 指向的地址無效)
EIDRM (在讀取中隊列被刪除)
EINVAL (msgqid無效, 或者msgsz 小於0 )
EPERM (IPC_SET或者IPC_RMID 命令被使用,但調用程序沒有寫的權限)

msgctl使用命令

IPC_STAT
讀取消息隊列的數據結構msqid_ds,並將其存儲在b u f指定的地址中。
IPC_SET
設置消息隊列的數據結構msqid_ds中的ipc_perm元素的值。這個值取自buf參數。
IPC_RMID
從系統內核中移走消息隊列。
我們在前面討論過了消息隊列的數據結構(msqid_ds)。系統內核中為系統中的每一個消息隊列保存一個此數據結構的實例。通過使用IPC_STAT命令,我們可以得到一個此數據結構的副本。下面的程序就是實現此函數的過程: int get_queue_ds( int qid, struct msgqid_ds *qbuf )
{
if( msgctl( qid, IPC_STAT, qbuf) == -1)
{
return(-1);
}
return(0);
} 如果不能複製內部緩衝區,調用進程將返回-1。如果調用成功,則返回0。緩衝區中應該包括消息隊列中的數據結構。
消息隊列中的數據結構中唯一可以改動的元素就是ipc_perm。它包括隊列的存取權限和關於隊列創建者和擁有者的信息。你可以改變用户的id、用户的組id以及消息隊列的存取權限。
下面是一個修改隊列存取模式的程序: 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(
} 我們通過調用get_queue_ds來讀取隊列的內部數據結構。然後,我們調用sscanf( )修改數據結構msg_perm中的mode 成員的值。但直到調用msgctl()時,權限的改變才真正完成。在這裏msgctl()使用的是IPC_SET命令。
最後,我們使用系統調用msgctl ( )中的IPC_RMID命令刪除消息隊列: int remove_queue(int qid )
{
if( msgctl( qid, IPC_RMID, 0) == -1)
{
return(-1);
}
return(0);
}
};