linux网络编程之POSIX 共享内存和 系列函数
来源:互联网 发布:sql 日志回滚 编辑:程序博客网 时间:2024/05/16 08:04
在前面介绍了system v 共享内存的相关知识,现在来稍微看看posix 共享内存 和系列函数。
共享内存简单来说就是一块真正的物理内存区域,可以使用一些函数将这块区域映射到进程的地址空间进行读写,而posix 共享内存与system v 共享内存不同的是它是用虚拟文件系统(tmpfs)实现的,已经挂载在/dev/shm 下面。man 7 shm_overview
下面来看系列函数,编译时候加上 -lrt 选项,即连接librt 库 (实时库)
功能:用来创建或打开一个共享内存对象
原型 int shm_open(const char *name, int oflag, mode_t mode);
参数
name:共享内存对象的名字,必须以/打头,并且后续不能有其它/ ,形如/somename长度不能超过NAME_MAX(255)
oflag:与open函数类似,可以是O_RDONLY、O_RDWR,还可以按位或上O_CREAT、O_EXCL、O_TRUNC等。
mode:此参数总是需要设置,如果oflag没有指定了O_CREAT,可以指定为0
返回值:成功返回非负整数文件描述符;失败返回-1
注意,不存在所谓的shm_close 函数,可以直接使用close 来关闭文件描述符。
功能:修改共享内存对象大小,shm_open不像shmget一样可以设置共享内存的大小,但可以使用ftruncate 设置大小。
原型 int ftruncate(int fd, off_t length);
参数
fd: 文件描述符
length:长度
返回值:成功返回0;失败返回-1
功能:获取共享内存对象信息
原型
int fstat(int fd, struct stat *buf);
参数
fd: 文件描述符
buf:返回共享内存状态
返回值:成功返回0;失败返回-1
struct stat 可以参考这里。
类似 shmctl(, IPC_STAT,);
功能:删除一个共享内存对象
原型 int shm_unlink(const char *name);
参数
name: 共享内存对象的名字
返回值:成功返回0;失败返回-1
shm_unlink 类似 shmctl(, IPC_RMID, );
功能:将共享内存对象映射到进程地址空间。
原型 void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
参数
addr: 要映射的起始地址,通常指定为NULL,让内核自动选择
len:映射到进程地址空间的字节数
prot:映射区保护方式
flags:标志
fd:文件描述符
offset:从文件头开始的偏移量
返回值:成功返回映射到的内存区的起始地址;失败返回-1
在前面曾经介绍了mmap 函数 将文件映射到进程地址空间的作用,其实它还可以将共享内存对象映射到进程地址空间,类似shmat的作用,只是传入的文件描述符fd 是shm_open 返回的。同样地,解除映射可以用munmap,类似shmdt 的作用。
下面写几个程序来演示一下:
shm_open.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(void)
{
int shmid;
shmid = shm_open("/xyz", O_CREAT | O_RDWR, 0666);
if (shmid == -1)
ERR_EXIT("shm_open");
if (ftruncate(shmid, 36) == -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 & 0777);
close(shmid);
return 0;
}
size=36, mode=664
simba@ubuntu:~/Documents/code/linux_programming/UNP/posix$ ls -l /dev/shm/xyz
-rw-rw-r-- 1 simba simba 36 Jun 16 15:01 /dev/shm/xyz
即创建了一个36字节的共享内存段,在/dev/shm 目录下。
shm_write.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.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, 0);
if (shmid == -1)
ERR_EXIT("shm_open");
struct stat buf;
if (fstat(shmid, &buf) == -1)
ERR_EXIT("fstat");
printf("size=%ld, mode=%o\n", buf.st_size, buf.st_mode & 0777);
STU *p;
p = (STU *)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;
}
size=36, mode=664
simba@ubuntu:~/Documents/code/linux_programming/UNP/posix$ od -c /dev/shm/xyz
0000000 t e s t \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000020 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
0000040 024 \0 \0 \0
0000044
使用mmap 将共享内存映射到进程地址空间,将shmid 传入fd 参数,其余跟文件映射没什么区别,od -c查看可以看到写入的东西。
shm_read.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.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, 0);
if (shmid == -1)
ERR_EXIT("shm_open");
struct stat buf;
if (fstat(shmid, &buf) == -1)
ERR_EXIT("fstat");
printf("size=%ld, mode=%o\n", buf.st_size, buf.st_mode & 0777);
STU *p;
p = (STU *)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;
}
size=36, mode=664
name=test age=20
即读取到了共享内存的数据,注意,读取数据后共享内存的数据还是存在的,除非被覆盖了。
参考:《UNP》
- linux网络编程之POSIX 共享内存和 系列函数
- linux网络编程之POSIX共享内存
- linux网络编程之POSIX 消息队列 和 系列函数
- linux网络编程之System V 共享内存 和 系列函数
- linux网络编程之System V 共享内存 和 系列函数
- linux网络编程之共享内存简介和mmap 函数
- linux网络编程之共享内存简介和mmap 函数
- linux网络编程之posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序
- UNIX网络编程——Posix共享内存区和System V共享内存区
- Linux环境编程之共享内存区(二):Posix共享内存区
- Linux进程通信之POSIX共享内存
- Linux进程通信之POSIX共享内存
- Linux进程通信之POSIX共享内存
- Linux IPC之POSIX共享内存
- UNIX网络编程卷二 笔记 Posix共享内存区
- 《UNIX网络编程 卷2》 笔记: Posix共享内存区
- linux网络编程之POSIX消息队列
- linux网络编程之POSIX条件变量
- HDU 2080 夹角有多大
- 给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数(google题目)
- 20+个创意十足的斜线网站设计
- python包管理工具pip
- VS2012安装后很卡,需要大化小化窗口
- linux网络编程之POSIX 共享内存和 系列函数
- PRJ:Detect a point if it's inside a triangle
- 软工12-13-2 实验报告五——住房贷款计算器最终完成效果及个人心得
- rtmp实现音频频点播之服务篇
- 在 ASP.NET 網頁上加入浮水印
- 思维导图
- 几何中点/线/多边形模板
- C#多线程学习(三) 生产者和消费者
- 详解Windows 8 RP版教程【系统收藏】