[Linux]system V shared memory
Article directory
Shared memory is an inter-process communication method under Linux system, which complies with the system V standard. The communication method interfaces under the System V standard are similar in usage, including three communication mechanisms: semaphore, shared memory and message queue.
The principle of shared memory communication
Shared memory is a space applied for by the operating system in the memory. The process maps the memory to the shared area of its own process address space, and then writes or reads data to the shared memory through this mapping to complete inter-process communication.
After completing the communication, the process must first unmap the relationship and then let the operating system release the shared memory.
System interface
Create shared memory interface
The Linux system provides shmget
an interface for creating shared memory:
//shmget所在的头文件和声明
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
- The shared memory number is returned successfully
shmid
, -1 is returned on failure, and the error code is set.
key parameter
Shared memory is a memory space that the operating system applies for in the memory. There may be a large amount of shared memory in the operating system. In order to manage these shared memories, the operating system must use corresponding structures to describe them, and then organize the described structures to share them. There is a field in the memory that uniquely identifies the shared memory. This field uses key参数
the value passed in. Before processes use shared memory to communicate, one process creates a shared memory and key参数
writes it, and then another process that wants to communicate with it uses the same method to compare it key参数
with the shared memory description structure in the operating system to find the corresponding share. key参数
memory to communicate.
In order to make the parameters used key
unique and ensure that the shared memory used by the process does not go wrong, we use ftok
the system interface:
//ftok所在的头文件和声明
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
ftok
An algorithm will be used to return a number with a very low repetition rate based on the parameters passed in.- Returns 0 on success, -1 on failure, and the error code is set.
size parameter
size参数
Used to specify the size of the shared memory to be created, in bytes.
The operating system creates shared memory page页
in units of 4KB.
shmflg parameters
shmflg参数
Used to indicate shmget
the usage pattern.
IPC_CREAT
: Create a shared memory. If the shared memory does not exist, create it. If it already exists, get the existing shared memory and return it.IPC_EXCL
It cannot be used alone and must be used in combinationIPC_CREAT
.IPC_CREAT | IPC_EXCL
: Create a shared memory. If the shared memory does not exist, create it. If it already exists, an error will be returned immediately - if the creation is successful, the corresponding shm must be the latest!- Passing in
umask
can set permissions for the shared memory to be created.
Associative shared memory interface
To use shared memory, you must associate shared memory and map the shared memory to your own process address space. The Linux system provides shmat
an interface for associating shared memory:
//shmat所在的头文件和声明
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid parameter – used to indicate the shared memory number to be associated.
- The shmaddr parameter – specifies the address to be associated. If you pass in a null pointer, the operating system will perform the association itself.
- The shmflg parameter – indicates the permissions on the shared memory to be associated. Pass in 0 for read and write permissions.
- The address of the shared memory mapped in the process address space is returned successfully, -1 is returned if failed, and the error code is set.
De-associate shared memory interface
After using the shared memory for communication, the shared memory must be disassociated. The Linux system provides shmdt
an interface for deassociating shared memory:
//shmdt所在的头文件和声明
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
- shmaddr parameter – the address of the shared memory to be associated, that is,
shmat
the address returned when the associated shared memory is called. - Returns 0 on success, -1 on failure, and the error code is set.
Delete shared memory interface
The Linux system provides shmctl
an interface for controlling shared memory:
//shmctl所在的头文件和声明
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- shmid parameter – used to indicate the shared memory number to be controlled.
- cmd parameter – used to specify control options, where
IPC_RMID
the option is to delete shared memory. - buf parameter – output parameter, used to receive structure information describing shared memory.
Use instructions to operate shared memory
View shared memory
Use this in a Linux system ipcs -m
to view the shared memory in the system:
key
:shmget
Passed in when the process calls to create shared memorykey参数
.shmid
: Shared memory number.owner
: The owner of the shared memory.perms
: The owner's permissions on shared memory.bytes
: The size of shared memory.
Delete shared memory
Use in Linux systems ipcrm -m 对应shmid
to delete the corresponding shared memory:
Shared memory features
- No extra copies required: Shared memory communication does not require the use of any interface. As long as the shared memory is mapped into the process's address space, the process can see the shared memory.
- Fast: Shared memory is mapped into the address space of the process, and the process can see the shared memory. No buffers are involved, and no redundant copying is required, so shared memory communication is very fast.
- No protection: Communication using shared memory does not require the use of any interface, so there is no protection mechanism for shared memory.
Coding test shared memory
Before coding to test shared memory, create three files: common.hpp
, server.cc
, client.cc
.
common.hpp
Used to implement classes and interfaces that use shared memory, the specific contents are as follows:
#ifndef __COMN_HPP__
#define __COMM_HPP__
#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdio>
#include <cerrno>
#include <cstring>
#include <cassert>
#include <unistd.h>
using namespace std;
#define PATHNAME "."
#define PROJID 0x6666
#define gsize 4096
//key_t类型实际也是int类型
key_t GetKey()//获取key值
{
key_t k = ftok(PATHNAME, PROJID);
if(k == -1)//错误检测
{
cerr << "errno: " << errno << " strerror: " << strerror(errno) << endl;
exit(1);
}
return k;
}
//只在本文件生效
static int createShmHelper(key_t key, size_t size, int shmflg)
{
int shmid = shmget(key, size, shmflg);
if(shmid == -1)//错误检测
{
cerr << "errno: " << errno << " strerror: " << strerror(errno) << endl;
exit(2);
}
return shmid;
}
int createShm(key_t k, int size)
{
umask(0);
return createShmHelper(k, size, IPC_CREAT | IPC_EXCL | 0666);
}
int getShm(key_t k, int size)
{
return createShmHelper(k, size, IPC_CREAT);
}
void* attachShm(int shmid)
{
void* start = shmat(shmid, NULL, 0);
return start;
}
void detachShm(void* start)
{
int n = shmdt(start);
assert(n != -1);
(void)n;
}
void delShm(int shmid)
{
int n = shmctl(shmid, IPC_RMID, nullptr);
assert(n != -1);
(void)n;
}
#define SERVER 1
#define CLIENT 0
class Shm
{
public:
Shm(int type):_type(type)
{
key_t key = GetKey();
if (_type == SERVER) _shmid = createShm(key, gsize);
else _shmid = getShm(key, gsize);
_start = attachShm(_shmid);
}
void* getStart()
{
return _start;
}
~Shm()
{
detachShm(_start);
if (_type == SERVER) delShm(_shmid);
}
private:
void* _start;
int _shmid;
int _type;
};
#endif
server.cc
Used to create shared memory, read data in shared memory, and complete the release of shared memory. The specific content is as follows:
#include "common.hpp"
int main()
{
Shm shm(SERVER);
char* start = (char*)shm.getStart();
int n = 0;
while(n < 30)
{
cout << "client send me : " << start << endl;
n++;
sleep(1);
}
return 0;
}
client.cc
Used to write data to shared memory, the specific content is as follows:
#include "common.hpp"
int main()
{
Shm shm(CLIENT);
char* start = (char*)shm.getStart();
char ch = 'a';
while(ch <= 'z')
{
start[ch - 'a'] = ch;
ch++;
start[ch - 'a'] = 0;
sleep(1);
}
return 0;
}
Compile the code, run it and see the results: