不同进程共享链表方法:用共享内存创建链表

int shmid = shmget(KEY,sizeof(struct node),IPC_CREAT|0666);
int ret = shmctl(shmid,IPC_RDIM,NULL);

不同的进程拥有独立的进程空间,是不能共享各自的变量的,这就引申了一个问题,就是不同的进程不能操作同一个链表,那如何解决这个问题呢,我们用到了共享内存。

共享内存是物理地址,可以映射给多个进程使用。


初略介绍一下共享内存的创建,映射,和删除。

首先是 shmget(),用于获取或创建一个共享内存空间,三个参数:KEY值,创建的共享内存大小,IPC_CREAT表示创建共享像内存,|0666表示共享内存的权限

第一个参数也可以为0.表示创建一个共享内存,但你无法通过KEY值来找到他。

int shmid = shmget(KEY,sizeof(struct node),IPC_CREAT|0666);  //KEY 用define 定义成了5555,当然你可以随便定义一个数,用于标识而已
if(shmid == -1)
{
	perror("failed to shmget\n");
	return -1;
}

接着是 shmat(),用于把共享内存映射进 进程空间,两个参数:共享内存的标识ID,NULL表示共享内存映射到进程空间的适合位置,,0表示可写可读
struct node* p =(struct node*)shmat(shmid,NULL,0);
而 shmdt()跟shmat()相反,shmdt是断开 进程空间和共享内存的连接的,例如:
struct node* p =(struct node*)shmat(shmid,NULL,0);   //连接共享内存
shmdt(p);					     //断开共享内存

shmctl()用于控制共享内存,可用于获取共享内存的状态,删除共享内存,改变共享内存状态。这里只说如何用 shmctl来删除共享内存:

三个参数:第一个为共享内存的ID,第二个为cmd,IPC_RMID表示要删除共享内存,第三个:在第二个参数为IPC_RMID的情况下填NULL就好。

int shmid = shmget(KEY,sizeof(struct node),IPC_CREAT|0666);
int ret = shmctl(shmid,IPC_RMID,NULL);

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

接下来介绍如何创建共享内存链表:

#include"myhead.h"
#define KEY 5566

struct node
{
	int val;
	int next;
};


int main(int argc, char const *argv[])
{
	struct node *head;
	struct node *p;
	int shmid = shmget(KEY,sizeof(struct node),IPC_CREAT|0666);   //申请一个共享内存当头结点,这个头节点要用KEY来做键值,因为方便找到他
	if(shmid == -1)
	{
		perror("failed to shmget\n");
		return -1;
	}
	head =(struct node*)shmat(shmid,NULL,0);			//把创建的共享内存映射到进程空间,并用head指向他。
	p = head;                                               //head作为头节点是不能动的,因此创建一个指针p来进行操作
	do
	{
		shmid = shmget(0,sizeof(struct node),IPC_CREAT|0666); //创建其他共享贡献内存结点
		p->next = shmid;                                      //把获得的共享内存ID给变量next,用来让p去指向共享内存映射后的地址。
		p = (struct node*)shmat(shmid,NULL,0);                //p指向共享内存映射后的地址
		scanf("%d",&p->val);                                  //给这个共享内存结点的val变量赋值,这个val才是我们用来保存数据的变量
	}while(p->val!=0);                                           //当共享内存的val变量赋值为0,创建共享内存链表结束。
	return 0;
}




运行结果:

运行程序 ./text后,开始输入 p->val 的值,然后用命令 ipcs -m 查看共享内存,有5个共享内存(算上头节点刚好5个)。

---------------------------------------------------------------------------------------------------------------------------------

再下面给出包含删除链表等功能更详细的代码:

下面的代码会创建多一个链表(是传统的链表),来保存所有共享内存的id,方便删除共享内存链表。

为什么要这样做?因为共享内存链表不是传统意义上的链表,他的没有指向下一个地址的指针,只有通过映射结点ID来指向下一个结点。一个结点的ID 是保存在上一个共享内存结点中的,这就导致头节点的ID必须通过shmget()和键值KEY来获得,

所以干脆弄多一条链表出来保存所有共享内存的ID。

#include"myhead.h"
#define KEY 5566

struct node              //共享内存链表结构体
{
	int val;
	int next;
};

struct shmid             //共享内存ID链表结构体
{
	int shmid;
	struct shmid *next;
};

struct shmid *shm_head;

struct shmid* init_list(struct shmid *shm_head)        //初始化共享内存ID链表头节点
{
	shm_head = malloc(sizeof(struct shmid));
	shm_head ->shmid = 0;
	shm_head->next = NULL;
	return shm_head;
}

void del_shm_list(struct node *head,struct shmid *shm_head)      //删除共享内存链表函数
{
	struct node *pnode;         //共享内存链表头节点
	struct shmid *pshm;         //共享内存ID链表头节点
	pnode = head;
	pshm = shm_head->next;
	while(pshm!=NULL)
	{
		head = (struct node*)shmat(head->next,NULL,0);
		shmdt(pnode);
		shmctl(pshm->shmid,IPC_RMID,NULL);
		pnode = head;
		pshm = pshm->next;
	}
}

int add_shmid(struct shmid* shm_head,int shmid)             //把共享内存的ID加入到共享内存ID链表中
{
	struct shmid *p = shm_head;
	struct shmid *newid = malloc(sizeof(struct shmid));
	newid ->shmid = shmid;
	newid ->next = NULL;
	while(p->next!=NULL)
	{
		p = p->next;
	}
	p->next = newid;
	return 0;
}

void show_shmid(struct shmid* head)            //遍历共享内存ID链表,列出所有共享内存结点的ID号
{
	struct shmid *p = head->next;
	while(p!=NULL)
	{
		printf("%d ",p->shmid);
		p = p->next;
	}
}

int main(int argc, char const *argv[])
{
	struct node *head;
	shm_head = init_list(shm_head);

	int shmid = shmget(KEY,sizeof(struct node),IPC_CREAT|0666);
	add_shmid(shm_head,shmid);

	if(shmid == -1)
	{
		perror("failed to shmget\n");
		return -1;
	}
	head =(struct node*)shmat(shmid,NULL,0);
	struct node *p;
	p = head;
	do
	{
		shmid = shmget(0,sizeof(struct node),IPC_CREAT|0666);
		add_shmid(shm_head,shmid);
		p->next = shmid;
		p = (struct node*)shmat(shmid,NULL,0);
		scanf("%d",&p->val);
		if(p->val == 0)
		{
			p->next = 0;
		}
	}while(p->val!=0);
	show_shmid(shm_head);               //显示所有共享内存ID号
	del_shm_list(head,shm_head);        //删除所有共享内存
	return 0;
}

//这个程序运行后,在命令行中输入 ipcs -m 就再没有东西了,因为已经删除了。不截图了,不信就算~~~





















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值