实现在C的a_list结构(共享内存链表)共享内存段 [英] Implement shared memory segment with a_list struct (linked list in shared memory) in C

查看:626
本文介绍了实现在C的a_list结构(共享内存链表)共享内存段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用此结构,我把持有节点共享内存段

 结构的a_list
{
  //充当节点列表的头,这个名单有下一个*和preV *
  结构LIST_HEAD清单;
  无符号长* VAL;
  字符*海峡;
  焦状态;
};

我试图查找堆栈上的答案,但他们实现了一个节点,而不是我的结构,这是与节点列表里面

我也有这个缓冲区,并追加方法,我用追加到这个列表(使用malloc),但我知道,共享内存我不能这样做,

 结构缓冲
{
    结构的a_list *缓冲区[BUFFER_SIZE];
    int类型;
    int的列;
};
//方法附加一个文件到队列的末尾(最近使用的文件是在尾部)
静态无效追加(结构的a_list * PTR,为const char * str中,无符号长VAL)
{
  结构的a_list * tmp目录;
  TMP =(结构的a_list *)malloc的(的sizeof(结构的a_list)); // tmp->海峡= str中;
  tmp-> STR =(字符*)malloc的(strlen的(STR)+1);
  的strcpy(tmp-> STR,STR);
  tmp-> VAL =(无符号长*)malloc的(sizeof的(无符号长));
  的memcpy(tmp-> VAL,和放大器; VAL,sizeof的(无符号长));
  tmp->指数=(INT *)malloc的(的sizeof(INT));
  的memcpy(tmp->指数&放大器; buffer_p->在,的sizeof(INT));
  tmp->地址=(结构的a_list *)malloc的(的sizeof(结构的a_list *));
  的memcpy(tmp->地址,&安培; fileQueue,的sizeof(结构的a_list *));
  如果(list_empty(安培; fileQueue.list)){//如果这是要被插入到fileQueue的第一要素,初始化头
    list_add_tail(及(tmp->表),及(ptr->列表));
    头= LIST_ENTRY(fileQueue.list.next,结构的a_list,清单);
  }
  其他{//否则只需将其添加到列表的尾部
    list_add_tail(及(tmp->表),及(ptr->列表));
  }
 //而(((buffer_p->在+ 1)%BUFFER_SIZE)== buffer_p->出)
    //;  buffer_p->缓冲液[buffer_p->在[= tmp->地址;
        //输出(放置数:%d \\ n,计数器);  buffer_p->在=(buffer_p->在+ 1)%BUFFER_SIZE;
}

和在我的主要我尝试用

初始化一切

 如果((的shmid = shmget的(键,(BUFFER_SIZE + 2)* sizeof的(INT),IPC_CREAT | 0666))小于0){
        PERROR(shmget的);
        出口(1);
    }    如果((SHM =的shmat(的shmid,NULL,0))≤; 0){
        PERROR(的shmat);
        出口(1);
    }    buffer_p =(结构缓冲*)SHM;
    buffer_p->在= 0;
    buffer_p->淘汰= 0;

我不喜欢这是如何工作的,因为IM做的指针的东西,一直malloc分配(不会共享内存的工作),所以我想改变它,以便它实际上将共享内存工作。我已经使用Beej指南共享内存作为指导以及几个堆栈溢出的问题,但没有人可以给我这个特定情况下(或至少我不明白的答案)。任何帮助将是AP preciated,即使它只是一个概念的IM可能丢失。在结构的a_list(fileQueue)的LIST_HEAD结构是从一个头文件中引用内核链表实现一个结构。

编辑:这是在这一程序正在使用的LIST_HEAD结构,它使用基本内核实现的清单

  / **
 *
 *我是从Linux内核源代码code GRUB时,并修复它为用户空间
 *程序。当然,这是一个GPL许可的头文件。
 *
 *这里是做饭list.h为用户空间程序的食谱
 *
 * 1。从Linux拷贝list.h /有/ list.h
 * 2.删除
 * - #IFDEF __KERNE__及其#ENDIF
 * - 所有的#include行
 * - prefetch()和RCU相关功能
 * 3.添加,宏offsetof()和container_of
 *
 * - kazutomo@mcs.anl.gov
 * /
的#ifndef _LINUX_LIST_H
#定义_LINUX_LIST_H/ **
 *从其他内核头文件@name
 * /
/ * @ {* // **
 *获取一个成员的偏移
 * /
的#define offsetof(TYPE,MEMBER)((为size_t)及((TYPE *)0) - > MEMBER)/ **
 *施放结构的构件出到含有结构
 * @参数PTR指针的成员。
 * @参数键入容器结构这被嵌入的类型。
 * @参数构件的结构中的部件的名称。
 *
 * /
#定义container_of(PTR,类型,成员)({\\
        常量的typeof(((键入*)0) - >成员)* __ mptr =(PTR); \\
        (类型*)((字符*)__ mptr - offsetof(类型,成员));})
