导航:首页 > 操作系统 > linux消息队列个数

linux消息队列个数

发布时间:2023-03-15 16:52:42

‘壹’ 请教一个关于linux消息队列的问题

一般使用步骤:

1. 用ftok产生一个key。

2. 调用msgget(使用key作为参数)产生一个队列

3. 进程可以用msgsnd发送消息到这个队列,相应的别的进程用msgrcv读取。

这里需要注意msgsnd可能会失败的两个情况:

a) 可能被中断打断(包括msgsnd和msgrcv). 尤其是大流量应用中更容易出现. 比较安全的用法是判断操作是否被中断打断,如果被打断, 则需要继续尝试。

b) 消息队列满。产生这个错误,则需要考虑提高系统消息队列规格,或者查看消息接收处是否有问题

4. msgctl函数可以用来删除消息队列
消息队列产生之后,除非明确的删除(可以用),产生的队列会一直保留在系统中。linux下消息队列的个数是有限的,注意不要泄露。如果 使用已经达到上限,msgget调用会失败,产生的错误码对应的提示信息为no space left on device.

注意点:

1.消息的类型 mtype 不需为非0值。如果使用0,则msgsnd会失败,并得到”Invalid argument“错误。

2.msgflg为0表示阻塞等待,如果msgflg为IPC_NOWAIT表示非阻塞。

3.最好使用root权限执行消息队列,否则msgrcv 提示 "Permission denied"。

‘贰’ 如何在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_

‘叁’ Linux多线程同步之消息队列有何特点

