进程间通信
进程都是独立的个体,每个进程之间的数据是不共享的。
文件操作缺陷:
- 没办法保证写入数据在读取数据之前
- 文件的存储空间是在磁盘上,写入数据时,要执行一次I/O操作,读取数据时执行一次I/O操作。
- 只能做到有关系的进程之间数据的传递,而且没办法实现任意两个进程之间。
进程间通信的机制:管道(有名管道,无名管道) 信号量 共享内存 消息队列。
有名管道:在磁盘有一个管道文件标识,但是这个管道文件只会占据一个inode结点,但是这个管道文件任何时候都不会占据block块,数据在传递过程中会缓存在内存上。(管道文件仅仅是为了使不同的进程(有权限操作的))能够共享。
无名管道:没有管道文件,借助父子进程共享fork之前打开的文件描述符。来实现进程间通信。
管道
创建管道文件:
命令 mkfifo filename
库函数 int mkfifo(); open read write close
有名管道文件通信测试
1 |
|
1 |
|
- open以一种方式打开管道文件会阻塞,直到有进程以另一种方式打开此管道文件。
- 如果管道对应的内存空间中没有数据,则read会阻塞,直到(1)内存中有数据(2)所有写端关闭
- 如果管道对应的内存空间已满,则write就会阻塞,直到(1)内存有空间(2)所有读端关闭
无名管道
1 |
|
消息队列
消息:类型+数据
队列:先进先出(优先级队列)
信号量 消息队列 共享内存—>内核对象(操作系统内核中)。
1 | int msgget((key_t)key,int flag) |
消息队列中的数据是有间隔的
1 |
|
1 |
|
1 |
|
信号量
对于进程执行的同步控制
关系:竞争关系 协作关系
特殊的一个变量(计数器),一般取正数值。他的值代表允许访问的资源数目,获取资源时,需要对信号量的值进行原子-1,该操作被称为P操作。当信号量值为0时,代表没有资源可用,P操作会阻塞。释放资源时,需要对信号量的值进行原子+1,该操作被称为V操作。信号量主要用来同步进程。信号量的值如果只取0,1,将其称为二值信号量。如果信号量的值大于1,则称为计数信号量。
临界资源:同一时刻,只允许被一个进程或者线程访问的资源。
临界区:访问临界资源的代码段。
Linux系统内核维护是一个信号量集
1 | int semget((key_t)key,int nsems,int flag) |
如果是第一次执行semget,内核中没有信号量集,则需要创建信号量集,并且完成初始化。如果内核中已经有了此信号量集,则直接获取返回就可以。
1 | int semctl(int semid,int semnum,int cmd,...) |
信号量的操作
sem.h
1 |
|
sem.c
1 |
|
maina.c
1 |
|
共享内存(最快的IPC)
1 | 1、获取 |
1 | A进程获取用户数据,B进程打印用户数据 |
shma.c
1 |
|
shmb.c
1 |
|