/ * @} * /
/ *
 *这些是会导致页面错误非NULL指针
 *在正常情况下,用于验证无人使用
 *非初始化列表条目。
 * /
#定义LIST_POISON1((无效*)0x00100100)
#定义LIST_POISON2((无效*)0x00200200)/ **
 *简单的双向链表实现。
 *
 *有些内部函数(__xxx)是有用的时候
 *操纵整个列表,而不是单一的项目,如
 *有时候,我们已经知道下一个/ $ P $光伏项目,我们可以
 *使用它们,而不是直接生成更好的code
 *使用通用单次入境程序。
 * /
结构LIST_HEAD {
    结构LIST_HEAD *接下来,* preV;
};的#define LIST_HEAD_INIT(名称){及(名称),及(名)}#定义LIST_HEAD(名)\\
    结构LIST_HEAD名= LIST_HEAD_INIT(名称)#定义INIT_LIST_HEAD(PTR)做{\\
    (PTR) - >接着=(PTR); (PTR) - GT; preV =(PTR); \\
}而(0)/ *
 *将连续两个知名项目之间的新条目。
 *
 *这是仅用于内部列表操作,我们知道
 *在preV /下一个条目已!
 * /
静态内嵌无效__list_add(结构LIST_HEAD *新的,
                  结构LIST_HEAD * preV,
                  结构LIST_HEAD * NEXT)
{
    下一步 - > preV =新的;
    新建 - >接下来=下一个;
    新建 - > preV = preV;
    preV->接下来=新的;
}/ **
 * list_add - 添加新条目
 * @new:新条目添加
 * @head:表头添加后
 *
 *将指定的头后,一个新的条目。
 *这是很好的执行堆栈。
 * /
静态内嵌无效list_add(结构LIST_HEAD *新的,结构LIST_HEAD *头)
{
    __list_add(新,头,流浆>接着);
}/ **
 * list_add_tail - 添加新条目
 * @new:新条目添加
 * @head:列表头前加入
 *
 *将指定的头前,一个新的条目。
 *这是用于实现队列有用。
 * /
静态内嵌无效list_add_tail(结构LIST_HEAD *新的,结构LIST_HEAD *头)
{
    __list_add(新,流浆> preV,头);
}
/ *
 *通过使preV /下一个条目删除列表条目
 *指向对方。
 *
 *这是仅用于内部列表操作,我们知道
 *在preV /下一个条目已!
 * /
静态内嵌无效__list_del(结构LIST_HEAD * preV,结构LIST_HEAD * NEXT)
{
    下一步 - > preV = preV;
    preV->接下来=下一个;
}/ **
 * list_del - 删除列表条目。
 * @entry:元素从列表中删除。
 *注:在进入list_empty在此之后没有返回true,该条目
 *不确定状态。
 * /
静态内嵌无效list_del(结构LIST_HEAD *进入)
{
    __list_del(入门级GT&; preV,入门>接着);
    入门级>接下来= LIST_POISON1;
    入门级GT&; preV = LIST_POISON2;
}/ **
 * list_del_init - 删除列表项,重新初始化。
 * @entry:元素从列表中删除。
 * /
静态内嵌无效list_del_init(结构LIST_HEAD *进入)
{
    __list_del(入门级GT&; preV,入门>接着);
    INIT_LIST_HEAD(输入);
}/ **
 * list_move - 从一个列表中删除,并添加作为另一个的头
 * @list:移动的条目
 * @head:将precede我们进入头部
 * /
静态内嵌无效list_move(结构LIST_HEAD *名单,结构LIST_HEAD *头)
{
        __list_del(列表 - > preV,列表 - >接着);
        list_add(清单头);
}/ **
 * list_move_tail - 从一个列表中删除,并添加作为另一个的尾巴
 * @list:移动的条目
 * @head:将按照我们的条目中的头
 * /
静态内嵌无效list_move_tail(结构LIST_HEAD *名单,
                  结构LIST_HEAD *头)
{
        __list_del(列表 - > preV,列表 - >接着);
        list_add_tail(清单头);
}/ **
 * list_empty - 测试是否一个列表是空的
 * @head:列表中进行测试。
 * /
静态内嵌INT list_empty(常量结构LIST_HEAD *头)
{
    返回流浆>接下来==头;
}静态内嵌无效__list_splice(结构LIST_HEAD *名单,
                 结构LIST_HEAD *头)
{
    结构LIST_HEAD *第一=列表 - >接下来,
    结构LIST_HEAD *最后=列表 - > preV;
    结构LIST_HEAD *在流浆=>接下来,    第一代和GT; preV =头;
    流浆>首先下一=;    最后所>接下来=上;
    AT-> preV =最后;
}/ **
 * list_splice - 加入两个列表
 * @list:新名单的补充。
 * @head:将其添加在第一个列表的地方。
 * /
