1.共享内存
共享内存:共享内存是一种最为高效的进程间通信方式。因为数据可以直接读写内存,不需要任何数据的拷贝。内核专门留出一块内存区,这段内存区可以由需要访问的进程将其中映射到自己的私有地址空间。但同时由于多个进程共享一段内存,因此也需要依靠同步机制,如互斥锁和信号量。(没有同步机制是共享内存的一个缺陷)
内核为每个共享内存段维护着一个结构,该结构至少要为每个共享内存段包含以下成员:
struct shmid_ds{
struct ipc_perm shm_perm;
size_t shm_segsz;
pid_t shm_lpid;
pid_t shm_cpid;
shmatt_t shm_nattch;
time_t shm_atime;
time_t shm_dtime;
time_t shm_ctime;
...
}
2.shmget
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg)
第一个参数key:有效地为共享内存段命名
第二个参数size:以字节为单位制定需要共享的内存容量。(实现通常将其向上取为系统页长的整数倍。但是,若应用指定的size值并非系统页长的整数倍,那么最后最后一页余下部分不可使用。)
第三个参数shmflg:权限标志
返回值: 成功:非负整数即共享内存标识符; 失败:-1
作用:创建新的共享内存或引用一个现有的共享内存。当创建一个新的共享内存时,初始化shmid_ds结构下列成员。
ipc_perm结构。其中mode按shmflg中的相应权限位设置
shm_lpid、shm_nattach、shm_atime和shm_dtime都设置为0.
shm_ctime设置为当前时间
shm_segsz设置为请求的size
如果创建一个新的共享内存段(通常在服务器进程中),则必须指定其size。如果正在引用一个现存的段(一个客户进程),则将size指定为0。当创建一个新共享内存时,段内的内容初始化为0.
3.shmat
#include <sys/shm.h>
char *shmat(int shmid, const void*shmaddr,int shmflg)
第一个参数shmid:共享内存标识符
第二个参数shmaddr:将共享内存映射到指定位置
如果shmaddr为0,则此段连接到由内核选择的第一个可用地址上。(这是推荐的使用方式)
如果shmaddr非0,并且没有指定SHM_RND,则此段连接到shmaddr所指定的地址上。
如果shmaddr非0,并且指定了SHM_RND,则此段连接到(shmaddr—(shmaddr mod SHMLBA))所表示的地方。
SHM_RND命令的意思是“取整”。SHMLBA的意思是“低边界地址倍数”(了解以下。现在基本使用这一种方式)
第三个地址:SHM_RND(这个标志与shm_addr联合使用,用来控制共享内存连接的地址)
SHM_RDONLY(使它连接的内存只读)
默认0:共享内存可读可写
返回值:返回一个指向共享内存第一个字节的指针; 失败:-1
作用:第一次创建共享内存时,它不能被任何进程访问。要想启用该共享内存的访问,必须将其连接到一个进程的地址空间中。
4.shmdt
#include <sys/shm.h>
int shmdt(const void *shmaddr)
第一个参数shmaddr:
shmaddr:被映射的共享内存段地址,在调用shmat时的返回值。
返回值: 成功:0; 失败:-1
作用:将共享内存从当前进程中分离(并不是删除)。 如果调用成功,shmdt将使相关shmid_ds结构中的shm_nattch计数器值减1。
5.shmctl
#include <sys/shm.h>
int shmctl(int shm_id, int command, struct shmid_ds *buf);
第一个参数shm_id:shmget返回的共享内存标识符
第二个参数command:要采取的动作,可以取三个值
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段
第三个参数buf:是一个指针,它指向包含共享内存模式和访问权限的结构
返回值:成功:0;失败:-1
struct shmid_ds{
uid_t shm_perm.uid,
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};