当前位置:网站首页>进程之间使用共享内存通信
进程之间使用共享内存通信
2022-06-21 14:46:00 【用户6978604】
共享内存
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。
但是它并未提供同步机制,即在某一个进程结束对共享内存的写操作之前,并不能可以阻止第二个进程开始对它进行读取,因此我们需要人为阻止通过其他机制进行同步。
shmget()函数
用于得到一个共享内存标识符或创建一个共享内存。
函数原型:
int shmget(key_t key, size_t size, int shmflg);参数 | 说明 |
|---|---|
key | 标识共享内存的键值,shmget()函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1. |
size | 指明共享内存的大小,以字节为单位 |
shmflg | 权限标志IPC_CREAT 如果共享内存不存在,则创建一个共享内存,否则打开操作。 IPC_EXCL 只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。 |
shmat()函数
第一次创建完共享内存后,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。
原型:
void *shmat(int shmid, const void *shmaddr, int shmflg)参数 | 说明 |
|---|---|
shmid | 共享存储的id,如shmget()函数的返回值 |
shmaddr | 指定共享内存连接到当前进程中的地址位置,一般为0,表示让内核自己决定一个合适的地址位置 |
shmflg | SHM_RDONLY:为只读模式,其他为读写模式,如0 |
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1。
shmdt()函数
与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存,但是并不是删除该共享内存。
原型:
int shmdt(const void *shmaddr);shmaddr:连接的共享内存的起始地址,如shmat()函数的返回值。调用成功的时候返回0,失败时返回-1。
shmctl()函数
控制共享内存。
原型:
int shmctl(int shm_id, int command, struct shmid_ds *buf);参数 | 说明 |
|---|---|
shm_id | 共享内存标识符,如shmget()的返回值 |
command | 一些命令,如IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值IPC_RMID:删除这片共享内存 |
buf | 共享内存管理结构体。 |
shmid_ds结构 至少包括以下成员:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};例如一个简单的例子,父子进程通过共享内存的方式进行通信:
/*
* @Author: YaleXin
* @Date: 2020-04-22 14:22:16
* @LastEditTime: 2020-04-22 21:38:34
* @LastEditors: YaleXin
* @Description:
* @FilePath: \my_c_workspace\others\shareMemory.c
* @祈祷不出现BUG
*/
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <unistd.h>
struct shareMemoryDate {
int mod;
char msg[100];
};
int main() {
int *shm = NULL;
struct shareMemoryDate *share;
// 创建一个共享内存
// IPC_CREAT表示如果共享内存不存在,则创建一个共享内存,否则打开操作。
// 需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限
int shm_id =
shmget((key_t)0, sizeof(struct shareMemoryDate), 0600 | IPC_CREAT);
if (shm_id == -1) {
printf("创建共享内存失败,我也不知为什么\n");
return 0;
}
int pId = fork();
if (pId == -1) {
printf("创建子进程失败,我也不知为什么\n");
} else if (pId == 0) {
//子进程
// 将共享内存连接到当前进程的地址空间
shm = shmat(shm_id, 0, 0);
if (shm == NULL) {
printf("链接失败,我也不知为什么\n");
return 0;
}
share = (struct shareMemoryDate *)shm;
char buffer[100];
printf("我是子进程,请输入想要写入共享内存的内容:\n");
fgets(buffer, sizeof(buffer), stdin);
strcpy(share->msg, buffer);
// 表示将数据写入完毕
share->mod = 1;
// 把共享内存从当前进程中分离
if (shmdt(shm) == -1) {
printf("分离失败,我也不知为什么\n");
}
} else if (pId > 0) {
//父进程
// 将共享内存连接到当前进程的地址空间
shm = shmat(shm_id, 0, 0);
if (shm == NULL) {
printf("链接失败,我也不知为什么\n");
// 删除共享内存
if (shmctl(shm_id, IPC_RMID, 0) == -1) {
printf("(无法链接)删除共享内存失败,我也不知为什么\n");
return 0;
}
}
share = (struct shareMemoryDate *)shm;
//等待子进程写入完毕
while (share->mod != 1) sleep(1);
printf("我是父进程,让我看看我的子进程在共享内存里边写了什么东西:\n");
printf("%s\n", share->msg);
printf("噢,原来是这些鬼玩意\n");
// 删除共享内存
if (shmctl(shm_id, IPC_RMID, 0) == -1) {
printf("(读取完毕)删除共享内存失败,我也不知为什么\n");
}
}
return 0;
}调试:
[email protected]:/media/yalexin/软件/my_c_workspace/others$ gcc -o share shareMemory.c
[email protected]:/media/yalexin/软件/my_c_workspace/others$ ./share
我是子进程,请输入想要写入共享内存的内容:
你好啊
我是父进程,让我看看我的子进程在共享内存里边写了什么东西:
你好啊
噢,原来是这些鬼玩意
[email protected]:/media/yalexin/软件/my_c_workspace/others$ 边栏推荐
- Qt-3-basic components
- For the first time in China, Tsinghua and other teams won the wsdm2022 only best paper award, and Hong Kong Chinese won the "time test Award"
- Is it safe to open a securities account by downloading the app of qiniu school? Is there a risk?
- What fun things can a desk service do
- 网上开户安全吗?新手可以开账户吗
- Write a compile time annotation
- 通过编译内核的方式增加系统调用
- Reptile essential_ regular expression
- 2022 Hunan latest fire facility operator simulation test question bank and answers
- Configuring MySQL master-slave and implementing semi synchronous replication in docker environment
猜你喜欢

Niuke - real exercise-01

Qt-6-file IO

2022 Fujian latest fire protection facility operator simulation test question bank and answers

LINQ extension methods - any() vs. where() vs. exists() - LINQ extension methods - any() vs. where() vs. exists()

Chapter 4 - network layer

Pyqt5 learning notes of orange_ Basic structure of pyqt5 GUI program

Subshell

What fun things can a desk service do

Summary of the most basic methods of numpy

Learn upward management and four questioning skills to get twice the result with half the effort
随机推荐
Invisible characters encountered \u200b
Qt-3-basic components
Subshell
Is it safe to open an account online? Can a novice open an account
2022 Fujian latest fire protection facility operator simulation test question bank and answers
Numpy: basic package for high performance scientific computing & data analysis
100% troubleshooting and analysis of Alibaba cloud hard disk
Teach you to stop visiting a website
Qt-2-signal and slot
JS hand tear pen test questions ~ not sorted out
Complete and detailed installation steps for kubeneter version 1.7
Simplified crud using code generation
[untitled] fish pond forwarding command
Online keyboard key detection tool
Explain the high availability features of Nacos
Nodejs process has too many open files
DP question brushing record
English accumulation__ annoyance
Is it safe to open a securities account by downloading the app of qiniu school? Is there a risk?
. bash_ profile