<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[csy777777的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/csy777777</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; csy777777]]></copyright><item><title><![CDATA[brpc源码阅读]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/118468028</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/118468028</guid><author>csy777777</author><pubDate>Sun, 04 Jul 2021 21:41:15 +0800</pubDate><description><![CDATA[好久都没有更新了，最近主要在看brpc的源码，确实非常精彩，对于锁、lock-free和wait-free的策略令人拍案叫绝，下面是最近看到的一篇文章，总结的挺好，推荐给大家看看。
brpc线程模型和网络模型

...]]></description><category></category></item><item><title><![CDATA[c++编译过程]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117659653</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117659653</guid><author>csy777777</author><pubDate>Mon, 07 Jun 2021 15:52:58 +0800</pubDate><description><![CDATA[前言
c++是一种编译型语言，在运行之前需要先经过编译器编译，虽然编译器由不同的厂家实现，但是他们需要遵守共同的规范，本文就介绍下c++的编译过程。
编译的四个阶段
先展示下本文实验用到的代码：
//main.cpp
#include &lt;stdio.h&gt;

int main(){
    printf ("hello, world");
    return 0;
}

预处理阶段
预处理阶段主要处理带“#”号的文件，如#include 或#define等信息，对于include的头文件，预处理]]></description><category></category></item><item><title><![CDATA[设计模式（二）：工厂模式]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117623053</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117623053</guid><author>csy777777</author><pubDate>Sun, 06 Jun 2021 13:24:51 +0800</pubDate><description><![CDATA[前言
工厂模式提供了一种创建对象的最佳方式，我们在创建对象时不会对客户端暴露创建逻辑，并且是通过使用一个共同的接口来指向新创建的对象。工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式，c++工厂模式主要利用了多态的特性，有关多态的内容可以参考c++多态。
简单工厂模式
简单工厂模式包括三个组件：

工厂类：用于创建一个指定具体实例对象。
具体产品类：工厂模式创建的对象。
抽象产品类：具体产品继承的父类或实现的接口。

可以通过一个实例来了解简单工厂模式，假设我们需要通过工厂模式生产衣服，工厂类定义为cl]]></description><category></category></item><item><title><![CDATA[虚拟地址空间（二）]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117607741</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117607741</guid><author>csy777777</author><pubDate>Sun, 06 Jun 2021 00:38:21 +0800</pubDate><description><![CDATA[前言
在我最开始写博客的时候，第一篇就介绍了虚拟地址空间，但当时受限于自己的水平，并且很多内容当时还没有介绍，所以当时写的比较简单，这篇文章算是还愿了吧。
/proc/{pid}/maps
linux的根目录下有很多目录，比如/etc通常是存放参数文件的，/bin通常存放二进制的可执行程序，/lib通常存放库文件，/include存放头文件，/proc存放的则是进程相关的文件。对每个正在运行的文件，/proc下都有一个文件名为该进程pid号的文件夹，例如有一个pid为10086的进程正在运行，那么就存在/p]]></description><category></category></item><item><title><![CDATA[快速排序及其优化]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117572819</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117572819</guid><author>csy777777</author><pubDate>Fri, 04 Jun 2021 22:11:29 +0800</pubDate><description><![CDATA[快排的原理
快排是综合性能最好的算法，也凭借优秀的性能成为常用的排序算法。快排基于分治的策略，每次选择一个基准值，将数组分为小于基准值和大于基准值两部分，然后对基准左右两侧的数组递归调用这个过程，直至找到所有元素的位置。

上面的图片展示了快排的基本过程，但问题是如何找到基准值的位置？最简单的想法是遍历所有元素，但这样就已经排好序了，失去了快排的意义。快排使用两端逼近的思路来找到基准值的位置，相关代码可以这样组织：
vector&lt;int&gt; nums//待排序数组
int pivot;   //基]]></description><category></category></item><item><title><![CDATA[死锁条件、避免、检测和解除]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117536651</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117536651</guid><author>csy777777</author><pubDate>Thu, 03 Jun 2021 23:27:35 +0800</pubDate><description><![CDATA[什么是死锁？
如果一个进程集合中的每个进程都在等待只能由此集合中的其他进程才能引发的事件，而无限期陷入僵持的局面称为死锁，例如下面的模型：

此时进程A和进程B就永远处于这个状态，称进程A和进程B处于死锁状态。上述的概念换成线程也同样适用，为叙述简洁，这里就使用进程来叙述。
死锁条件
死锁的产生必须满足四个条件：

资源互斥条件：使用资源必须是独占式地，资源本身不可分割，同一资源在某时刻至多只能被一个进程使用；
请求和保持条件：进程在请求资源时，不释放目前占有的资源；
不可剥夺条件：已经被某进程获取的资源在]]></description><category></category></item><item><title><![CDATA[epoll 的LT与ET实例]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117529589</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117529589</guid><author>csy777777</author><pubDate>Thu, 03 Jun 2021 17:26:27 +0800</pubDate><description><![CDATA[epoll的数据结构与函数
epoll需要使用struct epoll_event 来记录需要监听的事件，将需要监听的文件描述符记录在epoll_event.data.fd中，将需要监听的事件记录在epoll_event.events中，常见的监听事件包括：

EPOLLIN：读事件；
EPOLLOUT：写事件；
EPOLLRDHUP：读关闭事件，本端调用shutdown(SHUT_RD)或对端调用shutdown(SHUT_WR)；
EPOLLHUP：读写关闭事件，本端调用shutdown(SHUT_RD]]></description><category></category></item><item><title><![CDATA[select使用实例]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117456776</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117456776</guid><author>csy777777</author><pubDate>Wed, 02 Jun 2021 00:28:31 +0800</pubDate><description><![CDATA[select函数是多路复用的一种，本文我们给出一个select的通信实例，看下select的代码如何组织，先上代码：
#include &lt;unistd.h&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;sys/socket.h&gt;
#include &lt;errno.h&gt;
#include &lt;cstring&gt;
#include &lt;netinet/in.h&gt;
#include &l]]></description><category></category></item><item><title><![CDATA[五种网络IO模型]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117431653</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117431653</guid><author>csy777777</author><pubDate>Tue, 01 Jun 2021 00:38:16 +0800</pubDate><description><![CDATA[前言
网络IO指的是网络通讯时，socket读取的过程，具体包括数据从硬件接口传递到内核态，再从内核态拷贝到用户态。在服务器中存在大量的网络连接，这些网络连接带来了大量的IO消耗，因此了解网络模型对我们编写服务器程序是十分必要的。
阻塞式IO模型
在TCP（三）中，我们给出了一个利用TCP进行client-server通信的例子，在这个例子中，server调用listen后，将等待client的连接，如果没有client连接，server将一直阻塞。
这种阻塞等待IO信号的方式，被称为阻塞式IO，阻塞式IO]]></description><category></category></item><item><title><![CDATA[HTTPS]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117407522</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117407522</guid><author>csy777777</author><pubDate>Mon, 31 May 2021 00:39:07 +0800</pubDate><description><![CDATA[在TCP/IP网络模型和OSI网络模型中，已经介绍了HTTP相关的内容，但HTTP是明文传输，在网络中很容易被不法分子获取，因此现在广泛使用HTTPS协议代替HTTP协议。

HTTPS协议默认监听443端口，而HTTP协议默认监听80端口。此外，HTTPS将HTTP报文进行了加密，HTTPS报文实际上是加密后的HTTP报文，这种加密通过SSL（或TLS，TLS是SSL的正式版本）来完成，即HTTPS=HTTP+SSL。在了解SSL如何加密之前，我们先了解一下有哪些加密方式。
对称加密
对称加密指通信双方使]]></description><category></category></item><item><title><![CDATA[TCP/IP网络模型和OSI网络模型]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117407241</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117407241</guid><author>csy777777</author><pubDate>Sun, 30 May 2021 22:58:28 +0800</pubDate><description><![CDATA[网络模型的结构
OSI（Open System Interconnection）是由国际标准化组织（ISO）制定的网络模型，该模型定义了不同计算机如何互相连接，是设计和描述计算机网络通信的基本框架。OSI模型将网络通信分为7层：

OSI仅是一个理论上的模型，实际使用的是TCP/IP网络模型，TCP/IP模型将OSI模型的应用层，表示层和会话层合并为应用层：

由于TCP/IP是实际使用的模型，后续我们就以TCP/IP模型为例进行介绍，OSI也是基本相似的过程。
将网络协议分层的原因是，网络是一个非常复杂的]]></description><category></category></item><item><title><![CDATA[TCP（四）]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117402306</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117402306</guid><author>csy777777</author><pubDate>Sun, 30 May 2021 19:00:46 +0800</pubDate><description><![CDATA[前言
tcp大致的知识前面都已经介绍完毕了，本文我们再回答一些tcp的细节问题。
client连接server时，如果server未开启，或监听的端口不是client连接的端口，会发生什么事情？
我们还是使用TCP（三）中使用的server和client程序，先不启动server，仅启动client，使用wireshark抓包。

程序运行失败，error被设置为connection refused，下面我们看看wireshark：

从抓包情况来看,client向端口9007发起连接，此时操作系统为cli]]></description><category></category></item><item><title><![CDATA[TCP（三）]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117392573</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117392573</guid><author>csy777777</author><pubDate>Sat, 29 May 2021 23:45:32 +0800</pubDate><description><![CDATA[TCP server
在cs模型中，server只需要等待client的连接，因此server包括下面四个步骤：

调用socket()，初始化一个socket实例，
调用bind()，将socket绑定到网卡上，
调用listen()，等待客户端的连接，
与客户端三次握手后，调用accept()。

server的代码如下：
//server.cpp

#include &lt;unistd.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;sys/types]]></description><category></category></item><item><title><![CDATA[TCP（二）]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117382518</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117382518</guid><author>csy777777</author><pubDate>Sat, 29 May 2021 18:04:23 +0800</pubDate><description><![CDATA[前言
TCP是面向连接的协议，两个端口希望通过TCP通信时，需要在两个端口间先建立传输链路，这被称为三次握手过程，结束通信时，需要断开端口间的传输链路，这被称为四次挥手过程，本文我们来详细了解这两个过程。
三次握手
三次握手的过程可以结合下图来了解：

在第一次握手之前，client和server都处于close状态，client发起对server的连接时，将发送第一次握手请求。
第一次握手请求的内容包括syn标志位的设置和seq序列号的发送，我们在TCP(一)中介绍过，syn标志位的设置意味这这个包是用于]]></description><category></category></item><item><title><![CDATA[TCP（一）]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117338716</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117338716</guid><author>csy777777</author><pubDate>Thu, 27 May 2021 21:46:38 +0800</pubDate><description><![CDATA[前言
TCP协议是传输层的重要协议，TCP协议保证将数据包完整、可靠地送达对端，是网络中最重要的协议之一，本文我们结合TCP的首部格式来了解TCP。
TCP的首部格式
TCP首部包括20bytes的固定字段和64bytes的可选字段（如下图），16位的源端口号和目的端口号是传输层的基本要求，下面我们通过这些字段来理解TCP的机制。

应答
TCP为每个数据包添加自增的32位序列号，在接收到数据包时，TCP也需要根据包的序列号向对端发送应答，使用client-server模型，可以通过下图来表达这个过程，其中]]></description><category></category></item><item><title><![CDATA[进程调度算法]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117308062</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117308062</guid><author>csy777777</author><pubDate>Thu, 27 May 2021 00:26:57 +0800</pubDate><description><![CDATA[前言
在进程与线程中，我们介绍过进程的五种状态，还介绍了线程调度状态和调度算法与进程是一样的，本文我们就介绍一下常见的进程调度算法，当然按照我们之前的介绍，这些算法对线程同样适用。
先来先服务（First Come First Serve)
先来先服务的调度方式就和这个算法的名字一样，使用一个队列存储就绪态进程的task_struct，cpu空闲时，就从队列中取出第一个task_struct进行调度，在这个进程处理运行态时，别的进程不可抢占cpu，只能在就绪队列中等待被调度。
先来先服务算法优点是很好理解，]]></description><category></category></item><item><title><![CDATA[STL（八）：关联式容器]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117307118</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117307118</guid><author>csy777777</author><pubDate>Wed, 26 May 2021 22:25:44 +0800</pubDate><description><![CDATA[前言
关联式容器与序列式容器不同，元素插入关联式容器后，插入位置是由容器采用一定的算法计算的，与插入的时间无关。本文介绍STL中哈系表、集合和map等关联式容器。
哈希表
hashtable是SGI STL中的哈希表，标准库中使用unordered_map代替hashtable，但unordered_map也是以hashtable为基础的。哈希表是一种查找操作只需要o(1)时间复杂度的数据结构，哈希表由一串连续的的bucket构成，每个bucket上挂着一个链表，链表中储存的就是用户的数据，哈系表通过散列函]]></description><category></category></item><item><title><![CDATA[不同形态的二叉树]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117287630</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117287630</guid><author>csy777777</author><pubDate>Wed, 26 May 2021 15:55:46 +0800</pubDate><description><![CDATA[满二叉树
对二叉树来说，第i层的节点个数最多为2^(i-1)个，如果二叉树的每一层的节点个数都达到最大值，即叶子节点全部在最后一层，非叶子节点一定有左右孩子，这种二叉树称为满二叉树，下面展示了一棵满二叉树。

完全二叉树
完全二叉树的判断条件没有满二叉树那么苛刻，完全二叉树要求最下面两层的节点，可以没有孩子节点，也可以仅有一个孩子，但最下层的叶子节点必须都在左侧，比如下面的树：

需要注意最下层叶子节点必须在左侧，像下面的树违反了这个规则，不是完全二叉树：

二叉搜索树
二叉搜索树是一种非常实用的二叉树，对]]></description><category></category></item><item><title><![CDATA[二叉树]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117266421</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117266421</guid><author>csy777777</author><pubDate>Wed, 26 May 2021 00:17:58 +0800</pubDate><description><![CDATA[前言
树形数据结构是应用非常广泛的结构，包括二叉树、平衡二叉树、完全二叉树、红黑树、B树和B+树等，本文先介绍基础的树形结构——二叉树。
二叉树
二叉树是指节点可以有两个孩子节点的树型结构，其中左边的孩子节点称为左孩子，右边的孩子节点称为右孩子。

可以通过下面的结构来描述一个二叉树节点，为了数据结构的完整性，这里把构造方法也加上。
struct treeNode{
	treeNode *left;
	treeNode *right;
	int value;
//构造函数
	treeNode():value]]></description><category></category></item><item><title><![CDATA[STL（七）：heap和priority_queue]]></title><link>https://blog.youkuaiyun.com/csy777777/article/details/117265179</link><guid>https://blog.youkuaiyun.com/csy777777/article/details/117265179</guid><author>csy777777</author><pubDate>Tue, 25 May 2021 21:37:04 +0800</pubDate><description><![CDATA[前言
终于快写完序列式容器了！剩最后两个heap和priority_queue，这篇一起写完，明天要开始关联式容器了。
heap
heap是STL中的堆数据结构，堆其实是一种完全二叉树，即非叶子节点的左右孩子必不为空的二叉树。堆分为最大堆和最小堆，最大堆的特点就是堆顶的元素必定是所有元素中的最大值，而最小堆的特点就是堆顶元素的值必定是所有元素中的最小值，比如下面的结构就是一个最大堆。

STL底层使用vector来储存堆中的元素比如图中的最大堆会被储存为[23, 20, 13, 3, 10, 4]，这是由于]]></description><category></category></item></channel></rss>