消息队列是消息的链表,存放在内核中并有消息队列标示符标示。
msgget用于创建一个新队列或打开一个现存的队列。msgsnd将新消息加入到消息队列中;每个
消息包括一个long型的type;和消息缓存;msgrcv用于从队列中取出消息;取消息很智能,不一定先进先出
①msgget,创建一个新队列或打开一个现有队列
#include
int msgget ( key_t key, int flag );
//成功返回消息队列ID;错误返回-1
②msgsnd: 发送消息
#include
int msgsnd( int msgid, const void* ptr, size_t nbytes, int flag )
//成功返回0,错误返回-1
a:
flag可以指定为IPC_NOWAIT;
若消息队列已满,则msgsnd立即出错返回EABAIN;
若没指定IPC_NOWAIT; msgsnd会阻塞,直到消息队列有空间为止
③msgrcv: 读取消息:
ssize_t msgrcv( int msgid, void* ptr, size_t nbytes, long type, int flag );
a. type == 0; 返回消息队列中第一个消息,先进先出
b. type > 0
返回消息队列中类型为tpye的第一个消息
c. type < 0
返回消息队列中类型 <=
|type| 的数据;若这种消息有若干个,则取类型值最小的消息
消息队列创建步骤:
#define
MSG_FILE "."
struct msgtype {
long mtype;
char buffer[BUFFER+1];
};
if((key=ftok(MSG_FILE,'a'))==-1)
{
fprintf(stderr,"Creat Key Error:%s\n", strerror(errno));
exit
(1);
}
if((msgid=msgget(key, IPC_CREAT | 0666/*PERM*/))==-1)
{
fprintf(stderr,"Creat Message
Error:%s\n", strerror(errno));
exit
(1);
}

‘肆’ Linux系统编程—消息队列

消息队列本质上是位于内核空间的链表,链表的每个节点都是一条消息。每一条消息都有自己的消息类型,消息类型用整数来表示,而且必须大于 0。每种类型的消息都被对应的链表所维护:

其中数字 1 表示类型为 1 的消息,数字2、3、4 类似。彩色块表示消息数据,它们被挂在对应类型的链表上。

值得注意的是,刚刚说过没有消息类型为 0 的消息,实际上,消息类型为 0 的链表记录了所有消息加入队列的顺序,其中红色箭头表示消息加入的顺序。

无论你是发送还是接收消息,消息的格式都必须按照规范来。简单的说,它一般长成下面这个样子:

所以,只要你保证首4字节(32 位 linux 下的 long)是一个整数就行了。
举个例子:

从上面可以看出,正文部分是什么数据类型都没关系,因为消息队列传递的是 2 进制数据,不一定非得是文本。

msgsnd 函数用于将数据发送到消息队列。如果该函数被信号打断,会设置 errno 为 EINTR。

参数 msqid:ipc 内核对象 id
参数 msgp:消息数据地址
参数 msgsz:消息正文部分的大小(不包含消息类型)
参数 msgflg:可选项
该值为 0:如果消息队列空间不够,msgsnd 会阻塞。
IPC_NOWAIT:直接返回,如果空间不够,会设置 errno 为 EAGIN.

返回值:0 表示成功,-1 失败并设置 errno。

msgrcv 函数从消息队列取出消息后,并将其从消息队列里删除。

参数 msqid:ipc 内核对象 id
参数 msgp:用来接收消息数据地址
参数 msgsz:消息正文部分的大小(不包含消息类型)
参数 msgtyp:指定获取哪种类型的消息

msgtyp = 0:获取消息队列中的第一条消息
msgtyp > 0:获取类型为 msgtyp 的第一条消息,除非指定了 msgflg 为MSG_EXCEPT,这表示获取除了 msgtyp 类型以外的第一条消息。
msgtyp < 0:获取类型 ≤|msgtyp|≤|msgtyp| 的第一条消息。
参数 msgflg:可选项。
如果为 0 表示没有消息就阻塞。
IPC_NOWAIT:如果指定类型的消息不存在就立即返回,同时设置 errno 为 ENOMSG
MSG_EXCEPT:仅用于 msgtyp > 0 的情况。表示获取类型不为 msgtyp 的消息
MSG_NOERROR:如果消息数据正文内容大于 msgsz,就将消息数据截断为 msgsz

程序 msg_send 和 msg_recv 分别用于向消息队列发送数据和接收数据。

msg_send 程序定义了一个结构体 Msg,消息正文部分是结构体 Person。该程序向消息队列发送了 10 条消息。
msg_send.c

程序 msg_send 第一次运行完后,内核中的消息队列大概像下面这样:

msg_recv 程序接收一个参数,表示接收哪种类型的消息。比如./msg_recv 4 表示接收类型为 4 的消息,并打印在屏幕。

先运行 msg_send,再运行 msg_recv。
接收所有消息

接收类型为 4 的消息

获取和设置消息队列的属性

msqid:消息队列标识符
cmd:控制指令
IPC_STAT:获得msgid的消息队列头数据到buf中
IPC_SET:设置消息队列的属性,要设置的属性需先存储在buf中,可设置的属性包括:msg_perm.uid、msg_perm.gid、msg_perm.mode以及msg_qbytes
buf:消息队列管理结构体。

返回值:
成功:0
出错:-1,错误原因存于error中
EACCESS:参数cmd为IPC_STAT,确无权限读取该消息队列
EFAULT:参数buf指向无效的内存地址
EIDRM:标识符为msqid的消息队列已被删除
EINVAL:无效的参数cmd或msqid
EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

‘伍’ 请教一个关于linux进程通信消息队列mq

在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.

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.

‘陆’ linux编程的利用消息队列在两个进程间通信,怎么写代码,求思路,需要建立几个消息队列呢

首先建议你先参考 《advanced programming in the unix environment》 一书中的第15章(Interprocess communication 进程间通信)中的第7节(message queues 消息队列)了解消息队列的相关接口函数,比如如何创建获取消息队列,如何收发消息。然后就很简单了

如果你打算两个进程依次收消息,发消息,就像打乒乓球一样,那么只要一个queue,A 发消息, B 收消息并处理,然后 B 发消息, A 收并处理………… 按此次序进行下去。

更灵活的方法是两个消息队列 (a, b), A 进程从 队列a收消息,向 b 发消息。 B进程从b收消息,想a发消息。

阅读全文

与linux消息队列个数相关的资料

热点内容
微云下载文件夹是空的 浏览:3
r9数控车的编程 浏览:403
为什么删不掉ksafe文件夹 浏览:291
理科男学编程用什么电脑 浏览:839
安阳弹性云服务器 浏览:570
压缩空气储罐有效期 浏览:408
英国文学PDF 浏览:175
软件编程需求 浏览:626
广州哪里解压 浏览:253
手机小视频怎么压缩 浏览:915
微信聊天界面源码 浏览:24
seo竞价推广点击价格算法公式 浏览:319
框架结构可以加密吗 浏览:218
python编译器怎么清除 浏览:73
linux全局socks代理 浏览:611
php微信抽奖 浏览:771
压缩算法嵌入式移植 浏览:531
php新手小例子 浏览:233
按照医生的算法一周是几天 浏览:805
三次b样条曲线算法 浏览:924