实现在C的a_list结构(共享内存链表)共享内存段 [英] Implement shared memory segment with a_list struct (linked list in shared memory) in C
问题描述
我需要使用此结构,我把持有节点共享内存段
结构的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屋!