不同进程共享链表方法:用共享内存创建链表
2016-12-28 10:48
931 查看
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 就再没有东西了,因为已经删除了。不截图了,不信就算~~~
相关文章推荐
- 共享内存 不同进程中共享一个链表
- 进程间创建共享内存
- 单台服务器的PHP进程之间实现共享内存的方法
- Tomcat 服务器配置及远程调试和不同web项目session共享方法以及设置TOMCAT的内存
- 两个或多个进程之间通过Win32 API实现内存共享的方法(转)
- 0907使用write函数向共享内存中写入数据,实现不同进程间的数据信息传递
- 生产者进程和消费者进程共享内存解决方法---循环数组
- 简单的,两个不同进程间的共享内存通信(大小写转换)
- 创建单线性链表的不同表示方法和操作
- 进程内存共享的方法
- 单台服务器的PHP进程之间实现共享内存的方法
- 进程中的标识符和键(ftok函数创建)(共享内存,消息队列,信号量用到的)
- linux中进程共享内存的2种方法
- 两个或多个进程之间通过Win32 API实现内存共享的方法(转)
- 不同进程之间共享内存
- 父子进程共享内存通信的三种方法
- 创建进程间共享内存映射
- 创建进程,消息通信,共享内存通信,管道通信
- 父子进程共享内存通信的三种方法
- 通过信号量和共享内存实现h264码流在不同进程间传输