1.mmap内存共享映射
1.1 消息队列分为两种
1.2 主要功能
1.3 文件是该技术的主要载体,利用对文件的映射与SYNC同步技术实现
1.4 映射条件
1.5 共享映射过程
- 1.进程A申请映射内存,映射内存通过同步技术(SYNC)映射到映射文件中;则映射内存中的数据就会保存到映射文件中;
- 2.进程B申请映射内存,映射内存通过同步技术(SYNC)映射到映射文件中;则可能会覆盖进程A映射的映射文件,因为两者公用同一块映射文件;
1.6 使用同步技术让映射内存与映射文件内容实时保持一致,但这会消耗较多的资源
1.7 映射分为两种
- 1.私有映射:映射成功后,文件与内存无关,内容相互独立;
- 2.共享映射:具备SYNC同步技术,文件与内存内容实时保持一致;
1.8 同步技术实现映射内存
- 1.mmap 函数的参数
- 第一个参数:一般传 NULL ,意思是指在 NULL 地址附近找一块空间分配给映射内存;
- 第二个参数:映射文件的大小;
- 第三个参数:文件的权限;
- 第四个参数:映射的类型(私有还是共享);
- 第五个参数:文件描述符;
- 第六个参数:偏移量的大小;
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/mman.h>
int main()
{
int fd;
fd = open("mmap01", O_WRONLY|O_CREAT, 0664);
int size = lseek(fd, 0, SEEK_END);
int* p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
p[0] = 0x34333231;
munmap(p, size);
return 0;
}
1.9 利用 mmap 发送实时信息
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct
{
char name[10];
char sex[10];
}msg_t;
int main()
{
int fd;
int size = sizeof(msg_t);
int flags = 0;
msg_t* msg;
fd = open("mmap01", O_RDWR|O_CREAT, 0664);
ftruncate(fd, size);
msg = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
while(1)
{
bzero(msg->name, sizeof(msg->name));
bzero(msg->sex, sizeof(msg->sex));
sprintf(msg->name, "SLAM:%d", ++flags);
if(flags % 2 == 0)
{
sprintf(msg->sex, "%s", male");
}
else
sprintf(msg->sex, "%s", "female");
sleep(1);
}
munmap(msg, size);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
typedef struct
{
char name[10];
char sex[10];
}msg_t;
int main()
{
int fd;
fd = open("mmap01", O_RDONLY);
int size = sizeof(msg_t);
msg_t* msg;
msg = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
while(1)
{
printf("NAME:%s\tSEX:%s\n", msg->name, msg->sex);
sleep(1);
}
munmap(msg, size);
return 0;
}
1.10 mmap 允许每次映射文件的一部分(最后一个参数偏移量的用处),对数据进行分段映射,这样就能够处理大数据文件(也是常用的手段)
1.11 注意事项
- 为了避免用户越权操作映射文件,映射时的权限受打开文件权限限制,即使身份为root
2.SYSTEM V 消息队列
2.1 概念
2.2 常用函数
- msgget() :创建或打开一个消息队列
- msgsnd() :向消息队列中发送一条消息
- msgrcv() :从消息队列读一条消息
- msgctl() :修改消息队列属性或删除消息队列
2.3 消息队列的常用属性
- _MAX :消息数量
- _SIZE :消息的长度
- _CUR :当前消息数量
2.4 尝试代码
- 1.在终端中使用 ipcs -q 命令查看当前系统中存在的所有消息队列
- 2.在终端中使用 ipcrm -q 队列id 命令来删除存在的消息队列
- 3.msgrcv 函数中的 msgtype 参数的含义
- msgtype > 0 表示读取指定类型的任意一条消息
- msgtype = 0 表示读取任意类型的第一条消息
- msgtype < -1 表示读取小于绝对值的任意一条消息
- 写端
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define MSG "Hello SLAM"
int main()
{
key_t key;
int msg_id;
key = ftok(".", 'a');
msg_id = msgget(key, IPC_CREAT|0664);
msgsnd(msgid, MSG, strlen(MSG), 0);
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
int main()
{
key_t key;
int msg_id;
char buf[1024];
bzero(buf, sizeof(buf));
key = ftok(".", 'a');
msg_id = msgget(key, IPC_EXCL);
int len = msgrcv(msg_id, buf, sizeof(buf), 0, 0);
printf("RECV DATA:%s\n", buf);
return 0;
}
2.5 注意事项
- 消息队列若不关闭,则会一直存在到系统关闭;
- 管道和内存共享映射只持续到进程结束;