静态内嵌无效list_splice(结构LIST_HEAD *名单,结构LIST_HEAD *头)
{
    如果(!list_empty(列表))
        __list_splice(清单头);
}/ **
 * list_splice_init - 连接两个列表,并重新初始化清空列表。
 * @list:新名单的补充。
 * @head:将其添加在第一个列表的地方。
 *
 *在@list清单重新初始化
 * /
静态内嵌无效list_splice_init(结构LIST_HEAD *名单,
                    结构LIST_HEAD *头)
{
    如果(!list_empty(列表)){
        __list_splice(清单头);
        INIT_LIST_HEAD(名单);
    }
}/ **
 * LIST_ENTRY - 获得结构此条
 * @ptr:在&放大器;结构LIST_HEAD指针。
 * @type:这是嵌入在该结构的类型。
 * @member:结构内的list_struct的名称。
 * /
#定义LIST_ENTRY(PTR,类型,成员)\\
    container_of(PTR,类型,成员)/ **
 * list_for_each - 迭代列表
 * @pos:所述&放大器;结构LIST_HEAD作为循环计数器来使用。
 * @head:头部为你的列表中。
 * /#定义list_for_each(POS,头)\\
  对于(POS =(头) - >!下一; POS =(头); \\
       POS = POS->接下来)/ **
 * __list_for_each - 迭代列表
 * @pos:所述&放大器;结构LIST_HEAD作为循环计数器来使用。
 * @head:头部为你的列表中。
 *
 *该变种从list_for_each(不同),因为它是
 *尽可能简单的列表进行迭代code,没有prefetching完成。
 *使用此为code,知道的名单很短(空
 *或1项)的大部分时间。
 * /
#定义__list_for_each(POS,头)\\
    对于(POS =(头) - >接下来,POS =(头); POS = POS->接着!)/ **
 * list_for_each_ preV - 遍历列表向后
 * @pos:所述&放大器;结构LIST_HEAD作为循环计数器来使用。
 * @head:头部为你的列表中。
 * /
#定义list_for_each_ preV(POS,头)\\
    对于(POS =(头) - >!preV; prefetch(POS-GT&; preV),POS =(头); \\
            POS = POS-> preV)/ **
 * list_for_each_safe - 遍历列表与去除列表项的安全
 * @pos:所述&放大器;结构LIST_HEAD作为循环计数器来使用。
 * @n:另一个与放大器;结构LIST_HEAD用作临时存储
 * @head:头部为你的列表中。
 * /
#定义list_for_each_safe(POS,N,头)\\
    对于(POS =(头) - >接下来,N = POS->接下来,POS =(头); \\!
        POS = N,N = POS->接下来)/ **
 * list_for_each_entry - 迭代给定类型的列表
 * @pos:类型*为循环计数器使用。
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry(POS,头,成员)\\
    对于(POS = LIST_ENTRY((头) - >接下来的typeof(* POS),成员); \\
         POS->成员=(头)!; \\
         POS = LIST_ENTRY(POS-GT&;成​​员 - >接下来的typeof(* POS),成员))/ **
 * list_for_each_entry_reverse - 向后遍历​​给定类型的列表。
 * @pos:类型*为循环计数器使用。
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry_reverse(POS,头,成员)\\
    对于(POS = LIST_ENTRY((头) - > preV的typeof(* POS),成员); \\
         &放大器; POS-GT&;!=成员(头); \\
         POS = LIST_ENTRY(POS-方式>会员preV的typeof(* POS),成员))/ **
 * list_ prepare_entry - prepare一个POS条目用作起点
 * list_for_each_entry_continue
 * @pos:类型*为起点使用
 * @head:列表的头
 * @member:结构内的list_struct的名称。
 * /
#定义list_ prepare_entry(POS,头,成员)\\
    ((POS):LIST_ENTRY(头的typeof(* POS),成员))/ **
 * list_for_each_entry_continue - 迭代给定类型的列表
 *现有点后继续
 * @pos:类型*为循环计数器使用。
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry_continue(POS,头,成员)\\
    对于(POS = LIST_ENTRY(POS-GT&; member.next的typeof(* POS),成员); \\
         &放大器; POS-GT&;!=成员(头); \\
         POS = LIST_ENTRY(POS-GT&; member.next的typeof(* POS),成员))/ **
 * list_for_each_entry_safe - 迭代对去除列表项的安全特定类型的列表
 * @pos:类型*为循环计数器使用。
 * @n:另一种类型的*用作临时存储
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry_safe(POS,N,头,成员)\\
    对于(POS = LIST_ENTRY((头) - >接下来的typeof(* POS),成员),\\
        N = LIST_ENTRY(POS-GT&; member.next的typeof(* POS),成员); \\
         &放大器; POS-GT&;!=成员(头); \\
         POS = N,N = LIST_ENTRY(N-> member.next的typeof(* n)的成员))/ **
 * list_for_each_entry_safe_continue - 迭代给定类型的列表
 *现有的点对安全拆除列表条目后继续
 * @pos:类型*为循环计数器使用。
 * @n:另一种类型的*用作临时存储
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry_safe_continue(POS,N,头,成员)\\
    对于(POS = LIST_ENTRY(POS-GT&; member.next的typeof(* POS),成员),\\
        N = LIST_ENTRY(POS-GT&; member.next的typeof(* POS),成员); \\
         &放大器; POS-GT&;!=成员(头); \\
         POS = N,N = LIST_ENTRY(N-> member.next的typeof(* n)的成员))/ **
 * list_for_each_entry_safe_reverse - 向后遍历​​给定类型对安全名单
 *除去列表条目的
 * @pos:类型*为循环计数器使用。
 * @n:另一种类型的*用作临时存储
 * @head:头部为你的列表中。
 * @member:结构内的list_struct的名称。
 * /
