|
|
#include <dshm.h>int dshm_get(
key_t
key,size_t
buffer_size, unsigned long buffer_count, const void* dshmaddr,size_t
map_size, int ipcflgs, int dshmflgs);
If DSHM_FORCE_UNMAP is set in dshmflgs upon segment creation, the segment will operate in a special debugging mode where all mappings are aggressively destroyed when their reference counts go to zero. This mode can expose application bugs where stale copies of buffer pointers are used.
It is possible for a signal to terminate dshm_get between the creation of a segment by the kernel and its initialization by the library. If this occurs, subsequent attempts to attach the segment will return an error (EBUSY), and the application must remove and recreate the segment.
On failure, dshm_get returns -1 and sets errno to identify the error.
Before running the example, enable PAE mode by setting the boot parameter enable_4gb_mem=y in /stand/boot.
* Copyright 1997 The Santa Cruz Operation, Inc. All Rights Reserved. */ /* * program creates a dynamic shared memory segment * maps each dshm buffer and reads data into it */#include <dshm.h> #include <fcntl.h> #include <signal.h> #include <errno.h> #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/stat.h>
#define GIG 0x40000000 #define BSZ 4096 #define NBS 32
/* * define to a real raw disk slice * WARNING all data on the slice will be overwritten * slice size must be >= BSZ * NBS bytes */ #define SCRATCH_SLICE "/dev/rdsk/c0b0t0d0XX"
int fd; int dshmid, shmid; unsigned long mp; long kalignment; dshm_handle_t dh;
typedef struct { void *bufp; } bufhdr_t;
bufhdr_t *bhp;
main() { int i;
/* * get shared mem for shared buffer pointers to reside in * * Note in a real app, this would be shared with other * processes. */ if ((shmid = shmget(IPC_PRIVATE, NBS * sizeof(bufhdr_t), IPC_CREAT))==-1){ perror("shmget"); exit(1); }
/* * attach shared buffer pointers */ if ((bhp = (bufhdr_t *)shmat(shmid, 0, 0)) == (bufhdr_t *)-1){ perror("shmat"); shmctl(shmid, IPC_RMID, NULL); exit(1); }
for (i = 0; i < NBS; i++) { /* * initialise shared buffer pointer */ bhp[i].bufp = (void *)DSHM_NULL; }
/* * map size & map address must be a multiple of * the value returned by dshm_alignment. */ kalignment = dshm_alignment();
if ((dshmid = dshm_get(IPC_PRIVATE, /* key */ BSZ, /* buf size */ NBS, /* num of buffers */ (void*)GIG, /* map addr */ kalignment, /* map size */ IPC_CREAT | IPC_PERM, DSHM_FORCE_UNMAP)) == -1 ){ perror("dshmget"); shmctl(shmid, IPC_RMID, NULL); exit(1); }
/* * attach dshm segment * Note map address specified in dshm_get above */ if ((dh = dshm_attach(dshmid, 0, &mp)) == (dshm_handle_t)-1) { perror("dshmat"); dshm_control(dshmid, IPC_RMID, NULL); shmctl(shmid, IPC_RMID, NULL); exit(1); }
/* * max mappings set by dshm_attach is * the maximum number of concurrent mappings * by all users without deadlocking */ printf("%d: max mappings %d\n",getpid(), mp); /* open the raw disk file */ if ((fd = open(SCRATCH_SLICE, O_RDWR))==-1){ perror("open"); shmctl(shmid, IPC_RMID, NULL); dshm_control(dshmid, IPC_RMID, NULL); exit(1); }
/* * fill device with known data */ for (i = 0; i < NBS; i++) { uchar_t k[BSZ];
memset(k,i,sizeof(k));
if (write(fd, k, sizeof(k)) != sizeof(k)){ perror("write"); shmctl(shmid, IPC_RMID, NULL); dshm_control(dshmid, IPC_RMID, NULL); exit(1); } }
/* * fill buffers with data */ for (i = 0;i < NBS; i++) { /* * map buffer i * system chooses a user virtual address in which * to map the buffer & returns the address thru * the buffer pointer pointer. * on return bhp[i].bufp == address buffer mapped at. */ if (dshm_map(dh, i, (const void **)&bhp[i].bufp) == -1) { perror("dshm_map"); dshm_control(dshmid, IPC_RMID, NULL); shmctl(shmid, IPC_RMID, NULL); exit(1); }
pread(fd, bhp[i].bufp, BSZ, BSZ * i); /* * we're done with the buffer * unmap it. */ if(dshm_unmap(dh, (void *)bhp[i].bufp) == -1) { perror("dshm_unmap"); dshm_control(dshmid, IPC_RMID, NULL); shmctl(shmid, IPC_RMID, NULL); exit(1); } }
dshm_detach(dh); shmdt(bhp);
dshm_control(dshmid, IPC_RMID, NULL); shmctl(shmid, IPC_RMID, NULL);
close(fd);
exit(0); }