常见的IPC:
1 文件
2 信号
3 管道
4 共享内存
5 消息队列
6 信号量集(semaphore arrays)
7 网络编程(socket编程)
....
其中,共享内存/消息队列和信号量集 遵循相同的规范,在编程上有很多相似之处,统称为XSI IPC。
多个进程同时写数据的时候采用消息队列。
共同点:
1.XSI IPC都是系统内核管理的,叫内核结构。
2.XSI IPC都由外部的key ,类型是key_t,可以定位IPC结构。
3.1 宏IPC_PRIVATE 做key,这种方式程序员基本上不用,因能建IPC结构,但外部不能获取
3.2 定义一个共同体的头文件,所有的key存在头文件中,(key的赋值需要单独定义一个.c文件)
3.3 使用函数 ftok() 生成key.ftok()以文件作为参数,这个文件/目录是必须存在的
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);
}
}
}