Linux中的进程间通信之共享内存

时间:2024-10-03 20:51:25

共享内存

共享内存示意图

共享内存数据结构

struct shmid_ds {
 struct ipc_perm shm_perm; /* operation perms */
 int shm_segsz; /* size of segment (bytes) */
 __kernel_time_t shm_atime; /* last attach time */
 __kernel_time_t shm_dtime; /* last detach time */
 __kernel_time_t shm_ctime; /* last change time */
 __kernel_ipc_pid_t shm_cpid; /* pid of creator */
 __kernel_ipc_pid_t shm_lpid; /* pid of last operator */
 unsigned short shm_nattch; /* no. of current attaches */
 unsigned short shm_unused; /* compatibility */
 void *shm_unused2; /* ditto - used by DIPC */
 void *shm_unused3; /* unused */
};

共享内存函数

shmget函数

功能:用来创建共享内存
原型
 int shmget(key_t key, size_t size, int shmflg);
参数
 key:这个共享内存段名字---> 为了进行唯一性标识
 size:共享内存大小
 shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
shmflg:

IPC_CREAT:如何存在就获取,不存在就创建

IPC_EXEL:无法单独使用

IPC_CREAT|IPC_EXEL:不存在就创建,如何存在就出错返回

ftok
#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
key_t k=getKey();
    printf("key: 0x%x\n",k);
    int shmid=createShm(k);
    printf("shmid: %d\n",shmid);

key: 0x66053050
shmid: 65595

共享内存=物理内存块+共享内存相关属性

ipcs -m

查看共享内存

共享内存的生命周期是随OS的,不是随进程的。

ipcrm -m shmid

删除共享内存

shmctl函数

功能:用于控制共享内存
原型
 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
 shmid:由shmget返回的共享内存标识码
 cmd:将要采取的动作(有三个可取值)
 buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

监视共享内存:

while :; do ipcs -m; sleep 1; echo "---------------------"; done

shmat函数

让共享内存和进程关联起来

功能:将共享内存段连接到进程地址空间
原型
 void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
 shmid: 共享内存标识
 shmaddr:指定连接的地址
 shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1

共享内存的优点:速度最快,能大大减少拷贝次数。

共享内存的缺点:没有同步和互斥的操作,没有对数据做保护

共享内存大小一般为4KB(page)的整数被,4KB是内存划分的基本单位

同样的代码使用共享内存和管道,考虑键盘输入和显示器输出,二者各有几次数据拷贝?

管道需要经历6次拷贝(去除cin的话为4次)

共享内存需要经历4次拷贝(去除cin的话为2次)