一. 共享内存
在系统中,两个不同的进程都会维护自己的一块地址空间,这个地址空间一般是虚拟地址,会通过mmu和页表映射到对应的物理内存中,因为不同的进程会有不同的内存空间,因此两个进程之间是无法看见彼此的数据的,而共享内存就是使两个进程看到同一块地址空间,以此来实现不同进程间的数据交互。
值得提出的是,共享内存是进程间通信方式中最高效的一种,因为是直接通过访问内存来交换数据的,省去了消息队列中数据的复制和信号量中进行P、V操作所占用的时间。
二. 共享内存中的函数
1.共享内存的创建与销毁
创建:
函数参数中,
key值就不用说了,是用ftok函数创建出来的,需要使用路径名和一个proj_id的整数;
size指的是需要多大的空间,在Linux中数据是按页来分的,1页也就是4K也是4096个字节,这个size的 对齐数是4096的整数倍,也就是如果你指定了4098个字节,系统就会分配4096*2的大小空间;
shmflg和消息队列及信号量中是一样的,有IPC_CREAT和IPC_EXCL两个选项,同时使用这两个值就会新创建出一个共享内存,若共享内存存在就会返回-1;而当IPC_CREAT单独使用时若共享内存存在就返回存在的共享内存ID,否则就会新创建;
销毁:
函数参数中,
shmid就是创建出的共享内存的ID,而cmd的选项可以是IPC_RMID,后面的buf是一个结构体指针,这里需要销毁共享内存,可以将buf设为NULL;
2.共享内存的关联与取消关联
创建出了共享内存之后,需要的就是将进程同这个共享内存关联起来以能够使用,同样,使用完了之后也需要将关联解除:
上图中,
shmat是将进程同共享内存关联起来attach,shmid是共享内存的ID,而后面的shmaddr是一个缓冲区的指 针,如果为NULL,系统会自动的选择一块合适的内存作为缓冲区,而shmflg可以是SHM_RDONLY表示 进程在共享内存中只读,而当shmflg为0时表示读写都可以,并没有只写这一选项;
可以看到shmat函数的返回值是一个void型的指针,这可以理解为在内存中开辟好了一块空间返回 的指针;
shmdt函数中参数只有一个,开辟出了内存当然也要释放了,因此shmaddr就是shmat的返回值,用来取消 关联;
栗子时间:
和前面所谈的消息队列及信号量相同,可以将共享内存中的函数封装起来:
这样可以创建两个进程shm_client.c和shm_server.c:
两个进程都与创建好的共享内存取得关联,shm_client.c向共享内存中写入数据,而shm_server.c从中取出数据打印出来,这样也就实现的进程间的通信,运行程序:
这里要说的一点就是,上一篇谈到的信号量,其实就可以和共享内存结合使用,因为当两个进程同时访问一块共享内存向中写入数据或者读取数据的时候就会产生冲突,这时可以将共享内存看做一个临界资源用信号量来作为标识,可以完成进程间的同步和互斥的问题。
原文作者:精通Linux内核
原文地址:Linux内核:进程管理——共享内存(版权归原文作者所有,侵权留言联系删除)