POSIX共享内存

1. 创建/获取一个共享内存

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

参数:

   name:  共享内存名字;

   oflag: 与open函数类型, 可以是O_RDONLY, O_WRONLY, O_RDWR, 还可以按位或上O_CREAT, O_EXCL, O_TRUNC.

   mode: 此参数总是需要设置, 如果oflag没有指定O_CREAT, 则mode可以设置为0;

返回值:

   成功: 返回一个文件描述符;

   失败: 返回-1;

注意-Posix IPC名字限制:

   1. 必须以”/”开头, 并且后面不能还有”/”, 形如:/file-name;

   2. 名字长度不能超过NAME_MAX

   3. 链接时:Link with -lrt.

 

 

2. 修改共享内存大小

int ftruncate(int fd, off_t length);

该函数不仅可用于修改共享内存大小, 而且可以用于修改文件大小

参数:

    fd:文件描述符

    length:长度

返回值: 

成功返回0,失败返回-1

 

3. 获取共享内存状态

int fstat(int fd, struct stat *buf);

参数:

    fd: 文件描述符

    buf: 返回共享内存状态

返回值: 

成功返回0,失败返回-1 

该函数不仅可用于获取共享内存状态, 而且可以用于获取文件状态, 与前面曾经讲述过的stat, lstat类型,这两个需要指定文件的路径

//stat结构体
struct stat
{
    dev_t     st_dev;     /* ID of device containing file */
    ino_t     st_ino;     /* inode number */
    mode_t    st_mode;    /* protection */
    nlink_t   st_nlink;   /* number of hard links */
    uid_t     st_uid;     /* user ID of owner */
    gid_t     st_gid;     /* group ID of owner */
    dev_t     st_rdev;    /* device ID (if special file) */
    off_t     st_size;    /* total size, in bytes */
    blksize_t st_blksize; /* blocksize for filesystem I/O */
    blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
    time_t    st_atime;   /* time of last access */
    time_t    st_mtime;   /* time of last modification */
    time_t    st_ctime;   /* time of last status change */
};

 

4. 删除一个共享内存对象

int shm_unlink(const char *name);

参数:

    name:共享内存对象的名字

返回值:

    成功返回0,失败返回-1

 

例一:

#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
 
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
 
typedef struct stu
{
	char name[32];
	int age;
}STU;
 
int main(void)
{
	int shmid;
	shmid=shm_open("/xyz",O_CREAT | O_RDWR,0666);
	if(shmid==-1)
		ERR_EXIT("shm_open");
 
	printf("shm_open succ\n");
	//修改共享内存大小
	if(ftruncate(shmid,sizeof(STU))==-1)
		ERR_EXIT("ftruncate");
 
	struct stat buf;
	//获取共享内存对象信息
	if(fstat(shmid,&buf)==-1)
		ERR_EXIT("fstat");
 
	//共享内存的状态信息
	//共享内存的大小和权限
	printf("size=%ld mode=%o\n",buf.st_size,buf.st_mode & 07777);
	//和文件的关闭方式一样
	close(shmid);
	return 0;
}

[附]:共享内存自动挂载在/dev/shm

   -Posix共享内存默认创建在/dev/shm目录下

   -可以使用od命令查看共享内存的内容

od -c /dev/shm/xyz

 

5. 共享内存的映射/卸载

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);

参数:

   addr:  要映射的起始地址, 通常指定为NULL, 让内核自动选择;

   length: 映射到进程地址空间的字节数, 通常是先前已经创建的共享内存的大小;

   prot: 映射区保护方式(见下);

   flags: 标志(通常指定为MAP_SHARED, 用于进程间通信);

   fd: 文件描述符(填为shm_open返回的共享内存ID);

   offset: 从文件头开始的偏移量(一般填为0);

mmap返回值:

   成功: 返回映射到的内存区的起始地址;

   失败: 返回-1;

prot

说明

PROT_READ

页面可读

PROT_WRITE

页面可写

PROC_EXEC

页面可执行

PROC_NONE

页面不可访问

 

flags

说明

MAP_SHARED

变动是共享的

MAP_PRIVATE

变动是私有的

MAP_FIXED

准确解释addr参数, 如果不指定该参数, 则会以4K大小的内存进行对齐

MAP_ANONYMOUS

建立匿名映射区, 不涉及文件

 

应用代码

往共享内存写数据

#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
 
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
 
typedef struct stu
{
	char name[32];
	int age;
}STU;
 
int main(void)
{
	int shmid;
	shmid=shm_open("/xyz",O_RDWR,0666);
	if(shmid==-1)
		ERR_EXIT("shm_open");
 
	printf("shm_open succ");
	struct stat buf;
	if(fstat(shmid,&buf)==-1)
		ERR_EXIT("fstat");
 
	//共享内存的状态信息
	//共享内存的大小和权限
	printf("size=%ld mode=%o\n",buf.st_size,buf.st_mode & 07777);
 
	//将共享内存映射到进程的地址空间
	STU *p;
	p=mmap(NULL,buf.st_size,PROT_WRITE,MAP_SHARED,shmid,0);
	if(p==MAP_FAILED)
		ERR_EXIT("mmap");
	//往共享内存中写入一些数据
	strcpy(p->name,"test");
	p->age=20;
	
	//和文件的关闭方式一样
	close(shmid);
	return 0;
}

 

读共享内存中的数据

#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/stat.h>
 
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        }while(0)
 
typedef struct stu
{
	char name[32];
	int age;
}STU;
 
int main(void)
{
	int shmid;
	shmid=shm_open("/xyz",O_RDONLY,0666);
	if(shmid==-1)
		ERR_EXIT("shm_open");
 
	printf("shm_open succ");
	struct stat buf;
	if(fstat(shmid,&buf)==-1)
		ERR_EXIT("fstat");
 
	//共享内存的状态信息
	//共享内存的大小和权限
	printf("size=%ld mode=%o\n",buf.st_size,buf.st_mode & 07777);
 
	//将共享内存映射到进程的地址空间
	STU *p;
	p=mmap(NULL,buf.st_size,PROT_READ,MAP_SHARED,shmid,0);
	if(p==MAP_FAILED)
		ERR_EXIT("mmap");
 
	printf("name=%s age=%d\n",p->name,p->age);	
	//和文件的关闭方式一样
	close(shmid);
	return 0;
}
 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值