⑴ 高手進!在linux系統中用消息隊列實現兩個進程之間的信息傳輸的一個小程序,幫忙改下錯,急!!!!
你只在
server
進程中(對應spid==0),調用
open_queue
來打開
消息隊列
,即msqid只在這個進程中有效,在host進程中(對應cpid==0),由於msqid無效,所以無法發送消息。
解決方法:只要把
do
{
msqid
=
open_queue(key);
}
while
(msqid
==
-1);
這段代碼移到第一個fork之前,這樣所有的進程中的msqid就都指向那個隊列了。
還有問題可以
hi我,別忘了加分。
⑵ 如何在linux下看消息隊列是否存在
#include
#include
#include
#include types.h>
#include msg.h>
#include
#include ipc.h>
void msg_show_attr(int msg_id, struct msqid_ds msg_info)
{
int ret = -1;
sleep(1);
ret = msgctl(msg_id, IPC_STAT, &msg_info);
if( -1 == ret)
{
printf(獲消息信息失敗\n);
return ;
}
printf(\n);
printf(現隊列位元組數:%d\n,msg_info.msg_cbytes);
printf(隊列消息數:%d\n,msg_info.msg_qnum);
printf(隊列位元組數:%d\n,msg_info.msg_qbytes);
printf(發送消息進程pid:%d\n,msg_info.msg_lspid);
printf(接收消息進程pid:%d\n,msg_info.msg_lrpid);
printf(發送消息間:%s,ctime(&(msg_info.msg_stime)));
printf(接收消息間:%s,ctime(&(msg_info.msg_rtime)));
printf(變化間:%s,ctime(&(msg_info.msg_ctime)));
printf(消息UID:%d\n,msg_info.msg_perm.uid);
printf(消息GID:%d\n,msg_info.msg_perm.gid);
}
int main(void)
{
int ret = -1;
int msg_flags, msg_id;
key_t key;
struct msgmbuf{
int mtype;
char mtext[10];
};
struct msqid_ds msg_info;
struct msgmbuf msg_mbuf;
int msg_sflags,msg_rflags;
char *msgpath = /ipc/msg/;
key = ftok(msgpath,』a');
if(key != -1)
{
printf(功建立KEY\n);
}
else
{
printf(建立KEY失敗\n);
}
msg_flags = IPC_CREAT;
msg_id = msgget(key, msg_flags|0666);
if( -1 == msg_id)
{
printf(消息建立失敗\n);
return 0;
}
msg_show_attr(msg_id, msg_info);
msg_sflags = IPC_NOWAIT;
msg_mbuf.mtype = 10;
memcpy(msg_mbuf.mtext,測試消息,sizeof(測試消息));
ret = msgsnd(msg_id, &msg_mbuf, sizeof(測試消息), msg_sflags);
if( -1 == ret)
{
printf(發送消息失敗\n);
}
msg_show_attr(msg_id, msg_info);
msg_rflags = IPC_NOWAIT|MSG_NOERROR;
ret = msgrcv(msg_id, &msg_mbuf, 10,10,msg_rfla
共享內存示例代碼:
#include
#include sem.h>
#include ipc.h>
#include
typedef int sem_t;
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
} arg;
sem_t CreateSem(key_t key, int value)
{
union semun sem;
sem_t semid;
sem.val = value;
semid = semget(key,value,IPC_CREAT|0666);
if (-1 == semid)
{
printf(create semaphore error\n);
return -1;
}
semctl(semid,0,SETVAL,sem);
return semid;
}
/*
struct sembuf{
ushort sem_num;
short sem_op;
short sem_flg;
};
*/
void SetvalueSem(sem_t semid, int value)
{
union semun sem;
sem.val = value;
semctl(semid,0,SETVAL,sem);
return ;
}
int GetvalueSem(sem_t semid)
{
union semun sem;
return semctl(semid,0,GETVAL,sem);
return sem.val;
}
void DestroySem(sem_t semid)
{
union semun sem;
sem.val = 0;
semctl(semid,0,IPC_RMID,sem);
}
int Sem_P(sem_t semid)
{
struct sembuf sops={0,+1,IPC_NOWAIT};
return (semop(semid,&sops,1));
}
int Sem_V(sem_t semid)
{
struct sembuf sops={0,-1,IPC_NOWAIT};
return (semop(semid,&sops,1));
}
static char msg[]=共享內存\n;
int main(void)
{
key_t key;
int semid,shmid;
char i,*shms,*shmc;
struct semid_ds buf;
int value = 0;
char buffer[80];
pid_t p;
key = ftok(/ipc/sem/,』a');
shmid = shmget(key,1024,IPC_CREAT|0604);
semid = CreateSem(key,1);
p = fork();
if(p > 0)
{
/* 父進程 */
/* 建立共享內存 */
shms = (char *)shmat(shmid,0,0);
memcpy(shms, msg, strlen(msg)+1);
sleep(10);
Sem_P(semid);
shmdt(shms);
DestroySem(semid);
}
else if(p == 0)
{
shmc = (char *)shmat(shmid,0,0);
Sem_V(semid);
printf(共享內存值:%s\n,shmc);
shmdt(sg_
⑶ 如何用JAVA實現Linux上的消息隊列功能
下面來說說如何用不用消息隊列來進行進程間的通信,消息隊列與命名管道有很多相似之處。有關命名管道的更多內容可以參閱我的另一篇文章:Linux進程間通信——使用命名管道
一、什麼是消息隊列
消息隊列提供了一種從一個進程向另一個進程發送一個數據塊的方法。 每個數據塊都被認為含有一個類型,接收進程可以獨立地接收含有不同類型的數據結構。我們可以通過發送消息來避免命名管道的同步和阻塞問題。但是消息隊列與命名管道一樣,每個數據塊都有一個最大長度的限制。
Linux用宏MSGMAX和MSGMNB來限制一條消息的最大長度和一個隊列的最大長度。
二、在Linux中使用消息隊列
Linux提供了一系列消息隊列的函數介面來讓我們方便地使用它來實現進程間的通信。它的用法與其他兩個System V PIC機制,即信號量和共享內存相似。
1、msgget函數
該函數用來創建和訪問一個消息隊列。它的原型為:
int msgget(key_t, key, int msgflg);
與其他的IPC機制一樣,程序必須提供一個鍵來命名某個特定的消息隊列。msgflg是一個許可權標志,表示消息隊列的訪問許可權,它與文件的訪問許可權一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的消息隊列不存在時創建一個消息隊列,如果key所命名的消息隊列存在時,IPC_CREAT標志會被忽略,而只返回一個標識符。
它返回一個以key命名的消息隊列的標識符(非零整數),失敗時返回-1.
2、msgsnd函數
該函數用來把消息添加到消息隊列中。它的原型為:
int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);
msgid是由msgget函數返回的消息隊列標識符。
msg_ptr是一個指向准備發送消息的指針,但是消息的數據結構卻有一定的要求,指針msg_ptr所指向的消息結構一定要是以一個長整型成員變數開始的結構體,接收函數將用這個成員來確定消息的類型。所以消息結構要定義成這樣:
struct my_message{
long int message_type;
/* The data you wish to transfer*/
};
msg_sz是msg_ptr指向的消息的長度,注意是消息的長度,而不是整個結構體的長度,也就是說msg_sz是不包括長整型消息類型成員變數的長度。
msgflg用於控制當前消息隊列滿或隊列消息到達系統范圍的限制時將要發生的事情。
如果調用成功,消息數據的一分副本將被放到消息隊列中,並返回0,失敗時返回-1.
3、msgrcv函數
該函數用來從一個消息隊列獲取消息,它的原型為
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);
msgid, msg_ptr, msg_st的作用也函數msgsnd函數的一樣。
msgtype可以實現一種簡單的接收優先順序。如果msgtype為0,就獲取隊列中的第一個消息。如果它的值大於零,將獲取具有相同消息類型的第一個信息。如果它小於零,就獲取類型等於或小於msgtype的絕對值的第一個消息。
msgflg用於控制當隊列中沒有相應類型的消息可以接收時將發生的事情。
調用成功時,該函數返回放到接收緩存區中的位元組數,消息被復制到由msg_ptr指向的用戶分配的緩存區中,然後刪除消息隊列中的對應消息。失敗時返回-1.
4、msgctl函數
該函數用來控制消息隊列,它與共享內存的shmctl函數相似,它的原型為:
int msgctl(int msgid, int command, struct msgid_ds *buf);
command是將要採取的動作,它可以取3個值,
IPC_STAT:把msgid_ds結構中的數據設置為消息隊列的當前關聯值,即用消息隊列的當前關聯值覆蓋msgid_ds的值。
IPC_SET:如果進程有足夠的許可權,就把消息列隊的當前關聯值設置為msgid_ds結構中給出的值
IPC_RMID:刪除消息隊列
buf是指向msgid_ds結構的指針,它指向消息隊列模式和訪問許可權的結構。msgid_ds結構至少包括以下成員:
struct msgid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};
成功時返回0,失敗時返回-1.
三、使用消息隊列進行進程間通信
馬不停蹄,介紹完消息隊列的定義和可使用的介面之後,我們來看看它是怎麼讓進程進行通信的。由於可以讓不相關的進程進行行通信,所以我們在這里將會編寫兩個程序,msgreceive和msgsned來表示接收和發送信息。根據正常的情況,我們允許兩個程序都可以創建消息,但只有接收者在接收完最後一個消息之後,它才把它刪除。
接收信息的程序源文件為msgreceive.c的源代碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
struct msg_st
{
long int msg_type;
char text[BUFSIZ];
};
int main()
{
int running = 1;
int msgid = -1;
struct msg_st data;
long int msgtype = 0; //注意1
//建立消息隊列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//從隊列中獲取消息,直到遇到end消息為止
while(running)
{
if(msgrcv(msgid, (void*)&data, BUFSIZ, msgtype, 0) == -1)
{
fprintf(stderr, "msgrcv failed with errno: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("You wrote: %s\n",data.text);
//遇到end結束
if(strncmp(data.text, "end", 3) == 0)
running = 0;
}
//刪除消息隊列
if(msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl(IPC_RMID) failed\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
發送信息的程序的源文件msgsend.c的源代碼為:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
#define MAX_TEXT 512
struct msg_st
{
long int msg_type;
char text[MAX_TEXT];
};
int main()
{
int running = 1;
struct msg_st data;
char buffer[BUFSIZ];
int msgid = -1;
//建立消息隊列
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed with error: %d\n", errno);
exit(EXIT_FAILURE);
}
//向消息隊列中寫消息,直到寫入end
while(running)
{
//輸入數據
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
data.msg_type = 1; //注意2
strcpy(data.text, buffer);
//向隊列發送數據
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed\n");
exit(EXIT_FAILURE);
}
//輸入end結束輸入
if(strncmp(buffer, "end", 3) == 0)
running = 0;
sleep(1);
}
exit(EXIT_SUCCESS);
}
轉載僅供參考,版權屬於原作者。祝你愉快,滿意請採納哦