linux IPC 通信 study 五:posix共享内存

API介绍

  • shm_open

#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */
int shm_open(const char *name, int oflag, mode_t mode);
函数执行成功返回shm描述符,失败返回-1,errno指示错误信息
功能:创建一个新的share memory或者打开一个已经存在的share memory
参数name,shm标识字符串,形如“/somename”
参数oflag:
    O_RDONLY,只读方式,mmap时只能使用PROT_READ
    O_RDWR,读写方式
    O_CREAT,如果不存在就创建,存在就返回
    O_EXCL,如果存在就报错
    O_TRUNC,如果shm已经存在,将它的大小弄成0
参数mode: 表示访问权限,比如0644

  • ftruncate

int ftruncate(int fd, off_t length);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:设置shm的大小

  • mmap

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
函数执行成功返回进程内地址,失败返回-1,errno指示错误信息
是一个系统调用,将shm和进程内的地址关联起来
参数addr:映射区的起始地址,设置为NULL则由系统决定映射区的起始地址
参数length:映射区的长度,不足一个内存页按一页处理
参数prot:映射区的保护模式,不能和shm_open中的oflag冲突
    PROT_EXEC,页内容可以执行
    PROT_READ,页内容可以被读取
    PROT_WRITE,页内容可以被写入
    PROT_NONE, 页内容不可访问
参数flags:映射区是否可以共享,常设置为MAP_SHARED
参数fd:
    通过shm_open获得
参数offset
    被映射内容的起始点

  • munmap

int munmap(void *addr, size_t length);
函数执行成功返回0,失败返回-1,errno指示错误信息
系统调用

  • close

#include <unistd.h>
int close(int fd);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:关闭share memory

  • shm_unlink

int shm_unlink(const char *name);
函数执行成功返回0,失败返回-1,errno指示错误信息
功能:将shm_name和shm描述符分离


sample code

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#define SHM_PATH "/this_key"

typedef struct {
	int a;
	int b;
	int c;
}INFO;

int server()
{
	int shmfd = 0;
	INFO *info;
	mode_t old_mode;
	old_mode = umask(0);

	shmfd = shm_open(SHM_PATH,
			O_CREAT | O_EXCL | O_RDWR,
			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
	if (shmfd < 0) {
		if (errno == EEXIST) {
			printf("%s\n", strerror(errno));
			shmfd = shm_open(SHM_PATH, O_RDWR,
				S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
		} else {
			return -1;
		}
	}

	umask(old_mode);

	ftruncate(shmfd, sizeof(INFO));

	info = (INFO *)mmap(NULL, sizeof(INFO),
					PROT_READ | PROT_WRITE,
					MAP_SHARED,
					shmfd, 0);
	if (info == NULL) {

		printf("failed to mmap\n");
		goto exit;
		return -2;
	}

	memset(info, 0, sizeof(INFO));
	info->a = 1;
	info->b = 1;
	info->c = 0;
	printf("server set info to shm is %d %d %d\n", info->a, info->b, info->c);

	sleep(10);
	munmap((void *)info, sizeof(INFO));
exit:
	close(shmfd);
	shm_unlink(SHM_PATH);

	return 0;
}

int client()
{
	int shmfd = shm_open(SHM_PATH, O_RDWR, 0666);
	INFO *info;

	ftruncate(shmfd, sizeof(INFO));

	info = (INFO *)mmap(NULL, sizeof(INFO),
					PROT_READ | PROT_WRITE,
					MAP_SHARED,
					shmfd, 0);
	if (info == NULL) {
		printf("failed to mmap\n");
		goto exit;
		return -2;
	}

	printf("\tclient get info from shm is %d %d %d\n", info->a, info->b, info->c);
	munmap((void *)info, sizeof(INFO));
exit:
	close(shmfd);
	return 0;
}

int main(int argc, char **argv)
{
	pid_t pid = fork();
	if (pid == 0) {

		sleep(1);
		client();
	} else if (pid > 0) {
		server();
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值