管道
当一个进程连接数据流到另一个进程时,我们就会用到管道。我们通常把一个进程的输出连接到另一个进程的输入。管道的本质是内核提供的一段内存。
popen()函数和pclose()函数
popen()函数允许一个程序将另一个程序作为新进程来启动,返回一个文件流指针,第一个参数是程序名和对应的参数,另一个是“r”或“w”。pclose()函数关闭popen()函数对应的进程与之关联的文件流,成功返回文件流对应的退出码,失败返回-1,并设置errno。
FILE* read;
read = popen("uname -a",r);//以可读方式打开一个连接uname程序的管道
pclose(read);//关闭read指向的通道
有名管道和无名管道
无名管道
无名管道的的特性:
- 用于有亲缘关系的进程
- 半双工,单项通信,双向通信需要两个管道
- 声明周期随进程
- 有内置的同步互斥机制
- 面向字节流
无名管道的创建:首先需要定义一个存放两个整形变量的数组:int df[2]
,用来作为管道的输入端口和输出端口,使用pipe()
函数可以创建一个匿名管道,fd
作为参数传给pipe,df[0]
对应着管道的读端,df[1]
对应着管道的写端。成功返回0,失败返回-1,并设置errno。
有名管道
特性:除了可以在任意进程间使用,其他的和无名管道一样。
创建:mkfifo()函数,一个参数是程序的地址,第二个参数是文件模式。会创建一个FIFO文件。
总结
管道在内存中的实现,有头尾两个指针,头指针指向待写入区域,尾指针指向待读入区域,头指针减尾指针为管道实际存放的数据大小,当头指针与尾指针指向同一区域时,管道为空,read阻塞,当头指针在尾指针之后时,管道为满,write阻塞。
管道是一种半双工的通信方式,如果需要双向通信就得两个管道。
信号量
概念:
信号量,表示一个资源的变量 ,信号量是一个计数器,可用于实现多线程和多进程之间的临界资源访问安全和合理性,即同步与互斥;
临界资源
临界资源是一次仅允许一个进程使用的共享资源。各进程采取互斥的方式,实现共享的资源称作临界资源。属于临界资源的硬件有,打印机,磁带机等;软件有消息队列,变量,数组,缓冲区等。诸进程间采取互斥方式,实现对这种资源的共享。
临界区:
每个进程中访问临界资源的那段代码称为临界区(criticalsection),每次只允许一个进程进入临界区,进入后,不允许其他进程进入。不论是硬件临界资源还是软件临界资源,多个进程必须互斥的对它进行访问。多个进程涉及到同一个临界资源的的临界区称为相关临界区。使用临界区时,一般不允许其运行时间过长,只要运行在临界区的线程还没有离开,其他所有进入此临界区的线程都会被挂起而进入等待状态,并在一定程度上影响程序的运行性能。
进程同步
同步机制应该遵循的原则
(1) 空闲让进。当无进程处于临界区时,表明临界资源处于空闲状态。这用情况下,应该允许一个请求进入临界区的进程立即进入自己的临界区,以有效地利用临街资源。
(2) 忙则等待。当已有进程进入临界区时,表明临界资源正在被访问。此时其他试图进入临界区的进程必须等待,以保证对临界资源的互斥访问。
(3) 有限等待。要求访问临界资源的进程应该保证在有限时间内能进入自己的临界区,以免进入“死等”状态。
(4) 让权等待。当进程不能进入自己的临界区时,应该立即释放处理机,以免陷入“忙等”状态。
共享内存
共享内存是把同一个物理内存区域映射到多个进程的内存地址空间的通信机制。
优点:快速、方便的共享数据。
缺点:需要额外的同步机制来协调数据访问。
两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
消息队列
消息队列是消息的链表,存放在内核中,并由消息队列标识符表示。它提供了一种从一个进程向另一个进程发送数据块的方法,和管道类似,但它长度是有限的。
特点
- 生命周期随内核,消息队列会一直存在,需要我们显示的调用接口删除或使用命令删除
- 消息队列可以双向通信
- 克服了管道只能承载无格式字节流的缺点
套接字socket
网络详解