foreword
This blog introduces the second way of inter-process communication –
System V
System V has three ways:
共享内存
消息队列
信号量
this blog对于系统调用的函数,会进行一定的封装
Article directory
- foreword
- 1. System V shared memory
- 2. The principle of shared memory
- 3. The creation of shared memory
- 4. View and delete shared memory (instruction)
- 5. Modify/delete shared memory
- 6. Shared memory permissions
- 7. Association of shared memory
- Eight. The association of shared memory
- Nine. Shared memory communication
- 10. Little knowledge
- conclusion
1. System V shared memory
2. The principle of shared memory
Processes are independent, and different processes cannot directly obtain each other's data. All communication requires
第三方
some intervention, and the pipeline文件
provides shared files in the form of a method.
Anonymous pipes are based on子进程继承父进程的进程信息
the feature that the anonymous pipe created by the parent process can be obtained文件描述符
, which is only applicable to the owning“亲戚关系”
process;
the essence of the named pipe is the same as that of the anonymous pipe, but it is created in the current directory管道文件
, and different processes can不同方式
open this pipe file , proceed读写
,适用于任何不同进程
both pipelines are内存级文件
,不会进行刷盘
So how does System V shared memory enable different processes to communicate?
The premise of inter-process communication is:
让不同进程看到同一份“资源”
pipes pass through files, and System V通过内存实现
System V创建的共享内存通过页表映射放到不同进程的共享区
3. The creation of shared memory
The function to create shared memory is shmget()
shared memory get
- The first parameter will be explained in detail later
- The second parameter is the size of the shared memory created
- The third parameter is one
位图
, and there are three types of parameters that can be passed:
(1)IPC_CREAT
: If there is no shared memory, create it; if there is, return the shmid of the shared memory
(2)IPC_CREAT | IPC_EXCL
: If there is no shared memory, create it; Return -1 and set the error code. Its role is to ensure that the created shared memory is up to date
(3)以上两种 | 权限
Note:IPC_EXCL不能单独使用
, has no effectThe return value is the shared memory created
共享内存的标识符
(different from the file descriptor)
Let's explain the first parameter in detail
The shared memory we created
需要不同进程双方都能找到
, and when creating a new shared memory不和其他共享内存冲突
, all needs由系统生成一个key值
, try to avoid conflicts and ensure communication between different processes
The function of generating the key value is: ftok()
there may be multiple shared memories in the memory at the same time, and the operating system will also have corresponding structures for them to manage them. This is also a manifestation of describing first and then organizing ideas.
So we need to ensure that different processes can find the same shared memory
The first parameter: path string; the second parameter:
the two parameters of the project ID ftok,创建后会保存在共享内存结构体的属性中
so that the operating system can help us find the shared memory we want to use.
The processes that need to communicate确保这两个参数传的一样
need to find the same shared memory.
The specific content is actually not important (pathname需要是能找到的文件路径
), just make sure that the process to communicate is the same
function to get key value
#define PATHNAME "."
#define PROJID 0x6666
//获取key值
key_t getKey()
{
key_t k=ftok(PATHNAME,PROJID);
if(k==-1)
{
cerr<<errno<<":"<<strerror(errno)<<endl;
exit(1);
}
return k;
}
//将key值转换成十六进制
string toHex(key_t k)
{
char buffer[64];
snprintf(buffer,sizeof(buffer),"0x%x",k);
return buffer;
}
simple test
This way we get the same key value.
The next step is to create the memory space.
Because only the last parameter is different between creating shared memory and obtaining shared memory, we can perform certain encapsulation
//进行封装
static int createShmHelper(key_t key,int size,int flag)
{
int shmid = shmget(key,size,flag);
//出错判断
if(shmid==-1)
{
cerr<<"error: "<<errno<<" : "<<strerror(errno)<<endl;
exit(2);
}
return shmid;
}
//创建共享内存
int createShm(key_t key,int size)
{
//因为是创建,我们就用,保证创建最新的内存空间
return createShmHelper(key,size,IPC_CREAT | IPC_EXCL);
}
//获取共享内存
int getShm(key_t key,int size)
{
//只要获取就好,所以只要IPC_CREAT
return createShmHelper(key,size,IPC_CREAT);
}
simple test
4. View and delete shared memory (instruction)
We have successfully created the shared memory, then there is a question: our two programs are very simple, there is no task loop, and it will end after running once, then if we run
相应创建的共享内存还存在吗?
shmServer again, we will find the following phenomenon
because in shmServer.cpp, we Calling shmget() uses IPC_CREAT | IPC_EXCL, so when the shared memory already exists, it will fail to create, return -1, and set the error code.
==================================================================================
共享内存的查看
We can also use ipcs
instructions to view information related to inter-process communication.
The first is the message queue, the second is the shared memory, and the third is the semaphore array. The
ipcs -m
instruction means only viewing the shared memory.
key
: the key value corresponding to the shared memory,类比文件inode编号
, kernel use
shmid
: the id of the shared memory,类比文件描述符fd
, user use
owner
: the user who created the shared memory
perms
: the permission of the shared memory (same as the file)
bytes
: size (in bytes)
nattch
: association (link ) the number of processes that share memory
status
:
Both of the above phenomena indicate that即使创建共享内存的进程已经退出,相应的共享内存其实还存在。
==================================================================================
共享内存的删除
We can ipcrm -m shmid
delete the shared memory we created by
我们再创建共享内存就会分配新的shmid给我们创建的共享内存了
5. Modify/delete shared memory
The function is:
shmctl()
the first parameter isshmid
; the second is yes共享内存的操作
, there are many kinds of operations;删除,修改个别属性...
the third parameter输出型参数
is the shared memory management in the kernel结构体
, you can pass the structure获取该共享内存的属性
This is part of the properties of the structure
共享内存的删除
The macro for the modification operation isIPC_RMID
//删除共享内存
void delShm(int shmid)
{
int n=shmctl(shmid,IPC_RMID,NULL);
assert(n!=-1);
(void)n;
}
==================================================================================
获取共享内存属性
//查看共享内存属性
struct shmid_ds ds;
int n=shmctl(shmid,IPC_STAT,&ds);
if(n!=-1)
{
cout<<"perm: "<<toHex(ds.shm_perm.__key)<<endl;
cout<<"create pid: "<<ds.shm_cpid<<" : "<<getpid()<<endl;
}
Note: Permission is required to view shared memory
调用者必须要有这个共享内存的读权限
6. Shared memory permissions
We use the above method to create a shared memory, perms is the permission, the default is 0
Permissions need to be determined at the time of creation. In fact, you only need to add the corresponding permissions to the third parameter of shmget.
//创建共享内存
int createShm(key_t key,int size)
{
//因为是创建,我们就用,保证创建最新的内存空间
umask(0);//将掩码设置为0,保证预期的权限
return createShmHelper(key,size,IPC_CREAT | IPC_EXCL | 0666);
}
This successfully sets the permissions.
7. Association of shared memory
Above we have completed the peripheral work of inter-process communication, but we have not really realized the communication. We
只创建了共享内存
, but in fact, the shared memory is not in the task struct of our process at this time, we just created it successfully.关联这个共享内存
For this reason , we still need to将共享内存映射到进程的共享区
use it before we can really use it.
The associated function is shmat()
The first parameter is
shmid
; the second parameter is共享区的虚拟地址
, you can specify to mount the shared memory to the specified location through this parameter; the third parameter is挂接方式(读写)
the return value is the virtual address of the mounted shared area
//关联共享内存
char * attchShm(int shmid)
{
char*start=(char*)shmat(shmid,NULL,0);
return start;
}
In (3), we talked about, nattch是关联该共享内存的进程数
, and this test also verified this point. 0->1->2->1->0
Eight. The association of shared memory
The associated function isshmdt()
The header file is shmat()
the same as
传参是shmat的返回值
//取关联共享内存
void detachShm(char*start)
{
int n=shmdt(start);
assert(n!=-1);
(void)n;
}
Nine. Shared memory communication
Next, we can communicate using shared memory.
However, we can also encapsulate the above code into a class
#define SERVER 1
#define CLIENT 0
const int gsize=4096;
class Init
{
public:
Init(int t):type(t)
{
//获取key值
key_t k = getKey();
//创建/获取共享内存
if(type == SERVER)
{
//服务端创建
shmid = createShm(k, gsize);
}
else
{
//客户端获取
shmid = getShm(k, gsize);
}
//关联共享内存
start = attachShm(shmid);
}
//获取读写字符串
char *getStart()
{
return start;
}
~Init()
{
//取关联
detachShm(start);
if(type == SERVER)
{
//如果是服务端,还需要销毁共享内存
delShm(shmid);
}
}
private:
char *start;//读写字符串
int type; //表示是服务端还是客户端
int shmid;//共享内存的id
};
Use as follows:
communication completed successfully
10. Little knowledge
-
共享内存的大小分配
The size of PAGE_SIZE is 4KB, which just corresponds to the size of the data block accessed by the CPU.
But when we create a shared memory of, for example, 5000 bytes, does the operating system allocate 8KB?
The size of the shared memory is still 5000, not 8KB.
But this 5000 is actually just允许访问的大小
, actually操作系统是分配了8KB的
. -
Because the shared memory reads and writes data directly in the memory,
没有像管道那样的缓冲区
if one party writes, the other party can read it immediately, so yes所有进程通信速度最快的
. -
Because shared memory communicates directly in memory, there is no system call interface,
没有任何保护机制
yes同步互斥
conclusion
The knowledge record in this article is complicated, please understand. For the purpose of taking notes and sharing, Wang Lao gave pointers.
If you think this article is helpful to you, you might as well like it to support the blogger, please, this is really important to me.