Hi,
I am using Linux + SysV Shared memory (sorry, but my question is all
about offset + pointers and not about linux/IPC) and hence use
offset's instead on pointers to store the linked list in the shared
memory. I run fedora 9 and gcc 4.2. I am able to insert values in to
the list, remove values from the list, but the problem is in
traversing the list. Atlease one or 2 list nodes disappear when
traversing from the base of the list or the shared memory.
PS: Don't get carried away because of PROC1 macro. It's just used to
compile the same code to two different processes one that creates,
inserts & destroys the list & creates & destroys shared memory & the
other one simply attaches to the shared memory and traverses the
linked list created by the process that is compiled using PROC1 macro
defined. So to compile:
gcc -g -O -D PROC1 proc1 shlist.c
gcc -g -O -o proc2 shlist.c
now proc1 creates shared memory & destroys it and also creates &
destroys linked list. Where as proc2 just attaches (and detaches
finally) to shared memory and just traverses the list and prints the
value in each list element.
Thanks.
Kalyan
Below is the complete code (shlist.c) :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
int open_shared_mem ory(key_t shm_key,size_t shm_sz);
void* attach_shared_m emory(int shm_id);
void detach_shared_m emory(const void *mem);
void destroy_shared_ memory(int shm_id);
#define SHMEM_CREAT (IPC_CREAT|IPC_ EXCL|0644)
#define SHMEM_OPEN (IPC_CREAT|0644 )
int open_shared_mem ory(key_t shm_key,size_t shm_sz)
{
size_t shm_size = 1024;
int shm_id = -2; /*some invalid id number*/
if (shm_key == IPC_PRIVATE) abort();
if (shm_sz < 1024) {
fprintf(stderr, "Warning: Shared memory size is defaulted to 1024
bytes\n");
} else {
shm_size = shm_sz;
}
shm_id = shmget(shm_key, shm_size,SHMEM_ CREAT);
if (shm_id == -1) {
shm_id = shmget(shm_key, shm_size,SHMEM_ OPEN);
if (shm_id == -1) {
fprintf(stderr, "Unable to create/open shared memory with key value:
%lu\n",(unsigne d long) shm_key);
fprintf(stderr, "Error occured is \"%s\"\n",strer ror(errno));
return -1;
}
}
return shm_id;
}
void* attach_shared_m emory(int shm_id)
{
void *mem = shmat(shm_id,NU LL,0);
if (mem == (void *) -1) return NULL;
return mem;
}
void detach_shared_m emory(const void *mem)
{
shmdt(mem);
}
void destroy_shared_ memory(int shm_id)
{
shmctl(shm_id,I PC_RMID,(struct shmid_ds *) 0);
}
typedef long OffsetPtr;
extern unsigned char* base;
#define OFFSET_BASE(ptr ) \
if (ptr != NULL) base = (unsigned char*) ptr;
#define GET_OFFSET(ptr) \
((long) ((unsigned char*) ptr - base))
#define GET_POINTER(off ) \
((void*) (base + off))
#define IS_VALID_POINTE R(ptr) \
(base < (unsigned char*) (ptr))
unsigned char* base = 0;
static int count = 0;
typedef struct {
int value;
OffsetPtr next;
} IntList;
void InitList(IntLis t *list);
void InsertHead(IntL ist *list,int value);
void RemoveHead(IntL ist *list,int *removedValue);
void DestroyList(Int List *list);
void InitList(IntLis t *list)
{
if (list == NULL || !list) return;
OFFSET_BASE(lis t);
list->next = -1;
list->value = 0;
}
void InsertHead(IntL ist *list,int value)
{
IntList *newList,*nnode ;
if (list == NULL || !list) abort();
newList = (IntList *) (base + (count *sizeof(IntList )));
if (!newList || newList == NULL)
abort();
newList->value = value;
if (list->next == -1) newList->next = -1;
else newList->next = list->next;
list->next = GET_OFFSET(newL ist);
++count;
}
void RemoveHead(IntL ist *list,int *removedValue)
{
IntList *node,*nnode;
OffsetPtr next;
if (list == NULL || !list) return;
node = (IntList *) GET_POINTER(lis t->next);
nnode = (IntList *) GET_POINTER(nod e->next);
list->next = GET_OFFSET(nnod e);
*removedValue = node->value;
node->next = -1;
--count;
}
void DestroyList(Int List *list)
{
int val;
while (list->next != -1)
{
RemoveHead(list ,&val);
printf("Removed : %d\n",val);
}
list->next = -1;
}
int main(void)
{
IntList *myList;
IntList *node;
int i,val,shm_id;
shm_id = open_shared_mem ory(1511,4096);
if (shm_id == -1) return -errno;
base = attach_shared_m emory(shm_id);
myList = (IntList *) base;
#ifdef PROC1
InitList(myList );
for (i = 0 ; i < 20; i++) {
printf("Inserti ng :%d\n",(i + 1));
InsertHead(myLi st,(i + 1));
}
#endif
node = (IntList *) base;
while (node->next)
{
printf("%d ",node->value);
node = (IntList *) GET_POINTER(nod e->next);
}
printf("\n");
#ifndef PROC1
detach_shared_m emory((const void *) base);
#endif
#ifdef PROC1
printf("Press enter key to quit ...");
getchar();
DestroyList(myL ist);
myList->next = -1;
detach_shared_m emory((const void *) base);
destroy_shared_ memory(shm_id);
#endif
return 0;
}
I am using Linux + SysV Shared memory (sorry, but my question is all
about offset + pointers and not about linux/IPC) and hence use
offset's instead on pointers to store the linked list in the shared
memory. I run fedora 9 and gcc 4.2. I am able to insert values in to
the list, remove values from the list, but the problem is in
traversing the list. Atlease one or 2 list nodes disappear when
traversing from the base of the list or the shared memory.
PS: Don't get carried away because of PROC1 macro. It's just used to
compile the same code to two different processes one that creates,
inserts & destroys the list & creates & destroys shared memory & the
other one simply attaches to the shared memory and traverses the
linked list created by the process that is compiled using PROC1 macro
defined. So to compile:
gcc -g -O -D PROC1 proc1 shlist.c
gcc -g -O -o proc2 shlist.c
now proc1 creates shared memory & destroys it and also creates &
destroys linked list. Where as proc2 just attaches (and detaches
finally) to shared memory and just traverses the list and prints the
value in each list element.
Thanks.
Kalyan
Below is the complete code (shlist.c) :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
int open_shared_mem ory(key_t shm_key,size_t shm_sz);
void* attach_shared_m emory(int shm_id);
void detach_shared_m emory(const void *mem);
void destroy_shared_ memory(int shm_id);
#define SHMEM_CREAT (IPC_CREAT|IPC_ EXCL|0644)
#define SHMEM_OPEN (IPC_CREAT|0644 )
int open_shared_mem ory(key_t shm_key,size_t shm_sz)
{
size_t shm_size = 1024;
int shm_id = -2; /*some invalid id number*/
if (shm_key == IPC_PRIVATE) abort();
if (shm_sz < 1024) {
fprintf(stderr, "Warning: Shared memory size is defaulted to 1024
bytes\n");
} else {
shm_size = shm_sz;
}
shm_id = shmget(shm_key, shm_size,SHMEM_ CREAT);
if (shm_id == -1) {
shm_id = shmget(shm_key, shm_size,SHMEM_ OPEN);
if (shm_id == -1) {
fprintf(stderr, "Unable to create/open shared memory with key value:
%lu\n",(unsigne d long) shm_key);
fprintf(stderr, "Error occured is \"%s\"\n",strer ror(errno));
return -1;
}
}
return shm_id;
}
void* attach_shared_m emory(int shm_id)
{
void *mem = shmat(shm_id,NU LL,0);
if (mem == (void *) -1) return NULL;
return mem;
}
void detach_shared_m emory(const void *mem)
{
shmdt(mem);
}
void destroy_shared_ memory(int shm_id)
{
shmctl(shm_id,I PC_RMID,(struct shmid_ds *) 0);
}
typedef long OffsetPtr;
extern unsigned char* base;
#define OFFSET_BASE(ptr ) \
if (ptr != NULL) base = (unsigned char*) ptr;
#define GET_OFFSET(ptr) \
((long) ((unsigned char*) ptr - base))
#define GET_POINTER(off ) \
((void*) (base + off))
#define IS_VALID_POINTE R(ptr) \
(base < (unsigned char*) (ptr))
unsigned char* base = 0;
static int count = 0;
typedef struct {
int value;
OffsetPtr next;
} IntList;
void InitList(IntLis t *list);
void InsertHead(IntL ist *list,int value);
void RemoveHead(IntL ist *list,int *removedValue);
void DestroyList(Int List *list);
void InitList(IntLis t *list)
{
if (list == NULL || !list) return;
OFFSET_BASE(lis t);
list->next = -1;
list->value = 0;
}
void InsertHead(IntL ist *list,int value)
{
IntList *newList,*nnode ;
if (list == NULL || !list) abort();
newList = (IntList *) (base + (count *sizeof(IntList )));
if (!newList || newList == NULL)
abort();
newList->value = value;
if (list->next == -1) newList->next = -1;
else newList->next = list->next;
list->next = GET_OFFSET(newL ist);
++count;
}
void RemoveHead(IntL ist *list,int *removedValue)
{
IntList *node,*nnode;
OffsetPtr next;
if (list == NULL || !list) return;
node = (IntList *) GET_POINTER(lis t->next);
nnode = (IntList *) GET_POINTER(nod e->next);
list->next = GET_OFFSET(nnod e);
*removedValue = node->value;
node->next = -1;
--count;
}
void DestroyList(Int List *list)
{
int val;
while (list->next != -1)
{
RemoveHead(list ,&val);
printf("Removed : %d\n",val);
}
list->next = -1;
}
int main(void)
{
IntList *myList;
IntList *node;
int i,val,shm_id;
shm_id = open_shared_mem ory(1511,4096);
if (shm_id == -1) return -errno;
base = attach_shared_m emory(shm_id);
myList = (IntList *) base;
#ifdef PROC1
InitList(myList );
for (i = 0 ; i < 20; i++) {
printf("Inserti ng :%d\n",(i + 1));
InsertHead(myLi st,(i + 1));
}
#endif
node = (IntList *) base;
while (node->next)
{
printf("%d ",node->value);
node = (IntList *) GET_POINTER(nod e->next);
}
printf("\n");
#ifndef PROC1
detach_shared_m emory((const void *) base);
#endif
#ifdef PROC1
printf("Press enter key to quit ...");
getchar();
DestroyList(myL ist);
myList->next = -1;
detach_shared_m emory((const void *) base);
destroy_shared_ memory(shm_id);
#endif
return 0;
}
Comment