#定义list_for_each_entry_safe_reverse(POS,N,头,成员)\\
    对于(POS = LIST_ENTRY((头) - > preV的typeof(* POS),成员),\\
        N = LIST_ENTRY(POS-方式>会员preV的typeof(* POS),成员); \\
         &放大器; POS-GT&;!=成员(头); \\
         POS = N,N = LIST_ENTRY(N-方式>会员preV的typeof(* n)的成员))
/ *
 *双链表用一个指针链表头。
 *为哈希表,其中两个指针链表头大多是有益的
 *太浪费了。
 *您失去访问O(1)尾部的能力。
 * /结构hlist_head {
    结构hlist_node *第一;
};结构hlist_node {
    结构hlist_node *接下来,** P preV;
};#定义HLIST_HEAD_INIT {。首先= NULL}
#定义HLIST_HEAD(名称)结构hlist_head名= {。首先= NULL}
的#define INIT_HLIST_HEAD(PTR)((PTR) - >首先= NULL)
的#define INIT_HLIST_NODE(PTR)((PTR) - >接着= NULL,(PTR) - 指p preV = NULL)静态内嵌INT hlist_unhashed(常量结构hlist_node * H)
{
    返回H-> P!preV;
}静态内嵌INT hlist_empty(常量结构hlist_head * H)
{
    返回H->!第一;
}静态内嵌无效__hlist_del(结构hlist_node * N)
{
    结构hlist_node *下一= N>接下来,
    结构hlist_node ** P preV = N-指p preV;
    * P preV =下一个;
    如果(下)
        下一页 - 指p preV = P preV;
}静态内嵌无效hlist_del(结构hlist_node * N)
{
    __hlist_del(N);
    N->接下来= LIST_POISON1;
    正指p preV = LIST_POISON2;
}
静态内嵌无效hlist_del_init(结构hlist_node * N)
{
    如果(正指p preV){
        __hlist_del(N);
        INIT_HLIST_NODE(N);
    }
}静态内嵌无效hlist_add_head(结构hlist_node * N,结构hlist_head * H)
{
    结构hlist_node *第一= H->首先,
    N->首先下一=;
    如果(第一)
        一线指p preV =&放大器; N->接下来,
    H->首先= N;
    正指p preV =&放大器; H->首先,
}/ *接下来一定是!= NULL * /
静态内嵌无效hlist_add_before(结构hlist_node * N,
                    结构hlist_node * NEXT)
{
    正指p preV =下一页 - 指p preV;
    N->接下来=下一个;
    下一页 - 指p preV =&放大器; N->接下来,
    *(正指p preV)= N;
}静态内嵌无效hlist_add_after(结构hlist_node * N,
                    结构hlist_node * NEXT)
{
    下一步 - >接下来= N->接下来,
    N->接下来=下一个;
    下一页 - 指p preV =&放大器; N->接下来,    如果(下一页 - >下面)
        下一步 - >下一页 - 指p preV =&放大器;下一步 - >接下来,
}#定义hlist_entry(PTR,类型,成员)container_of(PTR,类型,成员)#定义hlist_for_each(POS,头)\\
    对于(POS =(头) - >首先,POS和放大器;及({prefetch(POS->下面); 1;}); \\
         POS = POS->接下来)#定义hlist_for_each_safe(POS,N,头)\\
    对于(POS =(头) - >首先,POS和放大器;及({N = POS->接下来1;}); \\
         POS = N)/ **
 * hlist_for_each_entry - 迭代给定类型的列表
 * @tpos:类型*为循环计数器使用。
 * @pos:所述&放大器;结构hlist_node作为一个循环计数器使用。
 * @head:头部为你的列表中。
 * @member:结构内的hlist_node的名称。
 * /
#定义hlist_for_each_entry(TPOS,POS,头,成员)\\
    对于(POS =(头) - >首先,\\
         POS机和放大器;&安培; ({prefetch(POS->下面); 1;})及&放大器; \\
        ({TPOS = hlist_entry(POS的typeof(* TPOS),成员); 1;}); \\
         POS = POS->接下来)/ **
 * hlist_for_each_entry_continue - 遍历hlist现有点之后继续
 * @tpos:类型*为循环计数器使用。
 * @pos:所述&放大器;结构hlist_node作为一个循环计数器使用。
 * @member:结构内的hlist_node的名称。
 * /
