lkml.org 
[lkml]   [2001]   [Nov]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
Subjectshmat issue.

Is it possible to do a shared memory attach where the attaching address is
an address where a file was mmapped as MAP_SHARED??

I am attaching a testcase that will do this. I was under the impression
that shmat will attach only unmapped memory.

compile the test as cc -oshm_test shm_test.c

Thanks
Manoj

*******************************************************************************
The greatest risk is not taking one.
*******************************************************************************
#include <pthread.h> /* required by pthread functions */
#include <stdio.h> /* required by fprintf() */
#include <stdlib.h> /* required by exit(), atoi() */
#include <string.h> /* required by strncpy() */
#include <unistd.h> /* required by getopt(), mmap() */
#include <sys/types.h> /* required by open(), shmat(), shmdt() */
#include <sys/stat.h> /* required by open() */
#include <sys/ipc.h> /* required by shmat() shmdt(), shmctl() */
#include <sys/shm.h> /* required by shmat() shmdt(), shmctl() */
#include <sys/mman.h> /* required by mmap() */
#include <fcntl.h> /* required by open() */

#define dprt printf

#define REPEAT 100


/******************************************************************************/
/* */
/* Function: usage */
/* */
/* Description: Print the usage message. */
/* */
/* Return: exits with -1 */
/* */
/******************************************************************************/
static void
usage(char *progname) /* name of this program */{
fprintf(stderr,
"Usage: %s -d NUMDIR -f NUMFILES -h -t NUMTHRD\n"
"\t -h Help!\n"
"\t -l Number of repatetions to execute: Default: 1000\n"
"\t -t Number of threads to generate: Default: 30\n",
progname);
exit(-1);
}
/******************************************************************************/
/* */
/* Function: mapfile */
/* */
/* Description: This file creates a file of size equal to multiple of pagesize*/
/* and maps the file into memory. */
/* */
/* Input: map_address - pointer to the address */
/* map_size - pointer to size of the file mapped. */
/* */
/* Output: map_address - contains the address in memory of file mapped. */
/* map_size - contains the size of the file that is mapped. */
/* */
/* Return: exits with -1 on error, 0 on success */
/* */
/******************************************************************************/
static int
mapfile(long **address, /* output parameter - addr of the mapped file*/
int size) /* size of this mapped file */
{
int fd = 0; /* file descriptor of tmp file */
int write_index = 0; /* index to number of 4096 blocks written */
char *filename; /* name of the temporary file */
char buff[4096]; /* buffer that will e written to the file */

memset(buff, 'a', 4096);
filename = (char *)tempnam(".", "tmpfile");
if ((fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0777)) == -1)
{
perror("mapfile(): open()");
return -1;
}
else
{
/* if the program dies prematurely, clean up tempfiles upfront. */
if (unlink(filename) == -1)
{
perror("mapfile(): unlink()");
return -1;
}
}

dprt("pid{%d]: mapfile(): size = %d\n", getpid(), size);
while (write_index < size)
{
write_index += 4096;
if (write(fd, buff, 4096) == -1)
{
perror("mapfile(): write()");
return -1;
}
}

if (fsync(fd) == -1)
{
perror("mkfile(): fsync()");
return -1;
}

