diff --git a/Linux/Linxu系统编程/IO编程.md b/Linux/Linxu系统编程/IO编程.md new file mode 100644 index 00000000..e69de29b diff --git a/Linux/Linxu系统编程/并行编程.md b/Linux/Linxu系统编程/并行编程.md new file mode 100644 index 00000000..e69de29b diff --git a/Linux/Linxu系统编程/网络编程.md b/Linux/Linxu系统编程/网络编程.md new file mode 100644 index 00000000..e69de29b diff --git a/工作日志/2021年2月27日-三月份计划.md b/工作日志/2021年2月27日-三月份计划.md index d0288ab1..adc06857 100644 --- a/工作日志/2021年2月27日-三月份计划.md +++ b/工作日志/2021年2月27日-三月份计划.md @@ -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 本书的学习需要阅读的书籍如下 diff --git a/工作日志/2021年4月6日-今日计划.md b/工作日志/2021年4月6日-今日计划.md index a7294ea8..a61aab56 100644 --- a/工作日志/2021年4月6日-今日计划.md +++ b/工作日志/2021年4月6日-今日计划.md @@ -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方式 diff --git a/操作系统/2.4 进程通信.md b/操作系统/2.4 进程通信.md index d3d1d107..59489a8d 100644 --- a/操作系统/2.4 进程通信.md +++ b/操作系统/2.4 进程通信.md @@ -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 @@ -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 进程通信的同步与阻塞 ### 同步异步、阻塞非阻塞 diff --git a/操作系统/4 存储器管理.md b/操作系统/4 内存管理.md similarity index 100% rename from 操作系统/4 存储器管理.md rename to 操作系统/4 内存管理.md diff --git a/操作系统/5 设备管理.md b/操作系统/5 设备IO管理.md similarity index 100% rename from 操作系统/5 设备管理.md rename to 操作系统/5 设备IO管理.md diff --git a/操作系统/附录3 五种IO模型.md b/操作系统/5.1 五种IO模型.md similarity index 89% rename from 操作系统/附录3 五种IO模型.md rename to 操作系统/5.1 五种IO模型.md index 76c411b4..a029134c 100644 --- a/操作系统/附录3 五种IO模型.md +++ b/操作系统/5.1 五种IO模型.md @@ -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 的描述符存储在内核,不容易调试。 \ No newline at end of file diff --git a/操作系统/附录8 同步异步、阻塞非阻塞.md b/操作系统/附录8 同步异步、阻塞非阻塞.md index e85a3139..4eb20231 100644 --- a/操作系统/附录8 同步异步、阻塞非阻塞.md +++ b/操作系统/附录8 同步异步、阻塞非阻塞.md @@ -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/O(Synchronous 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/O(Synchronous 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是否完成。效率很低。 ### 异步非阻塞通信