IO与通信彻底解决

This commit is contained in:
yinkanglong_lab
2021-04-06 17:26:49 +08:00
parent 8df0902abb
commit b5621d4b6c
10 changed files with 102 additions and 38 deletions

View File

View File

View File

View File

@@ -6,6 +6,7 @@
- 论文复现(一周时间)
### 工作
> [C++学习路线](https://www.zhihu.com/collection/589776737)
- 制作简历(明天)√
- 知识复习——语言
@@ -13,9 +14,9 @@
- [x] 基础语法 √
- [x] 标准库 STL√
- [x] 面向对象 √
- [ ] 设计模式有道云笔记gitee 设计模式库,书)
- [ ] 设计模式(有道云笔记,源网址,gitee设计模式库
- [ ] effective 系列
- [ ] 系列视频
- [ ] 系列视频(知乎上收藏的内容)
- [ ] 问题专项解决
- Java两周
- [ ] 语法
@@ -50,10 +51,14 @@
- [x] 文件管理
- [x] 系统调用
- 编程实战
- [ ] 网络编程socket网络编程
- [ ] 并行编程(多线程并发编程)
- [ ] 系统编程(linux操作系统编程)
- linux系统编程
- [ ] 网络编程(socket网络编程)
- [ ] 并行编程(多线程、多进程并发编程)
- [ ] IO编程实现多种机制的IO方式select/poll/epoll/signal/async等
- [ ] 系统编程linux操作系统编程
- C++通用库跨平台编程
- [ ] 网络编程socket跨平台网络编程
- [ ] 并行编程(多线程、多进程并发编程)
- 刷题
- 力扣(学习、题库、讨论。侧重于刷算法类型的题目和相关讨论)
- 学习3-5 本书的学习需要阅读的书籍如下

View File

@@ -5,4 +5,31 @@
## 收获
* 对网络编程和并行编程的内容进行了复习。
* 通信原理Linux的五种IO模型。阻塞IO、非阻塞IO、IO复用、信号、异步IO。前四种是同步最后是异步第二阶段从内核到用户复制数据是否阻塞。1、3是阻塞、2、4是非阻塞第一阶段是否进行阻塞。
* Linux网络编程Linux socket编程。主要通过bind、accept、socket、listen、read、send实现
* Linux并行编程同步pthread/各种lock。通信pipe/FIFO
* Linux IO编程file、epoll
* C++网络编程boost-asio
* C++并行编程C++多线程机制。C++线程同步机制Future/Async、thread/promise、mutex/guard_lock/unique_lock/condition_variable信号量互斥锁与条件变量
* Linux系统编程还其本身大量的网络编程和并行编程实现方案。
* C++的标准库和其他库也封装了网络编程和并行编程方案。
* 网络编程和并行编程本质上是一种东西。并行编程是实现多线程、线程同步、线程通信。网络编程是实现两个远程线程的同步和通信。
* 对几个概念的理解
* 网络编程
* 网络多进程、多线程。进程/线程的同步和通信。socket实现。是并发编程的一种形式。
* 并发编程
* 本地多进程、多线程。包含进程/线程同步、进程/线程通信。
* 进程同步
* 属于并发编程的一个环节
* 进程通信
* 属于并发编程的一个环节
* IO
* 本地设备IO机制。同步、异步、阻塞、非阻塞、IO复用等。
* 几个方案用来实现以上哪些内容。
* socket 实现网络编程。
* 信号量、管道、信号、消息队列:进程同步与进程通信
* select/poll/epoll IO方式

View File

@@ -1,4 +1,8 @@
# 2.4 进程通信
> 参考文献
> * [https://blog.csdn.net/qq_40989769/article/details/110481553](https://blog.csdn.net/qq_40989769/article/details/110481553)
> linux实现多线程多进程的方法有很多。可以在linux系统编程部分好好了解。在这里只引入Linux实现几种进程通信的方式。
## 0 进程通信的定义
@@ -38,24 +42,34 @@
4. **无名管道通信**。无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
5. **高级管道通**信。高级管道popen将另一个程序当做一个新的进程在当前程序进程中启动则它算是当前程序的子进程这种方式我们成为高级管道方式。
6. **有名管道通信**。有名管道 named pipe 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
7. 消息队列通信。消息队列( message queue 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
7. **消息队列通信**。消息队列( message queue 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
8. **套接字通信**。套接字( socket 套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
## 1 信号量通信
> 参考文献
> * [https://blog.csdn.net/csdn_kou/article/details/81240666](https://blog.csdn.net/csdn_kou/article/details/81240666)
### 函数接口
* 进程中的信号量函数
```
```
* 线程中的信号量函数。
* linux进程中的信号量函数
```C++
// linux操作系统
```
* linux线程中的信号量函数。
```C++
// linux操作系统
pthread_mutex_t
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_unlock
pthread_mutex_destroy
```
* 跨平台C库中的信号量(window/linux都可以使用)
```C++
// 标准库中的进程同步和通信
mutex/recursive_mutex;
guard_lock;
unique_lock;
condition_variable;
```
### 编程实现
```C
#include <time.h>
@@ -165,6 +179,11 @@ int main(int argc, char *argv[])
## 2 信号通信
### 函数接口
* linux下的信号机制
```
```
### 编程实现
```C
```
@@ -617,7 +636,7 @@ int main(int argc, char** argv)
}
```
## 9 进程通信的同步方式
## 9 进程通信的同步与阻塞
### 同步异步、阻塞非阻塞

View File

@@ -1,5 +1,8 @@
# 五种IO模型
> linux实现IO过程的方法有很多。这里只对五种模型进行介绍。如果要实现五种IO过程在linux系统编程部分进行学习。
## 1 I/O 模型
* 一个输入操作通常包括两个阶段:
@@ -77,9 +80,11 @@ ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *
* 同步IO的主要区别在第一个阶段。阻塞式IO、IO复用第一阶段会阻塞。非阻塞式IO、信号驱动IO在第一阶段不会阻塞。
![](image/2021-03-30-22-04-01.png)
## 2 I/O 复用
* select/poll/epoll 都是 I/O 多路复用的具体实现select 出现的最早,之后是 poll再是 epoll。
## 2 I/O 复用实现方式
> select/poll/epoll 都是 I/O 多路复用的具体实现select 出现的最早,之后是 poll再是 epoll。
### select
@@ -274,9 +279,9 @@ else
### 应用场景
* 很容易产生一种错觉认为只要用 epoll 就可以了select 和 poll 都已经过时了,其实它们都有各自的使用场景。
1. select 应用场景。select 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景比如核反应堆的控制。select 可移植性更好,几乎被所有主流平台所支持。
很容易产生一种错觉认为只要用 epoll 就可以了select 和 poll 都已经过时了,其实它们都有各自的使用场景。
1. select 应用场景。select 的 timeout 参数精度为微秒,而 poll 和 epoll 为毫秒,因此 select 更加适用于实时性要求比较高的场景比如核反应堆的控制。select 可移植性更好,几乎被所有主流平台所支持。
2. poll 应用场景。poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。
3. epoll 应用场景。只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。需要同时监控小于 1000 个描述符,就没有必要使用 epoll因为这个应用场景下并不能体现 epoll 的优势。需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。
2. poll 应用场景。poll 没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用 poll 而不是 select。
3. epoll 应用场景。只需要运行在 Linux 平台上,有大量的描述符需要同时轮询,并且这些连接最好是长连接。需要同时监控小于 1000 个描述符,就没有必要使用 epoll因为这个应用场景下并不能体现 epoll 的优势。需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用 epoll。因为 epoll 中的所有描述符都存储在内核中,造成每次需要对描述符的状态改变都需要通过 epoll_ctl() 进行系统调用,频繁系统调用降低效率。并且 epoll 的描述符存储在内核,不容易调试。

View File

@@ -4,26 +4,11 @@
> * [https://www.zhihu.com/question/19732473/answer/14413599](https://www.zhihu.com/question/19732473/answer/14413599)
> * [https://www.cnblogs.com/shiysin/articles/10689761.html](https://www.cnblogs.com/shiysin/articles/10689761.html)
> * [https://blog.csdn.net/jolin678/article/details/49611587](https://blog.csdn.net/jolin678/article/details/49611587)
## 1 同步异步、阻塞非阻塞
> * [https://blog.csdn.net/qq_40989769/article/details/110481553](https://blog.csdn.net/qq_40989769/article/details/110481553)
### nodejs中相关定义
* **同步式I/OSynchronous I/O或阻塞式I /O Blocking I/O**。线程/进程在执行中如果遇到磁盘读写或网络通信统称为I/O 操作),通常要耗费较长的时间,这时 操作系统会剥夺这个线程/进程的CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞 。当I/O 操作完毕时,操作系统将 这个线程的阻塞状态解除恢复其对CPU的控制权令其继续执行。
* **异步式 I/O Asynchronous I/O或非阻塞式I/O Non-blocking I/O**。则针对所有I/O 操作不采用阻塞的策略。当线程 遇到I/O 操作时不会以阻塞的方式等待I/O 操作的完成或数据的返回而只是将I/O 请求发送给操作系统继续执行下一条语句。当操作系统完成I /O 操作时以事件的形式通知执行I/O 操作的线程线程会在特定时候处理这个事件。为了处理异步I/O线程必须有事件循环不断地检查有没有未处 理的事件,依次予以处理。
* **并发方式**。阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过**多线程**。而非阻塞模式下一个线程永远在执行计算操作这个线程所使用的CPU 核心利用率永远是100%**I/O 以事件的方式通知**。在阻塞模式下多线程往往能提高系统吞吐量因为一个线程阻塞时还有其他线程在工作多线程可以让CPU 资源不被阻塞中的线程浪费。而在非阻塞模式下线程不会被I/O 阻塞永远在利用CPU。多线程带来的好处仅仅是在多核CPU 的情况下利用更多的核而Node.js的单线程也能带来同样的好处。这就是为什么Node.js 使用了单线程、非阻塞的**事件编程模式**。
### 一种更深的理解——在看完五种IO模型之后的反思
* 同步和异步是针对**应用程序和内核**的交互而言的;
* 同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪。
* 异步是指用户进程触发IO操作以后便开始做自己的事情而当IO操作已经完成的时候会得到IO完成的通知。
* 阻塞和非阻塞是针对于**进程在访问数据**的时候根据IO操作的就绪状态来采取的不同方式说白了是一种读取或者写入操作函数的实现方式
* 阻塞方式下读取或者写入函数将一直等待,
* 非阻塞方式下,读取或者写入函数会立即返回一个状态值。
## 1 进程通信的方式——同步异步、阻塞非阻塞
### 同步异步
@@ -38,8 +23,31 @@
* 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
* 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
## 2 设备IO的方式——同步异步、阻塞非阻塞
### nodejs中相关定义
## 3 实现方式
* **同步式I/OSynchronous I/O或阻塞式I /O Blocking I/O**。线程/进程在执行中如果遇到磁盘读写或网络通信统称为I/O 操作),通常要耗费较长的时间,这时 操作系统会剥夺这个线程/进程的CPU 控制权,使其暂停执行,同时将资源让给其他的工作线程,这种线程调度方式称为阻塞 。当I/O 操作完毕时,操作系统将 这个线程的阻塞状态解除恢复其对CPU的控制权令其继续执行。
* **异步式 I/O Asynchronous I/O或非阻塞式I/O Non-blocking I/O**。则针对所有I/O 操作不采用阻塞的策略。当线程 遇到I/O 操作时不会以阻塞的方式等待I/O 操作的完成或数据的返回而只是将I/O 请求发送给操作系统继续执行下一条语句。当操作系统完成I /O 操作时以事件的形式通知执行I/O 操作的线程线程会在特定时候处理这个事件。为了处理异步I/O线程必须有事件循环不断地检查有没有未处 理的事件,依次予以处理。
* **并发方式**。阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过**多线程**。而非阻塞模式下一个线程永远在执行计算操作这个线程所使用的CPU 核心利用率永远是100%**I/O 以事件的方式通知**。在阻塞模式下多线程往往能提高系统吞吐量因为一个线程阻塞时还有其他线程在工作多线程可以让CPU 资源不被阻塞中的线程浪费。而在非阻塞模式下线程不会被I/O 阻塞永远在利用CPU。多线程带来的好处仅仅是在多核CPU 的情况下利用更多的核而Node.js的单线程也能带来同样的好处。这就是为什么Node.js 使用了单线程、非阻塞的**事件编程模式**。
### 一种更深的理解——在看完五种IO模型之后的反思
* 同步和异步是针对**应用程序和内核**的交互而言的;
* 同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪。可以是阻塞等待也可以是非阻塞的轮询。
* 异步是指用户进程触发IO操作以后便开始做自己的事情而当IO操作已经完成的时候会得到IO完成的通知。
* 阻塞和非阻塞是针对于**进程在访问数据**的时候根据IO操作的就绪状态来采取的不同方式说白了是一种读取或者写入操作函数的实现方式
* 阻塞方式下读取或者写入函数将一直等待,
* 非阻塞方式下,读取或者写入函数会立即返回一个状态值。
## 3 进程通信和设备IO的关系
1. 关于同步异步、阻塞非阻塞。交互方式,分别有两种应用。一种用在**进程间的同步和通信**上;一种用在**设备IO过程**中。必须要进行区分。
2. 当然两者似乎也有重合的部分。例如在socket编程网络编程网络进程通信过程中即是一种**网络进程通信(两个远程进程)**,也是一种**网络IO过程一个进程与网卡设备IO**。可以看成两个远程的网络进程通信也可以看成单个线程与本地网卡设备的IO过程。
3. 所以在某种程度上。可以把两个进程的通信看成某一个用户进程的IO过程而另一个进程看成是设备。
## 4 实现方式
### 同步阻塞通信
> 在此种方式下用户进程在发起一个IO操作以后必须等待IO操作的完成只有当真正完成了IO操作以后用户进程才能运行。
@@ -50,7 +58,7 @@
### 同步非阻塞
> 在此种方式下用户进程发起一个IO操作以后边可返回做其它事情但是用户进程需要时不时的询问IO操作是否就绪这就要求用户进程不停的去询问从而引入不必要的CPU资源浪费。其中目前JAVA的NIO就属于同步非阻塞IO。
* poll机制。轮训IO信号虽然没有阻塞但是在循环中一确认IO是否完成。效率很低。
* poll机制。轮训IO信号虽然没有阻塞但是在循环中一确认IO是否完成。效率很低。
### 异步非阻塞通信