
本文共 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;}
struct node* p =(struct node*)shmat(shmid,NULL,0);
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 就再没有东西了,因为已经删除了。不截图了,不信就算~~~
发表评论
最新留言
关于作者