#定义hlist_for_each_entry_continue(TPOS,POS机,会员)\\
    为(位置=(POS) - >接下来; \\
         POS机和放大器;&安培; ({prefetch(POS->下面); 1;})及&放大器; \\
        ({TPOS = hlist_entry(POS的typeof(* TPOS),成员); 1;}); \\
         POS = POS->接下来)/ **
 * hlist_for_each_entry_from - 遍历hlist从现有的点继续
 * @tpos:类型*为循环计数器使用。
 * @pos:所述&放大器;结构hlist_node作为一个循环计数器使用。
 * @member:结构内的hlist_node的名称。
 * /
#定义hlist_for_each_entry_from(TPOS,POS机,会员)\\
    为(; POS&放大器;及({prefetch(POS->下面); 1;})及&放大器; \\
        ({TPOS = hlist_entry(POS的typeof(* TPOS),成员); 1;}); \\
         POS = POS->接下来)/ **
 * hlist_for_each_entry_safe - 迭代对去除列表项的安全特定类型的列表
 * @tpos:类型*为循环计数器使用。
 * @pos:所述&放大器;结构hlist_node作为一个循环计数器使用。
 * @n:另一个与放大器;结构hlist_node用作临时存储
 * @head:头部为你的列表中。
 * @member:结构内的hlist_node的名称。
 * /
#定义hlist_for_each_entry_safe(TPOS,POS,N,头,成员)\\
    对于(POS =(头) - >首先,\\
         POS机和放大器;&安培; ({N = POS->接下来; 1;})及&放大器; \\
        ({TPOS = hlist_entry(POS的typeof(* TPOS),成员); 1;}); \\
         POS = N)
#万一


解决方案

这是我的解决办法:结果

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&fcntl.h GT;
#包括LT&;&signal.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / shm.h>
#定义MAX_SHM_ID_NUM 100typedef结构节点
{
    INT VAL;
    结构节点*接下来的;
}节点;
INT shm_id_arr [MAX_SHM_ID_NUM]
INT CURRENT_INDEX = -1;无效insert_at_tail(INT NUM);
节点* my_head = NULL;
为int * num_of_elements = NULL;的key_t key_first = 5681;
的key_t key_current;无效* my_malloc(INT大小)
{
    无效* PTR = NULL;
    key_current = key_first ++;
    INT shm_id;
    如果((shm_id = shmget的(key_current,大小,IPC_CREAT | 0666))小于0){
        PERROR(shmget的错误。); printf的(错误号=%d个EINVAL =%d个\\ N,错误号,EINVAL);
       返回NULL;
    }    如果((PTR =的shmat(shm_id,NULL,0))==(无效*) - 1){
        PERROR(错误的shmat);
        //出口(1);
        返回NULL;    }
    CURRENT_INDEX ++;
    shm_id_arr [CURRENT_INDEX] = shm_id;
    返回PTR;}无效insert_at_tail(INT NUM)
{
    如果(my_head == NULL)
    {
        my_head = my_malloc(的sizeof(节点));
        my_head-> VAL = NUM​​;
        my_head->接着= NULL;    }其他
    {
        节点* TMP = my_head;
        而(tmp->!下次= NULL)
            TMP = tmp->接下来,
        tmp->接着= my_malloc(的sizeof(节点));
        tmp->下一步 - > VAL = NUM​​;
        tmp->下一步 - >接下来= NULL;
    }
    (* num_of_elements)++;
}
/ * deAttach共享内存而不删除。 * /
无效deattach_shared_mem()
{   如果(shmdt(num_of_elements)小于0){/ * deAttach num_of_elements * /
       PERROR(shmdt错误num_of_elements的\\ n);   }   如果(shmdt(my_head)小于0){
       PERROR(shmdt错误my_head \\ n);
   }
   //如何deattach在列表中的所有指针?
}
无效remove_shared_mem()
{
    INT I;
    对于(i = 0; I< CURRENT_INDEX;我++)
    {
        如果(了shmctl(shm_id_arr [I],IPC_RMID,NULL)小于0){/ *删除共享内存段。 * /
            PERROR(了shmctl错误。\\ n);        }
    }}无效print_it()
{
    节点* TMP = my_head;
    而(TMP!= NULL)
    {
        的printf(%d个\\ N,tmp-> VAL);
        TMP = tmp->接下来,
    }
}诠释的main()
{
    num_of_elements =(INT *)my_malloc(的sizeof(INT));
    (* num_of_elements)= 0;
    insert_at_tail(10);
    insert_at_tail(8);
    insert_at_tail(6);
    insert_at_tail(4);
    insert_at_tail(2);    的printf(我们有%d元素\\ n,(* num_of_elements));    print_it();
    deattach_shared_mem();
    remove_shared_mem();
    返回0;
}

I need to make a shared memory segment that holds nodes using this struct that I made

