文章目录
(一)共享内存
(1)共享内存实现进程间通信的原理:
- 共享内存在物理内存上开辟的空间
- 多个进程可以将自己的虚拟空间地址映射到该块物理空间上
- 多个进程都可以访问共享内存中的数据
- 共享内存上的改动可以被其他进程看到
- 并未实现同步机制,需要其他机制同步对共享内存的访问
(2)共享内存逻辑结构图
(二)共享内存相关函数
使用sys/shm.h
(1)创建(获得)共享内存
int shmget(key_t key, size_t size, int shmflg);
- key_t :键值用于标识使用同一个共享内存段;(IPC_PRIVATE创建只属于进程的共享内存,但不是真正的私有)
- size : 共享内存的容量(字节)
- shmflg : IPC_CREAT(创建生效 / 获得忽略)(9个位的权限标志,与文件权限mode类似)
- 返回值:成功返回共享内存标识符(非负数),失败-1
(2)共享内存和进程的连接(at)
void* shmat(int shm_id, const void* shm_addr, int shmflg);
- shm_id : 共享内存标识符
- shm_addr : 指定共享内存连接到当前进程的地址位置(通常是空指针NULL,表示让系统自己分配共享内存的地址)
- shmflg : 一般是0,SHM_RND(与shm_addr联合使用控制共享内存连接地址)、SHM_RDONLY(连接的内存只读)(一组位标志)
- 返回值:成功返回指向共享内存第一个字节的指针,失败-1
注意:
- 共享内存的读写权限:由创建者、它的访问权限、当前进程属主决定(类似于文件权限)
- 例外:shmflg & SHM_RDONLY为真时,此时的共享内存即使可写入,都不能写入;
(3)共享内存的控制(ctl)
int shmctl(int shm_id, int command, struct shmid_ds* buf);
- shm_id : shmget的返回值,共享内存标识符
- command : 采取的操作
命令 | 说明 |
---|---|
IPC_STAT | 把shmid_ds结构中的数据设置成共享内存的当前关联值 |
IPC_SET | 若进程有足够的权限,就把共享内存的当前关联值设置成shmid_ds结构中给定的值 |
IPC_RMID | 删除共享内存段 |
- buff :是一个指针,指向包含共享内存模式和访问权限的结构
- 返回值:成功返回0,失败-1
注意:删除一个正在处于连接状态的共享内存段后,通常还能够使用,直到最后一个进程脱离该共享内存段的连接(最好不要这样做!!哒咩)
(4)共享内存的分离(dt)
将共享内存从当前进程中分离;
int shmdt(const void* shm_addr);
- shm_addr是shmat()返回的指针
- 返回值:成功0,失败-1
注意:
共享内存分离,但未删除,只是分离的进程变得不可用
(三)练习巩固
(1)(未进程同步)简单的使用共享内存
- a.c
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
//向共享内存中写入数据
void WriteToShm()
{
//创建共享内存
int shmid = shmget((key_t)8888, 128, IPC_CREAT | 0600);
if(shmid == -1)
{
perror("shmget err");
return;
}
//连接共享内存
char* shm = shmat(shmid, NULL, 0);
if(shm == NULL)
{
perror("shmat shm err");
return;
}
//向共享内存中写入数据
printf("input data : \n");
while(1)
{
char buff[128] = {
0};
fgets(buff, 127, stdin);
if(strncmp(buff, "end", 3) == 0)
{
break;
}
strncpy(shm, buff, strlen(buff) - 1);
}
//脱离连接
shmdt(shm);
}
int main()
{