00001 /*! \file shm.c 00002 This file implements basic shared memory utilities. 00003 */ 00004 00005 #include "my_shm.h" 00006 00007 /*! \brief System isentifier for the shared memory segment. This value is set by create_shared_memory_segment() or 00008 get_shared_memory_segment_sys_id(). 00009 */ 00010 static int shm_id = -1; 00011 00012 /*! \brief Address used by the process to access the top of the shared memory segment. This value is set by the function 00013 attache_shared_memory_segment(). 00014 */ 00015 static SHM_addr attachement_address = (SHM_addr)-1; 00016 00017 /*! \brief This variable defines the default permission for all newly created SHM. It can be modified using the function 00018 change_shm_access_permission(). 00019 */ 00020 static int permissions = SHM_PERMISSION; 00021 00022 /*! \brief Data structure that contains information about the shared memory segment (see nam shmctl). 00023 */ 00024 static struct shmid_ds shm_info; 00025 00026 00027 /*! \brief Change the SHM's default permissions. 00028 \param new_permission New permissions to apply to the shared memory (at creation time). 00029 \warning By default the permission is 0x000001C0 (grant all rights for the process' user). 00030 */ 00031 00032 void change_shm_access_permission (int new_permission) 00033 { permissions = new_permission; } 00034 00035 /*! \brief Create the shared memory segment. 00036 \param size Size in bytes of the segment. 00037 \param ipc_key This argument represents the IPC identifier of the shared memory segment. If you know the (well known) 00038 identifier's value, then you can specify it. Otherwise, if you want to let the system choose the first available 00039 identifier, then you should set 'ipc_key' to (key_t)-1. Please note that an IPC identifier is a value greater or 00040 equal to 0. 00041 \return On success, the function may return one of the following values: 00042 <UL> 00043 <li>CREATE_SHM_ALREADY_CREATED: The shared memory segment has already been created. 00044 <li>CREATE_SHM_ERROR: An error occured while creating the segment. 00045 <li>CREATE_SHM_OK: The shared memory segment has been successfully created. 00046 </UL> 00047 Once you called create_shared_memory_segment(), you should call get_shared_memory_segment_id() to get the 00048 system's identifier assigned to the newly created shared memory segment. 00049 */ 00050 00051 int create_shared_memory_segment (key_t ipc_key, int size) 00052 { 00053 /* ===================================================== */ 00054 /* Make sure that 'shm_id' is not already associated */ 00055 /* with a shared memory segment. */ 00056 /* ===================================================== */ 00057 00058 if (shm_id != -1) { return CREATE_SHM_ALREADY_CREATED; } 00059 00060 /* ===================================================== */ 00061 /* Create the shared memory segment */ 00062 /* ===================================================== */ 00063 00064 if (ipc_key == (key_t)-1) { shm_id = shmget (IPC_PRIVATE, size, IPC_CREAT | permissions); } 00065 else { shm_id = shmget (ipc_key, size, IPC_CREAT | permissions); } 00066 00067 if (shm_id == -1) { return CREATE_SHM_ERROR; } 00068 00069 return CREATE_SHM_OK; 00070 } 00071 00072 /*! \example test_shm.c 00073 This example shows how to use the function create_shared_memory_segment(). 00074 */ 00075 00076 /*! \brief Get the system's identifier of a shared memory segment that has already been created (by another process). 00077 \param size Size in bytes of the shared memory segment. 00078 \param ipc_key <b>Well known</b> IPC key that represents the shared memory segment. This key is shared between all 00079 processes that access the shared memory segment. 00080 \return The function may return one of the following value: 00081 <UL> 00082 <li>GET_SHM_ALREADY_GET: You've already got the SHA system's identifier. 00083 <li>GET_SHM_ERROR: An error occured while getting the SHM system's identifier. 00084 <li>GET_SHM_OK: The operation was successful. 00085 </UL> 00086 Once you've called get_shared_memory_segment_sys_id(), you should call get_shared_memory_segment_id() to get the 00087 SHM system's identifier. 00088 \warning If you need to call this function, it means that you want to get the system ID of a SHM that has already been 00089 created by another process. Then you need to specify a <b>well known</b> IPC key. 00090 */ 00091 00092 int get_shared_memory_segment_sys_id (key_t ipc_key, int size) 00093 { 00094 /* ===================================================== */ 00095 /* Make sure that the shared memory segement is not */ 00096 /* already attached. */ 00097 /* ===================================================== */ 00098 00099 if (shm_id != -1) { return GET_SHM_ALREADY_GET; } 00100 00101 /* ===================================================== */ 00102 /* Get the shared memory segment identifier */ 00103 /* ===================================================== */ 00104 00105 shm_id = shmget (ipc_key, size, 0); 00106 00107 if (shm_id == -1) { return GET_SHM_ERROR; } 00108 00109 return GET_SHM_OK; 00110 } 00111 00112 /*! \brief Tell the IPC library to destroy the SHM on the last detachement. 00113 \return Upon successful completion, the function return 0, otherwise it returns -1. 00114 \warning There are 2 very important things to know: 00115 <UL> 00116 <li>This function should be called by the process that has created the SHM. 00117 <li>Once you've called this function, another process can NOT get the shared memory segment (the OS 00118 consider that the segment is ready to be destroyed ... so no more process can get it). Therefore 00119 you must call this function when you are sure that no more process will try to get the shared memory 00120 segment. 00121 </UL> 00122 */ 00123 00124 int set_shm_auto_destroy() 00125 { return shmctl(shm_id, IPC_RMID, NULL); } 00126 00127 /*! \example test_shm.c 00128 This example shows how to use the function get_shared_memory_segment_sys_id(). 00129 */ 00130 00131 /*! \brief Returns the shared memory segment identifier. 00132 \return The function returns the identifier of the shared memory segment. 00133 \warning The identifier should be a value greater or equal to 0. If this function returns -1, it means that an error 00134 occured during the creation of the segment or that the segment has not been created. 00135 */ 00136 00137 int get_shared_memory_segment_id() { return shm_id; } 00138 00139 /*! \example test_shm.c 00140 This example shows how to use the function get_shared_memory_segment_id(). 00141 */ 00142 00143 /*! \brief Returns the address used by the process to access the shared memory segment. 00144 \return The function returns the address used by the process to access the shared memory segment. 00145 */ 00146 00147 SHM_addr get_shm_address() { return attachement_address; } 00148 00149 /*! \example test_shm.c 00150 This example shows how to use the function get_shm_address(). 00151 */ 00152 00153 /*! \brief Attache a previously created shared memory segment. 00154 \return Upon successful completion the function returns the process' address of the memory segment (that is, the address 00155 used by the process to access the memory segment). Otherwise, the function returns (SHM_addr)-1. 00156 */ 00157 00158 SHM_addr attache_shared_memory_segment () 00159 { 00160 attachement_address = shmat(shm_id, (SHM_addr)0, 0); 00161 return attachement_address; 00162 } 00163 00164 /*! \example test_shm.c 00165 This example shows how to use the function attache_shared_memory_segment(). 00166 */ 00167 00168 /*! \brief Return the data structure that describes the Shared Memory Segment (as documented in man shmget). 00169 \return Upon successful completion, the function returns that address of a structure "struct shmid_ds" that 00170 describes the SHM (see man shmctl for details about this structure). If an error occured, then the function 00171 returns NULL. 00172 */ 00173 00174 struct shmid_ds* get_shm_info() 00175 { 00176 if (shmctl (shm_id, IPC_STAT, &shm_info) == -1) 00177 { return NULL; } 00178 00179 return &shm_info; 00180 } 00181 00182 /*! \example test_shm.c 00183 This example shows how to use the function get_shm_info(). 00184 */ 00185 00186 /*! \brief Detache the Shared Memory Segment. 00187 \return If an error occured, the function returns -1. Otherwise, the SHM attachement address is returned. 00188 */ 00189 00190 int detache_shm() 00191 { return shmdt(attachement_address); } 00192