struct a_list
{
  //The head of the list that acts as a node, this list has a next* and a prev*
  struct list_head list;
  unsigned long*   val;
  char* str;
  char state;
};

I tried looking up answers on stack but they implemented a Node as opposed to my struct, which is a list with nodes inside

I also have this buffer and append method which I used to append to this list (using malloc) but I know that for shared memory I cannot do that

struct buffer
{
    struct a_list* buffer[BUFFER_SIZE];
    int in;
    int out;
};
//Method to append a file to the end of the queue (Most recently used files are at the tail)
static void append(struct a_list* ptr,const char* str, unsigned long val)           
{
  struct a_list* tmp;
  tmp = (struct a_list*)malloc(sizeof(struct a_list));

 // tmp->str = str;
  tmp->str = (char *)malloc(strlen(str)+1);
  strcpy(tmp->str, str);
  tmp->val = (unsigned long*)malloc(sizeof(unsigned long));
  memcpy(tmp->val, &val, sizeof(unsigned long));
  tmp->index = (int *)malloc(sizeof(int));
  memcpy(tmp->index, &buffer_p->in, sizeof(int));
  tmp->address = (struct a_list*)malloc(sizeof(struct a_list*));
  memcpy(tmp->address, &fileQueue, sizeof(struct a_list*));
  if(list_empty(&fileQueue.list)){ //If this is the first element to be inserted into the fileQueue, initialize the head
    list_add_tail( &(tmp->list), &(ptr->list) );
    head = list_entry(fileQueue.list.next,struct a_list, list);
  }
  else{ //Else just add it to the tail of the list
    list_add_tail( &(tmp->list), &(ptr->list) );
  }
 // while(((buffer_p->in+1)%BUFFER_SIZE) == buffer_p->out)
    //      ;

  buffer_p->buffer[buffer_p->in] = tmp->address;
        //printf("Placed: %d\n", counter);

  buffer_p->in = (buffer_p->in+1) % BUFFER_SIZE;
}

and In my main I try to initialize everything with

if ((shmid = shmget(key, (BUFFER_SIZE+2)*sizeof(int), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }

    if ((shm = shmat(shmid, NULL, 0)) < 0) {
        perror("shmat");
        exit(1);
    }

    buffer_p = (struct buffer*) shm;
    buffer_p->in = 0;
    buffer_p->out = 0;

which I don't like how this is working because im making a pointer to something that's been malloc'd (which won't work with shared memory) so I want to change it so that it will actually work with shared memory. I have used Beej's Guide on shared memory as a guide as well as several stack overflow questions but none seem to give me this specific case ( or at least I don't understand the answer). Any help would be appreciated, even if it's just a concept im possibly missing. The list_head struct in the a_list struct (fileQueue) is a struct from a header file referencing the kernel linked list implementation.

EDIT: Here is the list_head struct that's being used in this program, it's basically using the kernel implementation of a list

/**
 * 
 * I grub it from linux kernel source code and fix it for user space
 * program. Of course, this is a GPL licensed header file.
 *
 * Here is a recipe to cook list.h for user space program
 *
 * 1. copy list.h from linux/include/list.h
 * 2. remove 
 *     - #ifdef __KERNE__ and its #endif
 *     - all #include line
 *     - prefetch() and rcu related functions
 * 3. add macro offsetof() and container_of
 *
 * - kazutomo@mcs.anl.gov
 */
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H

/**
 * @name from other kernel headers
 */
/*@{*/

/**
 * Get offset of a member
 */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

/**
 * Casts a member of a structure out to the containing structure
 * @param ptr        the pointer to the member.
 * @param type       the type of the container struct this is embedded in.
 * @param member     the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})
/*@}*/


/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200200)

/**
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */
struct list_head {
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

#define INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}

/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}


/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty on entry does not return true after this, the entry is
 * in an undefined state.
 */
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}



/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list,
                  struct list_head *head)
{
        __list_del(list->prev, list->next);
        list_add_tail(list, head);
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(const struct list_head *head)
{
    return head->next == head;
}

static inline void __list_splice(struct list_head *list,
                 struct list_head *head)
{
    struct list_head *first = list->next;
    struct list_head *last = list->prev;
    struct list_head *at = head->next;

    first->prev = head;
    head->next = first;

