进程间通信
共享内存
共享内存是最快的进程间通信方式,相较于其他进程间通信方式,少了两次内核态与用户态之间的数据拷贝过程
原理及使用过程
- 在物理内存中开辟一块内存空间
- 将这块内存空间通过页表映射到进程的虚拟地址空间中
- 进程可以直接通过进程虚拟地址空间访问到这块物理内存进行操作;若多个进程映射同一块物理内存,就可以实现相互通信;直接通过虚拟地址改变内存中的数据,其他进程的数据也会随之改变
- 解除映射关系
- 删除共享内存
1. 共享内存的创建
int shmget(key_t key,size_t size,int shmflg);
参数: key:共享内存在操作系统中的标识符
size:共享内存的大小
shmflag: 示例IPC_CREAT|0664
IPC_CREAT 共享内存若存在则打开,不存在就创建再打开
IPC_EXCL 与IPC_CREAT同时使用时,若共享内存存在则报错返回
mode 共享内存的操作权限
返回值: 正整数---共享内存的操作句柄 失败:-1
2. 共享内存的映射
void *shmat(int shmid,const void *shmaddr,int shmflg);
参数: shmid 创建共享内存返回的操作句柄
shmaddr 共享内存在虚拟地址空间中的首地址---通常置NULL
shmfig SHM_RDONLY---映射之后,共享内存只读;通常置0-可读可写
返回值 映射首地址 失败:(void*)-1
3. 共享内存的操作
同常见的内存操作一样,如memcpy/strcpy等
4. 解除映射关系
int shmdt(const void *shmaddr);
参数: shmaddr shmat建立映射时返回的映射首地址
5. 删除共享内存
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
参数: shmid 共享内存操作句柄
cmd 即将进行的操作-即IPC_RMID 删除共享内存
buf 用于获取/设置共享内存信息,不关心的话置NULL
共享内存的删除流程:共享内存在使用时会对当前的映射连接数(shm_nattch
)进行判断和±操作,在删除的时候,首先会判断当前映射连接数是否为0;若为0则直接删除;否则表示现在还有其他进程正在使用共享内存,不能立即删除,但是会拒绝后续进程的映射连接,等待映射连接数为0时删除
简单使用
//写端
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>//注意头文件
#define IPC_KEY 0x12345678
int main()
{
int shmid = shmget(IPC_KEY, 32, IPC_CREAT|0664);
if (shmid < 0) {
perror("shmget error");
return -1;
}
void *shm_start = shmat(shmid, NULL, 0);
if (shm_start == (void*)-1) {
perror("shmat error");
return -1;
}
int i = 0;
while(1) {
sprintf(shm_start, "%s-%d", "hello world!!", i++);
sleep(1);
}
shmdt(shm_start);//映射首地址
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
//读端
int main()
{
int shmid = shmget(IPC_KEY, 32, IPC_CREAT|0664);
if (shmid < 0) {
perror("shmget error");
return -1;
}
void *shm_start = shmat(shmid, NULL, 0);
if (shm_start == (void*)-1) {
perror("shmat error");
return -1;
}
int i = 0;
while(1) {
//在这里循环读取打印缓冲区的内容
printf("%s\n", shm_start);
sleep(1);
}
shmdt(shm_start);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
消息队列
消息队列是操作系统在内核中为用户创建的一个队列;其他进程可以通过访问相同的队列进行通信
消息队列所传输的是有类型的数据块
消息队列的生命周期随内核
信号量
信号量用于实现进程间的同步与互斥
实际上就是内核中的一个计数器,进行资源计数(统计现在有多少资源,用于判断是否能够进行操作)
同步:对临界资源访问的时序和理性
互斥:同一时间对临界资源操作的唯一性
原理:
-
互斥原理:只具有0/1计数时,就可以实现互斥
初始计数为1,表示当前只有一个进程能够获取资源,获取资源之后-1;计数为0,其他进程在等待队列上等待,临界资源被操作完毕之后计数+1,并且唤醒等待队列上的进程 -
同步原理:对程序逻辑进行控制(对临界资源合理操作控制)
通过计数判断当前能否对临界资源进行操作,不能操作(计数<=0),则等待;其他进程操作后计数+1,促使再次判断,唤醒等待的进程
查看ipc的命令
ipcs 查看ipc
ipcs -m 查看共享内存
ipcs -s 查看信号量
ipcs -q 查看消息队列
ipcrm 删除ipc
ipcrm -m shmid 删除共享内存,其他同理