进程间通信的重点 – 要让不同的进程看到同一块内存
一. system V共享内存的接口
key_t k = ftok(PATH_NAME, PROJ_ID);
int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
char *shmaddr = (char *)shmat(shmid, nullptr, 0);
int n = shmdt(shmaddr);
n = shmctl(shmid, IPC_RMID, nullptr);
二. 结论
- 申请到的共享内存在堆栈间,属于用户空间,则不经过系统调用,也可以直接访问(与之相对的管道经过文件通信,文件是内核的一种数据结构,需要经过系统接口访问)
- 则共享内存减少了很多拷贝,加快了访问速度,却缺乏访问控制!(server一直在读–与管道通信不同) 二者甚至都不知道对方的存在。
信号量的引入
一. 相关概念
- 把多个进程(执行流)看到的公共的一份资源看做 临界资源
- 把自己的代码访问临界资源的代码称为 临界区
- 为了更好的进行对临界区的保护,可以让多执行流在任何时刻,只能有一个进程进入临界区 – 互斥
- 要么不做,要么做,没有中间状态,就是 原子的
二. 信号量(电影票类比)
- 买票:对座位的预定机制
座位:临界资源
预定:申请信号量 - 不准确的认为 – 信号量为计数器
int count = n;
-
- 申请信号量成功
count --;
,临界资源内部,预留了想要的资源(P操作) - 访问临界资源 – 执行自己的临界区代码
- 释放信号量
count ++;
(V操作)
- 因为在CPU执行时,
count --;
至少有三步,而进程会随时被切换出去。则即使是定义了所有进程都看得到的内核级的全局count
,也无法保证对 count
加减操作的不受外界干扰。此方法不行,我们要保证P,V操作的原子性。