[英]Message queue (msgget - msgsnd - msgrcv) Linux - EIDRM
這是我的問題:我正在嘗試在服務器和客戶端之間實現消息隊列。 為此,我有兩個文件, msq-server.c
和msq-client.c
。
我使用函數msgctl(msqid, IPC_RMID, &buf)
退出服務器(例如,當我們要求他讀取消息隊列3次msgctl(msqid, IPC_RMID, &buf)
)。
與往常一樣, msqid
由msgget函數設置,而buf由struct msqid_ds buf
定義。
官方的msgctl文檔說,對於讀者(客戶端),errno設置為EIDRM(43),並且我想在發生錯誤時顯示自定義錯誤。 但是,當我嘗試從關閉的服務器讀取消息時,函數msgrcv(msqid, &message, 64, 0, IPC_NOWAIT)
返回EINVAL錯誤。 我認為msqid有罪
對於功能msgget
IPC_CREAT | IPC_EXCL |0666
IPC_CREAT | IPC_EXCL |0666
標志 IPC_EXCL | 0666
IPC_EXCL | 0666
標志 感謝您的幫助
當您通過msgctl()刪除消息隊列時,在讀取消息隊列時,msgrcv()將返回EIDRM(43)。
當您嘗試從不再存在的消息隊列中讀取消息時(因為已將其刪除),msgrcv()將返回EINVAL(22)。
請參見下面的示例。
服務器啟動,並將一條消息放入隊列。 然后等待。
客戶端啟動並讀取第一條消息,然后阻止等待從未到達的第二條消息。
服務器在客戶端等待第二條消息時刪除隊列,並看到EIDRM返回碼。
然后,客戶端嘗試再次讀取,並且由於沒有可用的隊列,因此會看到EINVAL。
msg_server.c
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct msgbuf {
long mType;
char mText[50];
};
int main() {
char txtBuf[50];
int qId;
key_t key;
struct msgbuf msg, buf;
struct msqid_ds msgCtlBuf;
if ( ( key = ftok( "/tmp", 'C' ) ) == -1 ) {
perror( "server: ftok failed:" );
exit( 1 );
}
printf( "server: System V IPC key = %u\n", key );
if ( ( qId = msgget( key, IPC_CREAT | 0666 ) ) == -1 ) {
perror( "server: Failed to create message queue:" );
exit( 2 );
}
printf( "server: Message queue id = %u\n", qId );
strcpy( msg.mText, "This is a message" );
msg.mType = 1;
if ( msgsnd( qId, &msg, sizeof msg.mText, 0 ) == -1 ) {
perror( "server: msgsnd failed:" );
exit( 3 );
}
printf( "server: Message sent successfully\n" );
printf( "server: waiting..." );
sleep( 15 );
printf( "server: done waiting. removing message queue...\n" );
if ( msgctl( qId, IPC_RMID, &msgCtlBuf ) == -1 ) {
perror( "server: msgctl failed:" );
exit( 4 );
}
printf( "server: Message queue removed OK\n" );
}
msg_client.c
#include <sys/msg.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct msgbuf {
long mType;
char mText[50];
};
int main() {
char txtBuf[50];
int qId;
key_t key;
struct msgbuf msg, buf;
struct msqid_ds msgCtlBuf;
if ( ( key = ftok( "/tmp", 'C' ) ) == -1 ) {
perror( "client: ftok failed:" );
exit( 1 );
}
printf( "client: System V IPC key = %u\n", key );
if ( ( qId = msgget( key, IPC_CREAT | 0666 ) ) == -1 ) {
perror( "client: Failed to create message queue:" );
exit( 2 );
}
printf( "client: Message queue id = %u\n", qId );
if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
perror( "client: msgrcv failed:" );
else
printf( "client: Message received = %s\n", buf.mText );
//
// attempt read again and block on queue waiting for server to IPC_RMID
//
if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
perror( "client: msgrcv failed:" );
else
printf( "client: Message received = %s\n", buf.mText );
printf( "client: errno = %d\n", errno );
//
// attempt read again but message queue should now be gone
//
if ( msgrcv( qId, &buf, sizeof msg.mText, 1, 0 ) == -1 )
perror( "client: msgrcv failed:" );
else
printf( "client: Message received = %s\n", buf.mText );
printf( "client: errno = %d\n", errno );
}
./msg_server和
[1] 668
服務器:系統V IPC密鑰= 1124335618
服務器:消息隊列標識= 262144
服務器:消息發送成功
./msg_client
客戶端:系統V IPC密鑰= 1124335618
客戶端:消息隊列標識= 262144
客戶端:收到消息=這是一條消息
服務器:正在等待...服務器:已完成等待。 正在刪除郵件隊列...
服務器:消息隊列已刪除,確定
客戶端:msgrcv失敗::標識符已刪除
客戶:errno = 43
客戶端:msgrcv失敗::無效參數
客戶端:errno = 22
[1] +出口33 ./msg_server
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.