IPC: 共享内存

###################################################

共享内存区

 

共享内存是IPC形式中最快的,因为共享内存不和内核进行数据交换。

通过fork派生的子进程不与父进程共享内存区。

 

共享内存区分为:

1.posix共享内存区

2.system V共享内存区

共享内存有两种形式:

1.匿名共享内存

2.有名共享内存

-----------------------------------------------------------

posix共享内存区:

gcc -lrt

-----------------------

系统调用

#include <sys/mman.h>

内存映射文件:就是硬盘中的文件或posix的共享内存区对象。

内存映射区:就是进程的地址空间,也就是内存中的内容。

void *mmap(void *addr, size_t length, int prot, intflags, int fd, off_t offset)

mmap把一个文件或posix共享内存区对象映射到调用进程的的地址空间;

成功返回该地址空间的起始地址,失败返回MAP_FAILED。

addr:内存映射区的起始地址,一般为NULL,让进程自己选择地址。

length:映射到进程地址空间的字节数。

offset:从内存映射文件的什么地方开始映射,一般是0.

fd就是内存映射文件:

1.用open打开文件

2.用shm_open打开文件

3.特殊参数=-1

prot:对内存映射区的保护,不能超过文件的打开权限。

PROT_READ:映射区可读

PROT_WRITE:映射区可写

PROT_EXEC:映射区可执行

PROT_NONE:映射区数据不可访问

flags:被映射的数据的标识,共享和私有必须指定一个。

MAP_SHARED:变动是共享的,除了修改的进程之外的其它进程也可见。

MAP_PRIVATE:变动是私有的,只有修改的进程可见。

MAP_ANONYMOUS:不用创建文件,fd=-1,offset=0,需MAP_SHARED

用mmap将硬盘文件映射到进程空间,不创建文件的两种方法:

1.用MAP_ANONYMOUS参数,fd=-1即可

2.使用/dev/zero作为文件,用open打开/dev/zero,返回fd

int munmap(void *addr, size_t length);

从进程的地址空间删除映射关系。

addr:由mmap返回的地址;

len:映射区的大小。

int mprotect(void *addr, size_t len, int prot);

更改现有内存映射区的权限,成功返回0,失败返回-1.

addr和len要和页边界对齐。

int msync(void *addr, size_t length, int flags);

如果存储映射区内容修改了,使用该函数将内容同步到内存映射文件中,成功返回0,失败返回-1.

如果映射是私有的就不修改文件。

addr和length要和页边界对齐。

flags:指定同步标识,同步和异步必须且只能指定一个。

MS_ASYNC:执行异步写

MS_SYNC:执行同步写

MS_INVALIDATE:使高速缓存的数据失效

-----------

#include<unistd.h>

#include <sys/types.h>

int ftruncate(int fd, off_t length);

用来截取内存映射文件或共享内存区的大小。

#include<unistd.h>

#include<sys/stat.h>

#include<sys/types.h>

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

获取内存映射文件的信息。

当fd为一个共享内存区对象时,只有下列四个参数有意义:

struct stat {

mode_t st_mode;

uid_t st_uid;

gid_t st_gid;

off_t st_size; // 文件大小

};

-----------------------

库函数

#include <sys/mman.h>

#include <sys/stat.h>

#include <fcntl.h>

int shm_open(const char *name, int oflag, mode_t mode);

oflag不能指定O_WRONLY参数,且mode参数必须指定。

效果和open函数差不多,返回一个描述符fd作为mmap的fd参数。

int shm_unlink(const char *name);

删除一个共享内存区对象的名字。

-----------------------------------------------------------

system v共享内存区:

#include <sys/ipc.h>

#include <sys/shm.h>

#include <sys/types.h>

内核维护一个共享内存结构:

struct shmid_ds {

struct ipc_permshm_perm;

size_t shm_segsz;//共享内存大小

pid_t shm_lpid;//最后一个操作的pid

pid_t shm_cpid;//创建者的pid

shmatt_t shm_nattch;

shmat_t shm_cnattch;

time_t shm_atime;

time_t shm_dtime;

time_t shm_ctime;

};

int shmget(key_t key, size_tsize, int shmflg);

创建一个新的共享内存区,或者访问一个已经存在的共享内存区。返回共享内存区标识符。

key:既可以是ftok的返回值,也可以是IPC_PRIVATE.

size:以字节为单位,指定内存区的大小,如果是已存在的共享内存区,为0.

shmflg:

shmflg: 可以用读写权限 或 其它可选权限。

属主:SHM_R        SHM_A

属组:SHM_R >> 3   SHM_A >> 3

其它:SHM_R >> 6   SHM_A >> 6

IPC_CREAT:不存在就创建,存在就返回已存在的。