if ((*address = (char *)mmap(0, size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == (char *)-1)
{
perror("mapfile(): mmap()");
return -1;
}
dprt("pid{%d]: mapfile(): address = %#x size = %d\n", getpid(),
*address, size);
return 0;
}


/******************************************************************************/
/* */
/* Function: rm_shared_mem */
/* */
/* Description: This function removes the shared segments that were created */
/* This function is called when shmat fails or logical end of */
/* the while loop is reached in do_shmat_shmdt function. */
/* */
/* Input: shm_id - id of the shared memory segment to be removed */
/* shm_addr - address of the shared memory segment to be removed */
/* cmd - remove id only or remove id and detach?? */
/* 0 - remove id dont detach segment. */
/* 1 - remove id and detach segment. */
/* */
/* Output: NONE. */
/* */
/* Return: exits with -1 on error, 0 on success */
/* */
/******************************************************************************/
static int
rm_shared_mem(key_t shm_id, /* id of shared memory segment to be removed */
char *shm_addr, /* address of shared mem seg to be removed */
int cmd) /* remove id only or remove id and detach seg */
{
struct shmid *shmbuf; /* info about the segment pointed by shmkey */

dprt("pid[%d]: rm_shared_mem(): shm_id = %d shm_addr = %#x cmd = %d\n",
getpid(), shm_id, shm_addr, cmd);
if (shmctl(shm_id, IPC_RMID, shmbuf) == -1)
{
dprt("pid[%d]: rm_shared_mem(): shmctl unable to remove shm_id[%d]\n",
getpid(), shm_id);
perror("rm_shared_mem(): shmctl()");
return -1;
}

if (cmd)
{
if (shmdt((void *)shm_addr) == -1)
{
dprt("pid[%d]:rm_shared_mem(): shmdt unable to detach addr = %#x\n",
getpid(), shm_addr);
perror("rm_shared_mem(): shmdt()");
return -1;
}
}
return 0;
}


/******************************************************************************/
/* */
/* Function: do_shmat_shmatd */
/* */
/* Description: This function attaches and detaches the memory */
/* that was mmaped. The size of the file is a multiple of page */
/* size. This function executes as a thread function. */
/* */
/* Input: The argument pointer contains the following. */
/* arg[1] - address of the memory that is to be attached. */
/* arg[2] - size of the memory that is to be attached. */
/* */
/* Return: exits with -1 on error, 0 on success */
/* */
/******************************************************************************/
static int
do_shmat_shmdt(char *mapaddr, /* address of the mem attached. */
int size) /* size of the file mapped. */
{
int shmndx = 0; /* index to the number of attach and detach */
int index = 0; /* index to the number of blocks touched */
key_t shmkey = 0; /* shared memory id */
char *shmat_addr; /* address of the attached memory */

dprt("pid[%d]:do_shmat_shmdt(): mapaddr = %#x, size = %d\n", getpid(),
mapaddr, size);

if ((shmkey = shmget(IPC_PRIVATE, (int)size, IPC_CREAT | 0666 ))
== -1)
{
dprt("pid[%d]: do_shmat_shmdt(): shmget failed\n", getpid());
perror("do_shmat_shmadt(): shmget()");
return -1 ;
}

fprintf(stdout, "pid[%d]: do_shmat_shmdt(): shmget():"
"success got segment id %d\n",
getpid(), shmkey);
dprt("pid[%d]: do_shmat_shmdt(): file mapped at = %#x\n",
getpid(), mapaddr);
if ((shmat_addr = shmat(shmkey, (void *)mapaddr, SHM_RND|SHMLBA))
== (void *)-1)
{
rm_shared_mem(shmkey, shmat_addr, 0);
fprintf(stderr, "pid[%d]: do_shmat_shmadt(): shmat_addr = %#x\n",
getpid(), shmat_addr);
perror("do_shmat_shmadt(): shmat()");
return -1 ;
}
fprintf(stdout,"pid[%d]: do_shmat_shmadt(): shmat success, address = %#x\n",
getpid(), shmat_addr);

if (rm_shared_mem(shmkey, shmat_addr, 1) == -1)
{
fprintf(stderr,
"pid[%d]: do_shmat_shmatd(): rm_shared_mem(): faild to rm id\n",
getpid());
return -1 ;
}

return 0 ;
}


/******************************************************************************/
/* */
/* Function: main */
/* */
/* Description: This is the entry point to the program. This function will */
/* parse the input arguments and set the values accordingly. If */
/* no arguments (or desired) are provided default values are used*/
/* refer the usage function for the arguments that this program */
/* takes. It also creates the threads which do most of the dirty */
/* work. If the threads exits with a value '0' the program exits */
/* with success '0' else it exits with failure '-1'. */
/* */
/* Return: -1 on failure */
/* 0 on success */
/* */
/******************************************************************************/
main(int argc, /* number of input parameters */
char **argv) /* pointer to the command line arguments. */
{
int index; /* number of times to repeat the mmap & shmat */
int map_size; /* size of the file mapped. */
char *map_address; /* address in memory of the mapped file */


for (index = 0; index < REPEAT; index++)
{
srand(time(NULL)%100);
map_size = (1 + (int)(1000.0*rand()/(RAND_MAX+1.0))) * 4096;

if (mapfile(&map_address, map_size) != 0)
{
fprintf(stdout, "main(): mapfile(): failed to map created file\n");
exit (-1);
}

dprt("main(): map_address = %#x map_size = %d\n",map_address, map_size);

if (do_shmat_shmdt(map_address, map_size) == -1)
{
fprintf(stderr, "main(): do_shmat_shmdt(): failed.\n");
exit(-1);
}

}
exit(0);
}
\
 
 \ /
  Last update: 2005-03-22 13:13    [W:0.099 / U:0.040 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site