Linux高级 2019-5-12下午

1.mmap内存共享映射

1.1 消息队列分为两种

  • 1.SYSTEMV
    1. POSIX

1.2 主要功能

  • 通过文件进行进程间通信

1.3 文件是该技术的主要载体,利用对文件的映射与SYNC同步技术实现

1.4 映射条件

  • 文件大小绝对不能为0

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);

	// 内存共享映射 mmap
	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);

	// 因为新创建的文件大小为0,因此需要将文件扩容
	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 ftok() 函数
	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 注意事项

  • 消息队列若不关闭,则会一直存在到系统关闭;
  • 管道和内存共享映射只持续到进程结束;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值