sshhmmggeett() -- General Function (libc)

Create or get shared-memory segment
#iinncclluuddee <ssyyss/ttyyppeess.hh>
#iinncclluuddee <ssyyss/iippcc.hh>
#iinncclluuddee <ssyyss/sshhmm.hh>
iinntt sshhmmggeett(_m_e_m_k_e_y, _s_i_z_e, _f_l_a_g)
kkeeyy_tt _m_e_m_k_e_y; iinntt _s_i_z_e, _f_l_a_g;

sshhmmggeett() creates a shared-memory identifier, associated data structure, and
shared-memory segment, links them to the identifier _m_e_m_k_e_y, and returns the
shared-memory identifier that it has associated with _m_e_m_k_e_y.

_m_e_m_k_e_y is  an identifier  that your  application generates to  identify its
shared-memory segments.   To guarantee that each key  is unique, you should
use the function call ffttookk() to generate keys.

_s_i_z_e gives the  size, in bytes, of the shared-memory  segment that you want
sshhmmggeett() to create.

_f_l_a_g can be bitwise OR'd to include the following constants:

IIPPCC_AALLLLOOCC This process  already has  a shared-memory segment;  please fetch
          it.

IIPPCC_CCRREEAATT If this  process does not  already have a  shared-memory segment,
          please create one.

IIPPCC_EEXXCCLL  Fail if a shared-memory segment already exists for this process.

IIPPCC_NNOOWWAAIITT
          Fail if the process must wait to obtain a shared-memory segment.

When it  creates a shared-memory  segment, sshhmmggeett() also creates  a copy of
structure sshhmmiidd_ddss, which is  defined in header file <ssyyss/sshhmm.hh>, and which
describes the shared-memory segment.  It is defined as follows:

struct shmid_ds {
     struct ipc_perm               shm_perm;/* operation permission struct */
     int shm_segsz;                /* segment size */
     char *__unused;               /* for binary compatibility */
     char __pad [4];               /* for binary compatibility */
     pid_t shm_lpid;               /* pid of last shmop */
     pid_t shm_cpid;               /* pid of creator */
     unsigned short shm_nattch;    /* current # attached */
     unsigned short shm_cnattach;  /* for binary compatibility */
     time_t shm_atime;             /* last shmat time */
     time_t shm_dtime;             /* last shmdt time */
     time_t shm_ctime;             /* last change time */
};

Field  sshhmm_ppeerrmm  is  a  structure  of  type  iippcc_ppeerrmm,  which  header  file
<ssyyss/iippcc.hh> defines as follows:

struct ipc_perm {
     unsigned short uid;           /* owner's user id */
     unsigned short gid;           /* owner's group id */
     unsigned short cuid;          /* creator's user id */
     unsigned short cgid;          /* creator's group id */
     unsigned short mode;          /* access modes */
     unsigned short seq;           /* slot usage sequence number */
     key_t key;                    /* key */
};

sshhmmggeett() initializes sshhmm_iidd as follows:

-> It   sets  fields   sshhmm_ppeerrmm.gguuiidd,   sshhmm_ppeerrmm.uuiidd,  sshhmm_ppeerrmm.ccggiidd,   and
   sshhmm_ppeerrmm.ggiidd to, respectively, the effective user ID and effective group
   ID of the calling process.

-> It sets the low-order nine  bits of field sshhmm_ppeerrmm.mmooddee to the low-order
   nine bits  of _f_l_a_g. These  nine bits define access  permissions: the top
   three bits  give the owner's access  permissions (read, write, execute),
   the middle three bits the owning group's access permissions, and the low
   three bits access permissions for others.

-> It sets field sshhmm_sseeggsszz equal to _s_i_z_e.

-> It sets  fields sshhmm_aattiimmee, sshhmm_ddttiimmee, sshhmm_llppiidd,  and sshhmm_nnaattttcchh to zero,
   and field sshhmm_ccttiimmee to the current time.

sshhmmggeett() fails if any of the following is true:

-> _s_i_z_e  is smaller  than one  byte,  or larger  than 0x10000  (the system-
   imposed maximum).  sshhmmggeett() sets eerrrrnnoo to EEIINNVVAALL.

-> A  shared-memory  identifier   exists  for  _m_e_m_k_e_y  but  permission,  as
   specified by _f_l_a_g's low-order nine bits, is not granted (EEAACCCCEESS).

-> A  shared-memory  identifier exists  for  _m_e_m_k_e_y, but  the  size of  its
   associated  segment is  less than  _s_i_z_e,  and _s_i_z_e  does not  equal zero
   (EEIINNVVAALL).

-> A  shared-memory  identifier  does not  exist  for  _m_e_m_k_e_y  and (_f_l_a_g  &
   IIPPCC_CCRREEAATT) is false (EENNOOEENNTT).

