In interprocess communication mode, each IPC object has a unique name, whether it is using message queue, shared memory, or even semaphores, it is called a key ). Through the "key", the process can identify the objects used. The relationship between the "key" and the IPC object is like the file name in the file. Through the file name, the process can read and write data in the file, and even multiple processes can share one file. In IPC communication mode, an IPC object can be shared by multiple processes through the use of keys.
In Linux, the data structure of all ipc objects in system v includes an ipc_perm structure, which contains the key value of the IPC object, this key is used to find the reference identifier of the IPC object in System V. Without the "key", the process cannot access the IPC object because the IPC object does not exist in the memory used by the process itself.
Generally, you want your program to have a unique key value in advance with other programs, but it is not always possible, because your program cannot select a key value for a shared memory. Therefore, set the key to ipc_private. In this way, the operating system will ignore the key, create a new shared memory, specify a key value, and return the ipc id of the shared memory. The ID of the new Shared Memory identifier tells other processes that the shared memory can be created by sending child processes or writing files or pipelines.
To use shared memory, follow these steps:
1. Open up a shared memory shmget ()
2. allow this process to use a shared memory shmat ()
3. Write/read
To delete this memory, follow these steps:
4. prohibit this process from using this shared memory shmdt ()
5. Delete this shared memory shmctl () or ipcrm under the command line
The process uses the following functions:
(1) create a new shared memory area or open an existing shared memory area.
Int shmget (key_t key, int shmsiz, int flag );
Creates a new shared memory area or opens an existing shared memory area.
If the execution succeeds, the ID of the shared memory is returned. If the execution fails, the value-1 is returned.
Key_t key: The identifier of the shared memory. For inter-process communication of the parent-child relationship, this identifier is replaced by ipc_private. If there is no relationship between the two processes, use ftok () to calculate an identifier (or define one by yourself.
Int size: the size of the shared memory.
Int flag: Shared Memory mode and permission ID.
The following values are recommended for the mode:
Ipc_creat new (if it has been created, the ID of the current shared memory is returned)
Ipc_excl and ipc_creat are used in combination. If a file has been created, an error is returned.
Then, the "Mode" and "permission ID" are calculated as "or" and used as the third parameter.
For example, ipc_creat | ipc_excl | 0640
In this example, "0666" indicates the permission ID. "4/2/1" indicates the read, write, and execute permissions respectively. "First 0" indicates the UID, and "first 6" (4 + 2) indicates the permission of the owner, the second 4 indicates the same group permission, and the third 0 indicates the permissions of others.
If you use ipc_creat separately, the shmget () function either returns an existing shared memory operator or a new shared memory identifier.
If ipc_creat and ipc_excl are used together, shmget () returns a new shared memory identifier. If the shared memory already exists,-1 is returned.
The ipc_exel flag does not make much sense, but it can be used with the ipc_creat flag to ensure that the obtained object is newly created, rather than opening an existing object.
Specify shm_r and shm_w, (shm_r> 3) and (shm_w> 3) as a set of read and write permissions for the user's read and write permissions, while (shm_r> 6) and (shm_w> 6) are global read and write permissions.
Note that | 0666 must be added to the parameter for verification. In some Linux systems, if this verification is not added, the shared space value (such as UBUNTU) cannot be obtained smoothly ). In addition, there are two common parameters that usually appear at the same time: s_irush | s_iwusr. Since these two parameters are very common, programmers generally do this operation.
# Define perm s_irusr | s_iwusr | ipc_creat
In this way, the third parameter can be expressed directly using perm!
Return Value
-----------------------------------------------
The identifier of the shared memory is returned. If the shared memory is not returned, the error-1 and errno are returned.
The einval parameter size is smaller than or greater than shmmax.
Shared Memory caused by key pre-created by eexist, but already exists.
The shared memory caused by the eidrm parameter key has been deleted.
Enospc exceeds the maximum (Shmall) shared memory allowed by the system ).
The shared memory specified by the enoent parameter key does not exist, and the ipc_creat bit is not set for the shmflg parameter.
The eacces does not have the permission.
The enomem core memory is insufficient.
I would like to say a few more about this function.
When creating shared memory, the shmflg parameter requires at least ipc_creat | permission ID. If only ipc_creat is used, the requested address is k = 0 xffffffff and cannot be used;
When obtaining the created shared memory, do not use ipc_creat for shmflg (only permission IDs when the shared memory is created, such as 0640). Otherwise, in some cases, for example, if you use ipcrm to delete shared memory, you can use this function and use the ipc_creat parameter to obtain the shared memory once (of course, the acquisition fails), even if you create the shared memory again, in this case, you must change the key to recreate the shared memory.
In addition, all memory allocation operations are in the unit of pages. Therefore, if a process requests only one piece of memory with only one byte, the memory will be allocated a whole page (the default size of one page on the i386 machine is pace_size = 4096 bytes, the size of the newly created shared memory is actually the page size adjusted from the size parameter. That is, if the size is 1 to 4096, the size of the actually applied shared memory is 4 K (one page); 4097 to 8192, the size of the actually applied shared memory is 8 K (two pages), and so on.
(2) return the starting address of the shared memory area in the calling process.
Void * shmat (INT shmid, char * shmaddr, int shmflag );
Used to allow the process to access a shared memory.
If successful, this function returns the starting address of the shared memory. -1 is returned when a failure occurs.
Int shmid: the ID of the shared memory.
Char * shmaddr: the starting address of the shared memory. If shmaddr is 0, the kernel will map the shared memory image to the selected location in the address space of the calling process. If shmaddr is not 0, the kernel will map the shared memory image to the location specified by shmaddr. Therefore, shmaddr is generally set to 0.
Int shmflag: indicates the Memory Operation Mode of the current process. If it is shm_rdonly, it is read-only mode. When the read/write mode is successful, this function returns the starting address of the shared memory. -1 is returned if the request fails.
(3) Delete the memory usage of this process.
Int shmdt (char * shmaddr );
The char * shmaddr parameter is the starting address of the shared memory.
If the call succeeds, 0 is returned. -1 is returned if the request fails.
Appendix: shmdt () is opposite to shmat (). It is a function used to prohibit the process from accessing a shared memory.
When a process no longer needs to share the memory segment, it will call the shmdt () system call to cancel the segment. However, this does not actually Delete the segment from the kernel, instead, the shm_nattch Domain value of the shmid_ds structure is reduced by 1. When this value is 0, the kernel physically deletes this shared segment.
(4) control the use of this shared memory
Int shmctl (INT shmid, int cmd, struct shmid_ds * BUF );
0 is returned for success, and-1 is returned for failure.
Int shmid: the ID of the shared memory.
Int cmd: A control command. The optional values are as follows:
Ipc_stat obtains the shared memory status.
Ipc_set changes the shared memory status
Ipc_rmid: delete shared memory
Struct shmid_ds * Buf: a struct pointer. In ipc_stat, the obtained status is placed in this struct. To change the shared memory status, use this struct.
The ipc_rmid command does not delete a segment from the kernel, but only marks the segment as deleted. The actual deletion occurs when the last process leaves the shared segment.
Please note that the shared memory will not be automatically eliminated as the program ends. You can either call shmctl to delete the shared memory or manually delete it. Otherwise, the shared memory will remain in the system forever.
Q &:
1. The following problems were found during debugging today: two processes that need to communicate use the same string to call ftok to generate a key and call shmget to this key, one of them cannot access the shared memory area. Read unp2 to understand.
Ftok converts an existing path name and an integer identifier into a key_t value.
Key_t ftok (const char * pathname, int proj_id)
Ftok combines three values to generate the key:
1. Information about the file system where the pathname is located.
2. The index node number of the file in the current file system.
3. 8 digits in the low order of the ID.
Key_t generation uses an existing file as the input. It is not a simple string hash function. A file must exist before it can be passed into ftok.
2,
Collected and sorted out some information and made a simple comparison.
|
MMAP system call |
System V shared memory |
Get share Memory ID |
# Include <sys/Mman. h> FD = open (name, flag, mode ); If (FD <0) .... |
# Include <sys/IPC. h> # Include <sys/SHM. h> Int shmget (key_t key, size_t size, int shmflg ); |
Ing memory |
PTR = MMAP (null, Len, prot_read | prot_write, Map_shared, FD, 0 ); |
Void * shmat (INT shmid, char * shmaddr, int shmflag ); |
Unmap |
Int munmap (void * ADDR, size_t Len ); |
Int shmdt (char * shmaddr ); The ing memory in the process is invalid and cannot be used. But reserved space |
Others |
Synchronization: Int msync (void * ADDR, size_t Len, int flags ); |
Control: Shmctl (shmid, ipc_stat, & BUF ); // Obtain the shared memory status Shmctl (shmid, ipc_rmid, & BUF ); // Delete shared memory-delete shared memory, completely unavailable, and release space |