K
kalyan
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_memory(key_t shm_key,size_t shm_sz);
void* attach_shared_memory(int shm_id);
void detach_shared_memory(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_memory(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",(unsigned long) shm_key);
fprintf(stderr,"Error occured is \"%s\"\n",strerror(errno));
return -1;
}
}
return shm_id;
}
void* attach_shared_memory(int shm_id)
{
void *mem = shmat(shm_id,NULL,0);
if (mem == (void *) -1) return NULL;
return mem;
}
void detach_shared_memory(const void *mem)
{
shmdt(mem);
}
void destroy_shared_memory(int shm_id)
{
shmctl(shm_id,IPC_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_POINTER(ptr) \
(base < (unsigned char*) (ptr))
unsigned char* base = 0;
static int count = 0;
typedef struct {
int value;
OffsetPtr next;
} IntList;
void InitList(IntList *list);
void InsertHead(IntList *list,int value);
void RemoveHead(IntList *list,int *removedValue);
void DestroyList(IntList *list);
void InitList(IntList *list)
{
if (list == NULL || !list) return;
OFFSET_BASE(list);
list->next = -1;
list->value = 0;
}
void InsertHead(IntList *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(newList);
++count;
}
void RemoveHead(IntList *list,int *removedValue)
{
IntList *node,*nnode;
OffsetPtr next;
if (list == NULL || !list) return;
node = (IntList *) GET_POINTER(list->next);
nnode = (IntList *) GET_POINTER(node->next);
list->next = GET_OFFSET(nnode);
*removedValue = node->value;
node->next = -1;
--count;
}
void DestroyList(IntList *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_memory(1511,4096);
if (shm_id == -1) return -errno;
base = attach_shared_memory(shm_id);
myList = (IntList *) base;
#ifdef PROC1
InitList(myList);
for (i = 0 ; i < 20; i++) {
printf("Inserting :%d\n",(i + 1));
InsertHead(myList,(i + 1));
}
#endif
node = (IntList *) base;
while (node->next)
{
printf("%d ",node->value);
node = (IntList *) GET_POINTER(node->next);
}
printf("\n");
#ifndef PROC1
detach_shared_memory((const void *) base);
#endif
#ifdef PROC1
printf("Press enter key to quit ...");
getchar();
DestroyList(myList);
myList->next = -1;
detach_shared_memory((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_memory(key_t shm_key,size_t shm_sz);
void* attach_shared_memory(int shm_id);
void detach_shared_memory(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_memory(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",(unsigned long) shm_key);
fprintf(stderr,"Error occured is \"%s\"\n",strerror(errno));
return -1;
}
}
return shm_id;
}
void* attach_shared_memory(int shm_id)
{
void *mem = shmat(shm_id,NULL,0);
if (mem == (void *) -1) return NULL;
return mem;
}
void detach_shared_memory(const void *mem)
{
shmdt(mem);
}
void destroy_shared_memory(int shm_id)
{
shmctl(shm_id,IPC_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_POINTER(ptr) \
(base < (unsigned char*) (ptr))
unsigned char* base = 0;
static int count = 0;
typedef struct {
int value;
OffsetPtr next;
} IntList;
void InitList(IntList *list);
void InsertHead(IntList *list,int value);
void RemoveHead(IntList *list,int *removedValue);
void DestroyList(IntList *list);
void InitList(IntList *list)
{
if (list == NULL || !list) return;
OFFSET_BASE(list);
list->next = -1;
list->value = 0;
}
void InsertHead(IntList *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(newList);
++count;
}
void RemoveHead(IntList *list,int *removedValue)
{
IntList *node,*nnode;
OffsetPtr next;
if (list == NULL || !list) return;
node = (IntList *) GET_POINTER(list->next);
nnode = (IntList *) GET_POINTER(node->next);
list->next = GET_OFFSET(nnode);
*removedValue = node->value;
node->next = -1;
--count;
}
void DestroyList(IntList *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_memory(1511,4096);
if (shm_id == -1) return -errno;
base = attach_shared_memory(shm_id);
myList = (IntList *) base;
#ifdef PROC1
InitList(myList);
for (i = 0 ; i < 20; i++) {
printf("Inserting :%d\n",(i + 1));
InsertHead(myList,(i + 1));
}
#endif
node = (IntList *) base;
while (node->next)
{
printf("%d ",node->value);
node = (IntList *) GET_POINTER(node->next);
}
printf("\n");
#ifndef PROC1
detach_shared_memory((const void *) base);
#endif
#ifdef PROC1
printf("Press enter key to quit ...");
getchar();
DestroyList(myList);
myList->next = -1;
detach_shared_memory((const void *) base);
destroy_shared_memory(shm_id);
#endif
return 0;
}