您的位置:首页 > 运维架构 > Linux

linux进程间通信——共享内存

2016-03-12 21:26 453 查看
共享内存。linux进程之间通信的一种方式。先说说优缺点吧。

共享内存,顾名思义,就是一块内存,大家都可以用。

优点:操作方便。直接访问内存,效率高。不需要进程有父子关系等等

缺点:需要自己同步控制。

关于linux的任何函数都可以通过命令man order,查看相关帮助。想要仔细看这些函数的相关帮助,请亲自操作,这是最好的方法。

涉及的函数:

注:这一系列函数都是以shm开头(share memory)。

头文件 :

#include <sys/ipc.h>

#include <sys/shm.h>

1. int
shmget(key_t key, size_t size, int shmflg);

这个函数的功能就是用来分配要共享的内存。但是并不是分配好就能用的。要想使用,请看下一个函数。

参数:

key_t key :关键码,可以自己随意定义,一个关键码对应一块共享内存。其他地方要想获取这块内存,需要知道这个key。

size_t size:要共享的内存的大小。相当于我们malloc时的参数。

int shmflg :这个标志是权限,一般可以设置为 0666|IPC_CREAT.

返回值:

成功返回共享内存的id。

失败返回-1,同时会设置errno。

2. void *shmat(int shmid, const void *shmaddr, int shmflg);

用来启动可分享的内存,并且把这段内存链接到本程序的地址空间中。

shm_id是由shmget函数返回的共享内存标识。
shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。
shm_flg是一组标志位,通常为0。

成功返回可分享内存的首地址,失败返回(void*)-1;

3. int shmdt(const void *shmaddr);

用来取消分享内存与本程序的关联。并不是释放这段分享的内存空间。

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

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

用来控制共享内存。

shm_id是shmget函数返回的共享内存标识符。

command是要采取的操作,它可以取下面的三个值 :
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值

IPC_RMID:删除共享内存段

buf是一个结构指针,它指向共享内存模式和访问权限的结构。
shmid_ds结构可以包括以下成员:

struct shmid_ds {

struct ipc_perm shm_perm; /* Ownership and permissions */

size_t shm_segsz; /* Size of segment (bytes) */

time_t shm_atime; /* Last attach time */

time_t shm_dtime; /* Last detach time */

time_t shm_ctime; /* Last change time */

pid_t shm_cpid; /* PID of creator */

pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */

shmatt_t shm_nattch; /* No. of current attaches */

...

};

下面是一些代码。每隔1秒去设置一下共享内存的内容。

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>

int main()
{
	int shmid;
	void* mem;
	shmid = shmget(8889, 4, 0666|IPC_CREAT);
	if (shmid == -1)
	{
		printf("shmget err!\n");
		return -1;
	}
	mem = shmat(shmid, 0, 0);
	if (mem == (void*)-1)
	{
		printf("shmat err!\n");
		return -2;
	}
	int i=0;
	for (; i<20 ; i++)
	{
		*(int*)mem = i;
		printf("shm set:%d\n", i);
		sleep(1);
	}
	if (-1 == shmdt(mem))
	{
		printf("shmdt err!\n");
		return -3;
	}
	return 0;
}</span>


另一个进程,每隔1秒读取一下共享内存的内容。

<span style="font-size:14px;">#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>

int main()
{
	int shmid ;
	void* mem;
	shmid = shmget(8889, 4, 0666|IPC_CREAT);
	if (shmid == -1)
	{
		printf("shmget err!\n");
		return -1;
	}
	mem = shmat(shmid, 0, 0);
	if (mem == (void*)-1)
	{
		printf("shmat err!\n");
		return -2;
	}
	int i = 0;
	for(;i<20;i++)
	{
		printf("shm:%d\n",*(int*)mem);
		sleep(1);
	}

	if (-1 == shmdt(mem))
	{
		printf("shmdt err!\n");
		return -3;
	}
	if (shmctl(shmid, IPC_RMID, 0) == -1)
	{
		printf("shmctl(shmid, IPC_RMID, 0) err!\n");
		return -4;
	}
	return 0;
}</span>


同时运行两个程序。结果如图;



可以看出,由于没有同步控制。s1一开始输出了两个0。也是属于正常情况。这也是共享内存的缺点,需要我们自己同步。下一篇,学习信号量与共享内存同时使用。自己来同步。。

如有问题,请斧正。感激不尽。

谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: