进程的是独立的,每个进程有自己的地址空间,通过页表映射到物理内存上。共享内存就是在物理内存上开辟一段内存空间,然后分别与多个不相干的进程,通过页表关联起来。关联的过程就是每个进程都开辟一段自己的虚拟地址空间 并通过页表 与共享内存一一对应。如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
(1) 创建或打开共享内存
int shmget (key_t key, size_t size, int shmflg);
参数: key 程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget()函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1. 不相关的进程可以通过key访问同一共享内存,程序先通过调用shmget()函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget()函数的返回值),只有shmget()函数才直接使用key,所有其他的共享内存函数使用由semget函数返回的共享内存标识符,就像文件标识符一样。 size 只有在key共享内存不在时,创建共享内存时生效,表示创建的共享内存大小。 shmflg 权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。 返回值: 共享内存标识符。
(2)共享内存连接
void *shmat(int shm_id, const void *shm_addr, int shmflg);
第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是把共享内存连接到当前进程的地址空间。 参数: shm_id : 就是shmget返回的共享内存描述符。 shm_addr: 指定共享内存连接到当前进程中的地址位置(虚拟地址空间),通常为空,表示让系统来选择共享内存的地址。 shmflg: shm_flg是一组标志位,通常为0。 返回值: 调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1. (3)将共享内存从当前进程中分离
int shmdt(const void *shmaddr);
该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。参数shmaddr是shmat()函数返回的地址指针,调用成功时返回0,失败时返回-1. (4)控制共享内存
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
shm_id: 共享内存 描述符。 cmd: 要采取的操作,它可以取下面的三个值 :
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内IPC_RMID:删除共享内存段。 shmid_ds结构 至少包括以下成员: struct shmid_ds { uid_t shm_perm.uid; uid_t shm_perm.gid; mode_t shm_perm.mode; };https://blog.csdn.net/zhaoyw2008/article/details/38787409
相比较其他的进程通信方式,共享内存确实是最快的。比如说以进程1 和进程2实现进程间通信为例 进程1 和进程2 要想进行进程间通信,首先进程1 需要将缓冲区的数据写到文件中,然后进程2再从文件中读出数据才能实现通信。然而共享内存就没有数据到文件的读写过程,因此效率最高.