-> sshhmmggeett() tried to create  a shared-memory segment, but could not because
   100 (the COHERENT-defined maximum) already exist (EENNOOSSPPCC).

-> sshhmmggeett()  tried to  create  a shared-memory  identifier,  but could  not
   because not enough physical memory is available (EENNOOMMEEMM).

-> A shared-memory identifier  already exists for _m_e_m_k_e_y, but _f_l_a_g requests
   that sshhmmggeett() create an exclusive segment it -- i.e.

       ( (_f_l_a_g & IPC_CREAT) && (_f_l_a_g & IPC_EXCL) )

   is true (EEEEXXIISSTT).

If all  goes well,  sshhmmggeett() returns  a shared-memory identifier,  which is
always a non-negative integer.  Otherwise,  it returns -1 and sets eerrrrnnoo to
an appropriate value.

_E_x_a_m_p_l_e
The  following demonstrates  how to  use COHERENT's  shared-memory feature.
Please note that this example will _n_o_t work with versions of COHERENT prior
to release 4.2.

The example  consists of two programs: wwrriitteesshhmm,  which captures input from
the keyboard and writes it into a shared-memory segment; and rreeaaddsshhmm, which
reads and  displays from the  shared-memory segment the  text that wwrriitteesshhmm
put there.  Each program terminates when you type ``end''.

Note that this  example is most effective if you  run each program from its
own virtual console.

The first program gives the source for wwrriitteesshhmm:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

main()
{
    int iShmId; /* Segment id */
    char *cpShm; /* Pointer to the segment */
    key_t key; /* Segment key */

    key = ftok("/etc/passwd", 'S'); /* Get a key */

    /* if a shared-memory segment exists, get it; otherwise, create one */
    if ((iShmId = shmget(key, 256, 0644 | IPC_CREAT)) < 0) {
        perror("get");
        exit(1);
    }

    /* Attach segment to process. Use an attach address of zero to
     * let the system find a correct virtual address to attach.
     */
    if ((cpShm = shmat(iShmId, 0, 0644)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }
    printf("Server is ready.\n");
    printf("Any message to continue, 'end' to exit\n");

    for (;;) {
        printf("Enter the message -> ");
        gets(cpShm);
        if (!strcmp(cpShm, "end")) {
            puts("Bye");
            shmdt(cpShm);   /* Detach segment */
            break;
        }
    }
}

The next program gives the source for rreeaaddsshhmm:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

main()
{
    int iShmId; /* Segment id */
    char *cpShm; /* Pointer to the segment */
    key_t key; /* Segment key */
    char cBuf[16]; /* Read buffer */

    /* Get a key */
    key = ftok("/etc/passwd", 'S');

    /* Get shared memory id. If it does not exist, do *not* create it. */
    if ((iShmId = shmget(key, 256, 0644)) < 0) {
        perror("get");
        exit(1);
    }

    /* attach shared-memory segment to the process */
    if ((cpShm = shmat(iShmId, 0, 0644)) == (char *) -1) {
        perror("shmat");
        exit(1);
    }
    printf("Client is ready\n");

    for (;;) {
        printf("Press enter to read the message -> ");
        gets(cBuf);
        printf("Got: \"%s\"\n", cpShm);

        /* Exit on the 'end': detach and remove segment */
        if (!strcmp(cpShm, "end")) {
            struct shmid_ds stShmId;

            puts("Bye");
            shmdt(cpShm);
            if (shmctl(iShmId, IPC_RMID, &stShmId)) {
                perror("shmctl");
                exit(1);
            }
            break;
        }
    }
}

_F_i_l_e_s
/uussrr/iinncclluuddee/ssyyss/iippcc.hh
/uussrr/iinncclluuddee/ssyyss/sshhmm.hh

_S_e_e _A_l_s_o
ffttookk(), iippccrrmm, iippccss, lliibbcc, lliibbssoocckkeett, sshhmmaatt(), sshhmmccttll(), sshhmmddtt()

_N_o_t_e_s
Prior to  release 4.2, COHERENT  implemented semaphores through  the driver
sshhmm.  In release  4.2, and  subsequent  releases, COHERENT  has implemented
semaphores as  a set of  functions that conform  in large part  to the UNIX
System-V standard.

The kernel variables SSHHMMMMAAXX  and SSHHMMMMNNII set, respectively, the maximum size
of a  shared-memory segment and  the number of  shared-memory segments that
can exist  at any  given time.  Daredevil  system operators who  have large
amounts of memory  at their disposal may wish to  change these variables to
increase the system-defined  limits.  For details on how to  do so, see the
Lexicon entry mmttuunnee.
