不同进程共享链表方法:用共享内存创建链表
发布日期:2021-05-07 04:38:46 浏览次数:17 分类:精选文章

本文共 4377 字,大约阅读时间需要 14 分钟。

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 5566struct 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 5566struct 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 就再没有东西了,因为已经删除了。不截图了,不信就算~~~
上一篇:(四) 用poll实现TCP服务端
下一篇:(三)TCP用select函数处理多个客户端连接(非阻塞模式)

发表评论

最新留言

能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月14日 00时06分51秒