Table of contents
1) Obtain a shared storage identifier: shmget function
2) Shared memory mapping (attach): shmat function
3) Detach shared memory mapping (detach): shmdt function
4) Shared memory control: shmctl function
1. Overview of shared memory
Shared memory allows two or more processes to share a given storage area.
Features of shared memory:
1) Shared memory is the fastest way to share data between processes.
When a process writes data to a shared memory area, all processes sharing this memory area can immediately see the contents.
2) What should be noted when using shared memory is the mutual exclusion of access to a given storage area between multiple processes.
If a process is writing data to the shared memory area, other processes should not read or write the data until it completes this operation.
Shared memory diagram:
Shared memory is the most efficient inter-process communication method. The reason is that the process operates directly on the physical memory and maps the physical address to the user process. Therefore, as long as the operation on its address is performed, the physical address is directly operated.
2. Shared memory operations
The shared memory limitations in ubuntu12.04 are as follows:
- Minimum number of bytes in shared memory: 1
- Maximum number of bytes in shared storage area: 32M
- Maximum number of shared memory areas: 4096
- The maximum number of shared storage areas that each process can map: 4096
Use shell commands to operate shared memory:
View shared memory: ipcs -m
Delete shared memory: ipcrm -m shmid
1) Obtain a shared storage identifier: shmget function
shmget function:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
Function: Create a shared memory
parameter:
key: key value, the unique key value determines the unique shared memory
size: the size of the shared memory created
shmflg: shared memory access permissions
Generally IPC_CREAT | 0777
return value:
Success: ID of shared memory
Failure: -1
Code example:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
system("ipcs -m");
return 0;
}
Execution screenshot:
2) Shared memory mapping (attach): shmat function
shmat function:
#include<sys/types.h>
#include<sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
Function: Map shared memory
parameter:
shmid: ID of shared memory
shmaddr: mapped address, set to NULL for automatic allocation by the system
shmflg: flag bit
0: Shared memory has read and write permissions
SHM_RDONLY: read only
return value:
Success: mapped address
Failure: -1
3) Detach shared memory mapping (detach): shmdt function
shmdt function:
#include<sys/types.h>
#include<sys/shm.h>
int shmdt(const void *shmaddr);
Function:
Unmap shared memory
parameter:
shmaddr: mapped address, return value of shmat
return value:
Success: 0
Failure: -1
Shared memory mapping and unmapping code examples:
write.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
//写入
strcpy(text, "hello world");
if (shmdt(text) == -1)
{
perror("fail to text");
exit(1);
}
system("ipcs -m");
return 0;
}
read.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
int main()
{
//创建共享内存
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
// system("ipcs -m");
//映射
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
printf("text = %s\n", text);
//解除映射
if (shmdt(text) == -1)
{
perror("fail to shmdt");
exit;
}
system("ipcs -m");
return 0;
}
Execution screenshot:
4) Shared memory control: shmctl function
shmctl function:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
Function:
Set or get the properties of shared memory
parameter:
shmid: ID of shared memory
cmd: command to perform operations
IPC_STAT Gets the attributes of shared memory
IPC_SET sets the properties of shared memory
IPC_RMID delete shared memory
shmid_ds: attribute structure of shared memory
return value:
Success: 0
Failure: -1
Code example:
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
//删除共享内存
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("fial to shmid");
exit(1);
}
system("ipcs -m");
return 0;
}
Execution screenshot:
Summarize:
As an efficient inter-process communication mechanism, shared memory plays an important role in a multi-process environment with its unique advantages. It allows multiple processes to directly access the same memory area, thereby realizing fast sharing and exchange of data and significantly improving system performance . However, this also brings challenges of data synchronization and concurrency control. We need to combine locks, semaphores and other synchronization technologies to solve these problems.
Overall, shared memory is a powerful and flexible tool, but it needs to be used carefully and effectively to ensure program correctness and stability.