IPC_CREAT | IPC_EXCL:不存在就创建,存在就返回错误。

void *shmat(int shmid, constvoid *shmaddr, int shmflg);

把已经创建的共享内存区映射到调用进程的地址空间,返回起始地址。

shmaddr:一般为NULL,让系统自己选择地址。

shmflg:一般为0.

SHM_RND:如果shmaddr不为空,映射到shmaddr指定的地址向下舍入SHMLBA个值的地方,如果没有这个标识就映射到shmaddr指定的地方。

SHM_RDONLY:只读访问

int shmdt(const void *shmaddr);

断开已存在的共享内存区和进程的地址空间的映射关系。

int shmctl(int shmid, int cmd,struct shmid_ds *buf);

对共享内存区的操作。

cmd:

IPC_STAT:获取共享内存段的值

IPC_SET:设置共享内存段的值

IPC_RMID:删除共享内存段

IPC_INFO

SHM_INFO

SHM_STAT

SHM_LOCK

SHM_UNLOCK

###################################################

时间: 2024-10-20 10:03:48

IPC: 共享内存的相关文章

Linux IPC 共享内存用法

Linux IPC 常见的方式 写 Linux Server 端程序,必然会涉及到进程间通信 IPC. 通信必然伴随着同步机制,下面是一些常见的通信与同步机制: 进程间通信:匿名管道,命名管道,消息队列,共享内存,Domain Socket, 本机 TCP Socket,文件 进程间同步:信号,信号量 线程间同步:条件变量,互斥量,读写锁,自旋锁,Barrier. 对于大部分的业务场景,本机 TCP Socket 足以,现在Linux 也对本机 TCP Socket做了很好的优化.而且如果以后需

进程-IPC 共享内存和消息队列 (三)

详见:https://github.com/ZhangzheBJUT/linux/blob/master/IPC(%E4%B8%89).md 五 共享内存 5.1. 共享内存简介 共享内存指多个进程共享同一块物理内存,它只能用于同一台机器上的两个进程之间的通信.在进程的逻辑地址空间中有一段地址范围是用来进行内存映射使用的,该段逻辑地址空间可以映射到共享的物理内存地址上(进程空间介绍:http://blog.csdn.net/zhangzhebjut/article/details/3906025

35 守护进程 互斥锁 IPC 共享内存 的方式 生产者消费者模型

守护进程 进程:一个正在运行的程序. 主进程创建守护进程: 1.守护进程会在主进程代码执行结束后就终止, 2.守护进程内无法再开启子进程,否则抛出异常. 注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即终止. 例子:from multiprocessing import Processimport time def task(): print('老了....') time.sleep(2) print('睡了一会..') if __name__ == '__main__': prin

IPC——共享内存

Linux进程间通信——使用共享内存 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段

(转载)linux下的僵尸进程处理SIGCHLD信号Linux环境进程间通信(五): 共享内存(下)

Linux环境进程间通信(五): 共享内存(下) 在共享内存(上)中,主要围绕着系统调用mmap()进行讨论的,本部分将讨论系统V共享内存,并通过实验结果对比来阐述两者的异同.系统V共享内存指的是把所有共享数据放在共享内存区域(IPC shared memory region),任何想要访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面. 系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内

进程间通信(8) - 共享内存(posix)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.共享内存介绍 前面所讲述的Linux下面的各种进程间通信方式,例如:pipe(管道),FIFO(命名管道),message queue(消息队列),它们的共同点都是通过内核来进行通信(假设posix消息队列也是在内核中实现的,因为posix标准没有规定它的具体实现方式).向pipe,fifo,message queue写入数据时,需要把数据从用户空间(用户进程)复制到

共享内存基础

shmget int shmget(key_t key, size_t size, int flag); key: 标识符的规则 size:共享存储段的字节数 flag:读写的权限 返回值:成功返回共享存储的id,失败返回-1 key_t key-----------------------------------------------    key标识共享内存的键值: 0/IPC_PRIVATE. 当key的取值为IPC_PRIVATE,则函数shmget()将创建一块新的共享内存:如果ke

深入理解进程间通信之共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.是针对其他通信机制运行效率较低而设计的.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共

(转)Linux环境进程间通信系列(五):共享内存

原文地址:http://www.cppblog.com/mydriverc/articles/29741.html 共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式.两个不同进程 A . B 共享内存的意思是,同一块物理内存被映射到进程 A . B 各自的进程地址空间.进程 A 可以即时看到进程 B 对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存

Linux环境进程间通信:共享内存

共享内存简介 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC.共享内存的方式有两种:mmap()系统调用和系统V共享内存. mmap()系统调用 mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存.普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作. 注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的.它本身提供了不同于一般对普