linux IPC 通信 study 五:system v 共享内存

Share memory允许多个进程共享一个给定的存储区域,因为数据不需要在多个进程之间复制,所以他是最快的IPC。要注意的是多个进程在访问share memory的时候一定要做同步机制,防止读到脏数据,或者写坏数据。

API介绍
  • 1.shmget

    sys/shm.h

    int shmget(key_t key, size_t size, intflag);

    成功执行返回share memory id,若出错返回-1

    参数key通过ftok获得

    参数size表示共享存储空间的长度,以字节为单位。实现通常将其向上取为系统页长的整数倍,页对齐,若时间长度并不是页的整数倍,最后一个页的剩余部分不可用。

    如果进程创建share memory,则必须指定size的大小;

    如果进程只是访问share memroy,指定size为0;

    参数flag,定义一些访问权限

             IPC_CREAT| IPC_EXCL 表示share memory id标识的共享存储是否已经存在,存在的话就会返回-1,并且errno=EEXIST;

  • 2.shmat

    sys/shm.h

    int shmat(int shmid, const char *addr, int flag);

    成功时返回映射出来的地址,失败时返回-1

    参数shmid是通过shmget得到的

    参数addr 如果为0,表示shm连接到有内核选择的第一个可用的地址上。

    如果非0,并且flag也没有执行SHM_RND,则连接上addr指定的地址上;

    如果非0,并且flag指定了SHM_RND,则连接到(addr-(addr mod SHMLBA))所表示的地址上;

    参数flag,SHM_RDONLY表示只读,否则表示读写。

     

  • 3.shmdt

    sys/shm.h

    int shmdt(const char *addr);

    成功时返回0,失败时返回-1

    参数addr 是shmat的返回值。相当于一个detach的动作,减少shmid_ds中的shm_nattch数目

  • 4.shmctl

    sys/shm.h

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

    成功时返回0,失败时返回-1

    参数shmid通过shmget获得

    参数cmd:IPC_STAT,获取shmid_ds机构体中的数据信息

            IPC_SET,设置shmid_ds 结构体中的信息给SHM

    IPC_RMID,删除shm

    SHM_LOCK和SHM_UNLOCK,这两个标志容易搞混,它并不是说对shm加锁,做进程同步,真正的意义在于锁定这块共享内存并禁止它交换。被锁定的区段不允许被交换出内存(否则它可能被交换到虚拟内存中,swap分区)。这样做的优势在于,与其把内存区段交换到文件系统,在某个应用程序调用时再交换回内存,不如让它一直处于内存中,且对多个应用程序可见。从提升性能的角度来看,很重要的。但是,这并不代表一个进程锁定住共享内存以后其它进程禁止访问。锁定后只是不会交换到文件系统里(虚拟内存swap分区),而不是指它的访问性

    参数buf,具体根据cmd来输入,或者传入NULL

sample code:

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define SHM_PATH "./this_key"

typedef struct {
	int a;
	int b;
	int c;
	int e;
	int d;
}INFO;

int server()
{
	int shmid = shmget(ftok(SHM_PATH, 0x05), sizeof(INFO), IPC_CREAT | 0666);
	printf("shmid = %d\n", shmid);
	printf("shmsize = %d\n", sizeof(INFO));
	struct shmid_ds ds;
	shmctl(shmid, IPC_STAT, &ds);
	printf("realsize = %d\n", ds.shm_segsz);
	printf("attch num %d\n", ds.shm_nattch);

	INFO share_info;
	share_info.a = 1;
	share_info.b = 1;
	share_info.c = 0;
	share_info.d = 2;
	share_info.e = 0;

	INFO *ptr = (INFO *)shmat(shmid, 0, 0);
	memcpy(ptr, &share_info, sizeof(INFO));

	sleep(20);

	shmctl(shmid, IPC_RMID, NULL);
	printf("share memory removed\n");

}

int client()
{
	int shmid = shmget(ftok(SHM_PATH, 0x05), 0, IPC_CREAT | 0666);

	struct shmid_ds ds;
	shmctl(shmid, IPC_STAT, &ds);
	printf("\trealsize = %d\n", ds.shm_segsz);
	printf("\tattch num %d\n", ds.shm_nattch);

	INFO *p_share_info;
	p_share_info = (INFO *)shmat(shmid, 0, 0);
	printf("\tget info is %d %d %d %d %d\n",
			p_share_info->a,
			p_share_info->b,
			p_share_info->c,
			p_share_info->d,
			p_share_info->e);
	shmdt(p_share_info);

}

int main(int argc, char **argv)
{
	pid_t pid = fork();
	if (pid == 0) {
		sleep(1);
		client();
	} else if (pid > 0) {
		server();
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值