    last->next = at;
    at->prev = last;
}

/**
 * list_splice - join two lists
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(struct list_head *list, struct list_head *head)
{
    if (!list_empty(list))
        __list_splice(list, head);
}

/**
 * list_splice_init - join two lists and reinitialise the emptied list.
 * @list: the new list to add.
 * @head: the place to add it in the first list.
 *
 * The list at @list is reinitialised
 */
static inline void list_splice_init(struct list_head *list,
                    struct list_head *head)
{
    if (!list_empty(list)) {
        __list_splice(list, head);
        INIT_LIST_HEAD(list);
    }
}

/**
 * list_entry - get the struct for this entry
 * @ptr:    the &struct list_head pointer.
 * @type:   the type of the struct this is embedded in.
 * @member: the name of the list_struct within the struct.
 */
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

/**
 * list_for_each    -   iterate over a list
 * @pos:    the &struct list_head to use as a loop counter.
 * @head:   the head for your list.
 */

#define list_for_each(pos, head) \
  for (pos = (head)->next; pos != (head);   \
       pos = pos->next)

/**
 * __list_for_each  -   iterate over a list
 * @pos:    the &struct list_head to use as a loop counter.
 * @head:   the head for your list.
 *
 * This variant differs from list_for_each() in that it's the
 * simplest possible list iteration code, no prefetching is done.
 * Use this for code that knows the list to be very short (empty
 * or 1 entry) most of the time.
 */
#define __list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * list_for_each_prev   -   iterate over a list backwards
 * @pos:    the &struct list_head to use as a loop counter.
 * @head:   the head for your list.
 */
#define list_for_each_prev(pos, head) \
    for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
            pos = pos->prev)

/**
 * list_for_each_safe   -   iterate over a list safe against removal of list entry
 * @pos:    the &struct list_head to use as a loop counter.
 * @n:      another &struct list_head to use as temporary storage
 * @head:   the head for your list.
 */
#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

/**
 * list_for_each_entry  -   iterate over list of given type
 * @pos:    the type * to use as a loop counter.
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)              \
    for (pos = list_entry((head)->next, typeof(*pos), member);  \
         pos->member != (head);                 \
         pos = list_entry(pos->member->next, typeof(*pos), member))

/**
 * list_for_each_entry_reverse - iterate backwards over list of given type.
 * @pos:    the type * to use as a loop counter.
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry_reverse(pos, head, member)          \
    for (pos = list_entry((head)->prev, typeof(*pos), member);  \
         &pos->member != (head);    \
         pos = list_entry(pos->member.prev, typeof(*pos), member))

/**
 * list_prepare_entry - prepare a pos entry for use as a start point in
 *          list_for_each_entry_continue
 * @pos:    the type * to use as a start point
 * @head:   the head of the list
 * @member: the name of the list_struct within the struct.
 */
#define list_prepare_entry(pos, head, member) \
    ((pos) ? : list_entry(head, typeof(*pos), member))

/**
 * list_for_each_entry_continue -   iterate over list of given type
 *          continuing after existing point
 * @pos:    the type * to use as a loop counter.
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry_continue(pos, head, member)         \
    for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
         &pos->member != (head);    \
         pos = list_entry(pos->member.next, typeof(*pos), member))

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:    the type * to use as a loop counter.
 * @n:      another type * to use as temporary storage
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)          \
    for (pos = list_entry((head)->next, typeof(*pos), member),  \
        n = list_entry(pos->member.next, typeof(*pos), member); \
         &pos->member != (head);                    \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_continue -  iterate over list of given type
 *          continuing after existing point safe against removal of list entry
 * @pos:    the type * to use as a loop counter.
 * @n:      another type * to use as temporary storage
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe_continue(pos, n, head, member)         \
    for (pos = list_entry(pos->member.next, typeof(*pos), member),      \
        n = list_entry(pos->member.next, typeof(*pos), member);     \
         &pos->member != (head);                        \
         pos = n, n = list_entry(n->member.next, typeof(*n), member))

/**
 * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
 *                    removal of list entry
 * @pos:    the type * to use as a loop counter.
 * @n:      another type * to use as temporary storage
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe_reverse(pos, n, head, member)      \
    for (pos = list_entry((head)->prev, typeof(*pos), member),  \
        n = list_entry(pos->member.prev, typeof(*pos), member); \
         &pos->member != (head);                    \
         pos = n, n = list_entry(n->member.prev, typeof(*n), member))




/*
 * Double linked lists with a single pointer list head.
 * Mostly useful for hash tables where the two pointer list head is
 * too wasteful.
 * You lose the ability to access the tail in O(1).
 */

struct hlist_head {
    struct hlist_node *first;
};

struct hlist_node {
    struct hlist_node *next, **pprev;
};

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)

static inline int hlist_unhashed(const struct hlist_node *h)
{
    return !h->pprev;
}

static inline int hlist_empty(const struct hlist_head *h)
{
    return !h->first;
}

static inline void __hlist_del(struct hlist_node *n)
{
    struct hlist_node *next = n->next;
    struct hlist_node **pprev = n->pprev;
    *pprev = next;
    if (next)
        next->pprev = pprev;
}

static inline void hlist_del(struct hlist_node *n)
{
    __hlist_del(n);
    n->next = LIST_POISON1;
    n->pprev = LIST_POISON2;
}


static inline void hlist_del_init(struct hlist_node *n)
{
    if (n->pprev)  {
        __hlist_del(n);
        INIT_HLIST_NODE(n);
    }
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
    struct hlist_node *first = h->first;
    n->next = first;
    if (first)
        first->pprev = &n->next;
    h->first = n;
    n->pprev = &h->first;
}



