Linux inter-process communication (IPC) Programming Practice (7) use of shared memory-System V shared memory (API)
The system call mmap mentioned in the previous blog map a common file to implement shared memory. The System V shared memory described in this article is to map files in the shm of a special file System to implement shared memory communication between processes. That is to say, each shared memory area corresponds to a file in the shm of the special file system. The shmget is called before shmat. For each shared memory area, the kernel maintains the following information structure, which is defined in Header file.
// System V shared memory Basic Data Structure struct shmid_ds {struct ipc_perm shm_perm;/* Ownership and permissions: Data Structure shared by System v ipc */size_t shm_segsz; /* Size of segment (bytes): Size of the shared memory segment */time_t shm_atime;/* Last attach time */time_t shm_dtime;/* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid;/* PID of creator */pid_t shm_lpid;/* PID of last shmat (2)/shmdt (2) */shmatt_t shm_nattch; /* No. of current attaches */...};
Common System V shared memory APIs
# Include
# Include
/* Create a new memory shared area or access an existing shared memory area and return the shared memory area identifier */int shmget (key_t key, size_t size, int shmflg ); /* after creating or opening a shared memory area, call shmat to connect it to the address space of the calling process */void * shmat (int shmid, const void * shmaddr, int shmflg ); /*
When a process completes the use of a shared memory area, call shmdt to disconnect this memory area */int shmdt (const void * shmaddr);/* perform multiple operations on the memory area. cmd values: IPC_RMID: deletes the shared memory area identified by shmid from the system and removes it. IPC_SET: sets IPC_STAT as the shmid_ds result Member for the specified shared memory area: the buff parameter is used to return the current shmid_ds structure */int shmctl (int shmid, int cmd, struct shmid_ds * buf) of the specified shared memory area to the caller );
Call the shmget function to create a shared memory zone with the specified path name and length, as shown below:
int shmget(key_t key, size_t size, int shmflg);
Create shared memory and initialize the content of the memory to 0;
Open an existing shared memory. If you do not know the size of the shared memory, you can set the size to 0 and the shmflg to 0 (based on the default permission );
Parameters:
Key: the name of the shared memory segment;
Size: the size of the shared memory (bytes );
Shmflg: similar to the msgflg parameter in msgget;
Return Value:
A non-negative integer is returned, that is, the ID code of the shared memory segment;-1 is returned if a failure occurs.
/** Example: Create and open a shared memory **/int main (int argc, char ** argv) {const int SHM_SIZE = 1024; int shmid = shmget (0x1234, SHM_SIZE, 0666 | IPC_CREAT); if (shmid =-1) err_exit ("shmget error "); cout <"share memory get success" <endl ;}
Shmat
void *shmat(int shmid, const void *shmaddr, int shmflg);
Connect to the address space of the process. After the connection is successful, the operation on the memory is very similar to the memory of malloc. If there is data in the memory, then you can directly extract the data.
Parameters:
Shmaddr: Specifies the connection address (NULL is recommended if the connection size is unknown)
Shmflg: It is generally set to 0, which indicates readable and writable. The other two values of SHM_RND and SHM_RDONLY may be used (see below)
Return Value:
A pointer is returned, pointing to the starting address of the shared memory. If the pointer fails, return (void *)-1.
Description of shmaddr and shmflg combinations |
Shmaddr is NULL. |
Linux Kernel automatically connects processes to the memory (recommended) |
Shmaddr is not NULL and shmflg is not marked with SHM_RND |
Use shmaddr as the connection address |
Shmaddr is not NULL and SHM_RND flag is set for shmflg |
The connected address is automatically adjusted down to an integer multiple of SHMLBA; Formula: shmaddr-(shmaddr % SHMLBA) SHMLBA is the memory page size (4 K) |
Shmflg = SHM_RDONLY |
Read-Only shared memory. Otherwise, it is readable and writable. Note: This concept is not readable. |
Shmdt
When a process completes the use of a shared memory area, call shmdt to disconnect the memory area:
int shmdt(const void *shmaddr);
Parameters:
Shmaddr: pointer returned by shmat
Note: removing the shared memory segment from the current process is not equal to deleting the shared memory segment.
/** Example: write/read data to/from the shared memory program write: write data to the shared memory program read: read data to the shared memory (of course, you can read N times) ** // write Program struct Student {char name [26]; int age ;}; int main (int argc, char ** argv) {int shmid = shmget (0x1234, sizeof (Student), 0666 | IPC_CREAT); if (shmid =-1) err_exit ("shmget error "); // connect the shared memory Student * p = (Student *) shmat (shmid, NULL, 0); if (p = (void *) -1) err_exit ("shmat error"); strcpy (p-> name, "xiaofang"); p-> age = 22; shmdt (p );}
// Read program int main (int argc, char ** argv) {int shmid = shmget (0x1234, 0, 0); if (shmid =-1) err_exit ("shmget error"); // read-only connection to the shared memory Student * p = (Student *) shmat (shmid, NULL, 0 ); if (p = (void *)-1) err_exit ("shmat error"); // print the content directly to the output cout <"name: "<p-> name <", age: "<p-> age <endl; shmdt (p );}
Shmctl
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Set/obtain shared memory attributes
Parameters:
Cmd: action to be taken (see the following for the three values)
Buf: indicates a data structure that stores the mode status and access permissions of the shared memory.
IPC_RMID: deletes the shared memory area identified by shmid from the system and removes it. IPC_SET: sets IPC_STAT as the shmid_ds result Member for the specified shared memory area: the buff parameter is used to return the current shmid_ds structure of the specified shared memory area to the caller.
System V shared memory summary:
1) if the shared memory has been disconnected from all the processes that access it, the system will immediately delete the identifier of the shared memory and delete the shared memory after the IPC_RMID subcommand is called, and all relevant data structures;
2) if another process is still connected to the shared memory, after the IPC_RMID sub-command is called, the shared memory will not be immediately deleted from the system, but is set to IPC_PRIVATE, and marked as "deleted" (you can see the dest field using the ipcs command). The shared memory will not disappear from the system until all existing connections are disconnected.
3) In addition, once the shared memory is deleted through shmctl, the shared memory will no longer accept any new connections, even if it still exists in the system! Therefore, it is clear that it is safe to delete a new connection after the shared memory is deleted. Otherwise, if a new connection still occurs after the delete operation, all these connections may fail.
/** Example: delete shared memory **/int main (int argc, char * argv []) {int shmid = shmget (0x1234, 0, 0 ); if (shmid =-1) err_exit ("shmget error"); if (shmctl (shmid, IPC_RMID, NULL) =-1) err_exit ("shmctl IPC_RMID error "); cout <"share memory remove success" <endl ;}