提示:以下是本篇文章正文内容,下面案例可供参考
一、匿名管道
进程之间的通信目的一般是来控制另一个进程。也可以用来实现数据的交流,还有资源共享等。
匿名管道原理:
(铺垫)进程之间是具有独立性,而linux是以文件来管理数据的,决定了实现共享文件必须由操作系统来提供内存级别的缓存区来存储数据,实现进程的数据共享。
例如:fork()创建父子进程之间是数据相同,但发生写入操作时,会发生写时拷贝,因为进程具有独立性,它们俩个的文件描述符表内容也是相同的,但是文件表述符表里的文件标识符指向的文件却是同一份文件。两个进程都具有对该文件的读写功能,关闭父进程的对以写功能的该文件(保留了那个以读方式打开的文件),子进程相反保留了写的关闭了读的,这样两个进程就实现了一个读一个写,它们之间是单向通信。由于该文件是由操作系统提供的,所以它提供了系统接口来实现管道通信。
系统调用接口pipe函数 :如果创建成功就返回0,如果失败就返回-1。pipefd[0]是默认以分配以读方式打开的文件描述符。pipefd[1]是以读方式的
我们让子进程不断写入数据让计数器++,然后父进程读取子进程写入的数据。
二、管道通信的四种情况
1. 子进程不写入数据的同时也不关闭写,那么父进程就会进行等待。
2.子进程不断写入数据直到将文件写满那么子进程就会堵塞,这时父进程读取就会读取全部的数据,读取完,子进程就写入数据。
3.子进程写入数据,之后在关闭写端,父进程会读取完管道的 数据,然后read()返回0,表示读取结束。
4.父进程关闭读同时子进程仍在写入,子进程就会发送退出信号给父进程,子进程也退出了
2.有名管道
有名管道的可以让不同的进程进行通信,这个特殊的文件(管道)由操作系统提供系统调用传建,同时数据不会向磁盘刷新数据(存储)。
原理:2个进程之间打开这个特殊的文件。可以对文件进行读写
创建:如果这里路径为./fifo,权限可以为0666.表示 在当前目录下创建了名为|fifo管道文件,权限为可读可写(可以用mask(0),处理系统默认的影响)
删除:
删除这个特殊文件,如果没删除,进程退出,那么这个文件也会被删除,因为文件生命周期随进程的
3.共享内存
共享内存原理:就是要物理内存上操作系统开辟一段空间,修改进程的页表(挂载),让物理地址映射到页表上的虚拟地址上,同时这个也是进程读取数据最快的方式,不过缺少了管道的同步机制,使得写入的数据任意时刻都会被挂载这个内存的其他进程,随时读取,造成信息的不完整性,这个需要我们自己控制。
1.共享内存的创建:
这里的key是内核区分共享内存的标记,size是申请的大小,shmflg是标识常用的是 IPC_CREAT或者是IPC_EXCL,通常IPC_CREAT和IPC_EXCL配合使用,表示如果通过key创建共享内存已存在就报错,不存在就不会报错。IPC_CREAT单独使用,如果通过key已经有了一个共享内存就会截取
2.获取key
proj_id是一个数字,ftok会用proj_id和pathname形成唯一的key
2.获取共享内存
实际上截取和创造共享内存是同个函数只是选择的不同,一个进程创造共享内存,一个进程通过同个key截取这个共享内存,这样两个进程挂载后这个共享内存就可以实现通信了。
3.获取共享内存的相关属性
shmct可以获取共享内存一些信息,当然选项的不同也有其他的功能比如选项是IPC_RMID就是删除,如果cmd是IPC_STAT,我们申请一个shmid_ds类型的结构体,系统会把共享内存一些信息拷贝到这个结构体中,比如:
2.共享内存的删除(指令/系统函数)
指令:ipcrm -m +shmid
函数:
共享内存的生命是随内核的,如果不主动删除,就会一直存在,除非重启linux
3.挂载(at)和删除挂载(dt)
挂载就是修改进程的页表,把物理内存映射到虚拟地址上,通过这个虚拟地址就可以找到物理内存
4.消息队列
消息队列是一个具有数据类型的队列,因为 不同进程既能获取也可以写入数据,为了区分哪个数据是哪个进程的也为了方便进程获取各自需要的数据。
1.创建
2.获取属性或者删除
3.写入数据和读取