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