/* next must be != NULL */
static inline void hlist_add_before(struct hlist_node *n,
                    struct hlist_node *next)
{
    n->pprev = next->pprev;
    n->next = next;
    next->pprev = &n->next;
    *(n->pprev) = n;
}

static inline void hlist_add_after(struct hlist_node *n,
                    struct hlist_node *next)
{
    next->next = n->next;
    n->next = next;
    next->pprev = &n->next;

    if(next->next)
        next->next->pprev  = &next->next;
}



#define hlist_entry(ptr, type, member) container_of(ptr,type,member)

#define hlist_for_each(pos, head) \
    for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
         pos = pos->next)

#define hlist_for_each_safe(pos, n, head) \
    for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
         pos = n)

/**
 * hlist_for_each_entry - iterate over list of given type
 * @tpos:   the type * to use as a loop counter.
 * @pos:    the &struct hlist_node to use as a loop counter.
 * @head:   the head for your list.
 * @member: the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry(tpos, pos, head, member)            \
    for (pos = (head)->first;                    \
         pos && ({ prefetch(pos->next); 1;}) &&          \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

/**
 * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
 * @tpos:   the type * to use as a loop counter.
 * @pos:    the &struct hlist_node to use as a loop counter.
 * @member: the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_continue(tpos, pos, member)         \
    for (pos = (pos)->next;                      \
         pos && ({ prefetch(pos->next); 1;}) &&          \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

/**
 * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
 * @tpos:   the type * to use as a loop counter.
 * @pos:    the &struct hlist_node to use as a loop counter.
 * @member: the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_from(tpos, pos, member)             \
    for (; pos && ({ prefetch(pos->next); 1;}) &&            \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = pos->next)

/**
 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @tpos:   the type * to use as a loop counter.
 * @pos:    the &struct hlist_node to use as a loop counter.
 * @n:      another &struct hlist_node to use as temporary storage
 * @head:   the head for your list.
 * @member: the name of the hlist_node within the struct.
 */
#define hlist_for_each_entry_safe(tpos, pos, n, head, member)        \
    for (pos = (head)->first;                    \
         pos && ({ n = pos->next; 1; }) &&               \
        ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
         pos = n)


#endif

解决方案

here is my workaround:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/shm.h>
#define MAX_SHM_ID_NUM 100

typedef struct node
{
    int val;
    struct node * next;
} node;
int shm_id_arr[MAX_SHM_ID_NUM];
int current_index = -1 ;

void insert_at_tail (int num);
node * my_head = NULL;
int * num_of_elements = NULL ;

key_t key_first = 5681;
key_t key_current;

void *  my_malloc(int size)
{
    void * ptr = NULL;
    key_current = key_first ++;
    int shm_id;
    if ((shm_id = shmget(key_current, size , IPC_CREAT | 0666)) < 0) {
        perror("shmget error.");printf("errno= %d EINVAL=%d \n ", errno , EINVAL);
       return NULL;
    }

    if ((ptr = shmat(shm_id, NULL, 0)) == (void *) - 1) {
        perror("shmat error");
        //exit(1);
        return NULL;

    }
    current_index ++ ;
    shm_id_arr[current_index] = shm_id ;
    return ptr;

}

void insert_at_tail (int num)
{
    if(my_head == NULL)
    {
        my_head = my_malloc(sizeof(node));
        my_head->val = num;
        my_head->next = NULL;

    }else
    {
        node * tmp = my_head;
        while(tmp->next != NULL)
            tmp = tmp->next;
        tmp->next = my_malloc(sizeof(node));
        tmp->next->val = num;
        tmp->next->next = NULL;
    }
    (* num_of_elements) ++;
}
/* deAttach the shared memory without removing. */
void deattach_shared_mem()
{

   if (shmdt(num_of_elements) < 0) { /*  deAttach  num_of_elements */
       perror("shmdt error num_of_elements\n");

   }

   if (shmdt(my_head) < 0) {
       perror("shmdt error my_head\n");
   }


   //how to deattach all pointers in list?
}
void remove_shared_mem()
{
    int i;
    for(i = 0 ; i < current_index ; i ++)
    {
        if (shmctl(shm_id_arr[i], IPC_RMID, NULL) < 0) { /* remove the shared memory segment. */
            perror("shmctl error.\n");

        }
    }

}

void print_it()
{
    node * tmp = my_head;
    while(tmp != NULL)
    {
        printf("%d\n" , tmp->val);
        tmp = tmp->next;
    }
}

int main()
{
    num_of_elements = (int *)my_malloc(sizeof(int));
    (* num_of_elements) = 0 ;
    insert_at_tail(10);
    insert_at_tail(8);
    insert_at_tail(6);
    insert_at_tail(4);
    insert_at_tail(2);

    printf("we have %d elements.\n" , (*num_of_elements));

    print_it();
    deattach_shared_mem();
    remove_shared_mem();


    return 0 ;
}

这篇关于实现在C的a_list结构(共享内存链表)共享内存段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