dshm_get(3dshm)


dshm_get -- create/lookup DSHM segment

Synopsis

   #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);

Description

dshm_get creates or looks up a DSHM segment in a manner similar to shmget(2). Key differences between dshm_get and shmget are:

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.

Return values

If successful, dshm_get returns a dshmid.

On failure, dshm_get returns -1 and sets errno to identify the error.

Errors

In the following conditions, dshm_get fails and sets errno to:

EAGAIN
The segment cannot be locked in memory due to insufficient resources.

EINVAL
illegal flag(s) in dshmflgs

EINVAL
The segment exists, and buffer_size is non-zero and not equal to the buffer size of the segment.

EINVAL
The segment does not exist, and buffer_size is not a power of 2.

EINVAL
buffer_size is greater than DSHM_MAX_BUFFER_SIZE.

EINVAL
The segment exists, and buffer_count exceeds the application buffer count for the segment.

EINVAL
The segment does not exist, and dshmaddr is not aligned as required.

EINVAL
The segment exists, and map_size exceeds the map size for the segment.

EINVAL
The segment does not exist, and map size is zero or is not aligned as required.

EINVAL
Temporary attach of newly created segments failed due to address space conflict.

ENOSYS
DSHM is not supported.

EPERM
Caller lacks appropriate privileges to create/lock segment.

EINVAL
size is less than the system-imposed minimum or greater than the system-imposed maximum.

EACCES
A dynamic shared memory identifier exists for key but operation permission (see intro(2)) as specified by the low-order 9 bits of ipcflgs would not be granted.

ENODEV
System is not operating in PAE mode. Large memory must be enabled by specifying the enable_4gb_mem boot parameter.

ENOENT
A dynamic shared memory identifier does not exist for key and (ipcflgs&IPC_CREAT) is false.

ENOSPC
A dynamic shared memory identifier and associated dynamic shared memory segment are to be created, but the system-imposed limit on the maximum number of shared memory segments system-wide, dynamic or otherwise, would be exceeded.

ENOMEM
A dynamic shared memory identifier and associated dynamic shared memory segment are to be created but the amount of available memory is not sufficient to fill the request.

EEXIST
A dynamic shared memory identifier exists for key, but both (ipcflgs&IPC_CREAT) and (ipcflgs&IPC_EXCL) are true.

EINVAL
dshmid is not a valid dynamically mapped shared memory identifier.

EACCES
Operation permission is denied to the calling process.

EMFILE
The number of dynamically mapped shared memory segments attached to the calling process would exceed the system-imposed limit.

Example

The following is an example code fragment for DSHM. dshm_get requires P_PLOCK privilege. Run as root or see filepriv(1M).

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); }

References

dshm_alignment(3dshm), dshm_attach(3dshm), dshm_bufindex(3dshm), dshm_control(3dshm), dshm_detach(3dshm), dshm_map(3dshm), dshm_minmapsize(3dshm), dshm_reattach(3dshm), dshm_unmap(3dshm), dshm_updatetlb(3dshm)
© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 25 April 2004