消息队列一

进程之间不能通过内存直接互访,但进程之间有时候需要数据交互,因此进程间通信就非常的重要。Linux系统以多进程为核心的操作系统,因此进程间通信在Linux系统中频繁的被使用。
   常见的IPC:
    1 文件
    2 信号
    3 管道
    4 共享内存
    5 消息队列
    6 信号量集(semaphore arrays)
    7 网络编程(socket编程)
    ....
  其中,共享内存/消息队列和信号量集 遵循相同的规范,在编程上有很多相似之处,统称为XSI IPC。
 多个进程同时写数据的时候采用消息队列。





共同点:
1.XSI IPC都是系统内核管理的,叫内核结构。

2.XSI IPC都由外部的key ,类型是key_t,可以定位IPC结构。


3.外部key的获取方式有三种:
3.1 宏IPC_PRIVATE 做key,这种方式程序员基本上不用,因能建IPC结构,但外部不能获取
3.2 定义一个共同体的头文件,所有的key存在头文件中,(key的赋值需要单独定义一个.c文件)

3.3 使用函数 ftok() 生成key.ftok()以文件作为参数,这个文件/目录是必须存在的


4 在内核中的IPC结构都有一个ID代表,这个ID可以用函数获取,这个函数叫:xxxget(key,……) 比如:shmget(key,……)   msgget(key,……)
5创建IPC结构的函数也是 xxxget(),其中的flag需要写成:IPC_CREAT|0666(权限)
6在代码中,用ID代表IPC结构,就像fd代表一个打开的文件一样。
7每种IPC结构都提供了一个xxxctl()函数,可以实现对IPC结构的查询/修改和删除,比如:shmctl()  msgctl()  
其中,会有一个cmd参数,至少包括三个值:
IPC_STAT -查询
IPC_SET  -修改
IPC_RMID  -删除


8.系统提供了一套命令查看/删除IPC结构
ipcs -查看IPC结构
ipcs -a 查看所有IPC结构,包括3个
ipcs -m 查看共享内存
ipcs -q 查看队列
ipcs -s 查看信号量集


ipcrm -删除IPC结构,按ID 删除
ipcrm -m ID删除共享内存
ipcrm -q ID 删除消息队列
ipcrm -s ID删除信号量集


共享内存(shared memory)

消息队列 -队列是种数据结构,按次序存放元素,先入先出
队列中的元素就是消息。
消息队列的使用方式就是先把数据放入消息中,然后把消息放入队列中。队列的管理由内核完成。


消息队列就是以内核管理的一个队列作为交互的媒介。比较常用的IPC。


(重点):


消息队列的使用步骤:


 1.使用ftok()或共用的头文件提供一个key;


 2.使用msgget(key,……)创建/获取一个消息队列

 3.使用msgsnd()发送消息(把消息放入队列中)或使用msgrcv()取出消息(把消息从队列中取出)

   

4.如果确保不再使用消息队列,可以使用msgctl(IPC_RMID)删除



消息分为 有类型和无类型消息,无类型消息可以支持任意类型的数据,但只能先入先出,如果放入的顺序和取出的次序不同,一定会出问题,更多的时候使用有类型小型。



有类型消息必须是一个结构体,
struct 名称{//名称  程序员随便起,合法标识符就行
long mtype;//第一个必须long,代表消息类型
    数组或结构;//数据区,数据放在这里
}
其中,mtype必须大于0.

int msgsnd(int msgid,void* msgp,size_t msgsz,int flags)
功能:发送消息到消息队列的末尾。
参数:msgid就是消息队列的ID
msgp 就是消息结构体的首地址
msgsz 就是消息结构体中数据的大小(不带类型玩)
flags取0 或IPC_NOWAIT 0就是满了会等,IPC_NOWAIT满了就直接返回-1
返回 :成功返回0,失败返回-1
ssize_t msgrcv(int msgid,void* msgp,size_t msgsz.long msgtype,int flags)
功能:按类型接受
参数:msgid/msgp/msgsz/flags和msgsnd一样
msgtype  可以取三种值
>0  就是接受特定类型的消息(类型=msgtype)
0  就是接受任意类型的消息(先入先出)
<0  就是接受类型小于等于|msgtype|的消息,从小到大顺序:比如:msgtype传了-3   ,接受消息的类型为1 2 3
返回:失败返回-1,成功返回实际接受的字节数。



编程案例:

//msgsend.c

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>


struct msg{
long mtype;
char name[20];
};
int main(){
key_t key=ftok(".",100);
int msgid=msgget(key,IPC_CREAT|0666);
if(msgid==-1){
perror("msgget");
exit(-1);
}
struct msg msg1,msg2;
msg1.mtype=1;
strcpy(msg1.name,"zhangfei");
msg2.mtype=2;
strcpy(msg2.name,"guanyu");
msgsnd(msgid,&msg1,sizeof(msg1.name),0);
msgsnd(msgid,&msg2,sizeof(msg2.name),0);
}


// msgrcv.c


#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>


struct msg{
long mtype;
char name[20];
};
int main(){
key_t key=ftok(".",100);
int msgid=msgget(key,0);
if(msgid==-1){
perror("msgget");
exit(-1);
}
struct msg msg1;
int res=msgrcv(msgid,&msg1,sizeof(msg1.name),1,0);
if(res==-1){
perror("msgrcv");
}
else{
printf("%s\n",msg1.name);
}
}


编程案例二:自发自收


#include"stdio.h"
#include"stdlib.h"
#include"sys/ipc.h"
#include"sys/msg.h"
#include"string.h"


typedef struct{
        long mtype;
        char name[20];
}msg;


void main(){
        key_t key=ftok(".",10);
        int msgid=msgget(key,IPC_CREAT|0666);
        if(msgid==-1){
                perror("msgget");
                exit(-1);
        }
        msg msg1,msg2;
        msg1.mtype=1;
        while(1){
        printf("Enter something \n");
        //scanf("%s",msg1.name);
        gets(msg1.name);
        msgsnd(msgid,&msg1,sizeof(msg1.name),0);
        }
}


#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"sys/ipc.h"
#include"sys/msg.h"


typedef struct{
        long mytype;
        char name[20];
}msg;


void main(){
        key_t key=ftok(".",10);
        int msgid=msgget(key,0);
        if(msgid==-1){
                perror("msgget");
                exit(-1);
        }
        msg msg1,msg2;
        while(1){
        int res=msgrcv(msgid,&msg1,sizeof(msg1.name),1,0);
        if(res==-1){
                perror("msgrcv");
        }
        else{
                printf("I recv: %s\n",msg1.name);
        }
        }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零一2035

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值