自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(365)
  • 收藏
  • 关注

原创 Linux网络编程之端口复用 Address already in use

为什么需要端口复用我们直到,TCP连接在进行4次挥手断开连接时,为了确保最后一次ACK到达对端,保证对端正确关闭资源,以防止对傻傻等待浪费网络和计算机资源,要求等待2MSL时常,那么对于我们需要立即重启程序的情况不友好,有过经验的朋友都知道,我们关闭一个链接,然后立马重启这个连接,一般会报bind失败:虽然这个图是客户端主动断开连接,实际服务端主动断开也是一样的过程bind error: Address already in use表示端口号正在被占用,因为前一次的链接还没有被完全释放,通过指令可

2021-05-10 07:41:20 36

原创 IO多路转接epoll函数解析复习

函数原型:open an epoll file descriptor: 打开一个epoll文件系统#include <sys/epoll.h>int epoll_create(int size);参数:在内核中开辟一块内存,创建一个epoll文件系统(也叫内核事件表、是一棵红黑树),参数size是对内核的一个建议,但是一定要比0大,不一定起作用,表示监听的文件描述符个数,也就是基础红黑树的建议大小。返回值:ret > 0 返回一个可用,合法的文件描述符,表示创建的epo

2021-05-09 17:38:38 18

原创 IO多路转接之poll函数解析

函数原型:#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);返回值:ret > 0 ,表示有事件发生的文件描述符的个数,可以去遍历fds,看哪个fd发生事件,并且根据对应的revent做下一步处理ret == 0,表示超时,且还没有事件发生ret<0,表示失败,可以根据全局变量errno来判断下一步的动作参数解析:struct pollfd *fds:是一个数组,将所有

2021-05-09 14:33:27 15

原创 数据结构与算法之排序方法分类

按照存储介质分内部排序:数据量不大,数据都在内存中,无需内外存进行交换数据外部排序:数据量较大,数据在外存,排序时需要将数据换入换出内存按比较器个数分串行处理:单处理机 同一时刻比较一对元素并行处理:多处理机 同一时刻比较多对元素按主要操作分比较排序:用比较的方法,如插入排序,交换排序,选择排序,归并排序基数排序:不比较元素的大小,仅仅根据元素本身的取值确定其有序的位置按照排序所需辅助空间可分为:原地排序:空间复杂度为O(1),空间复杂度不会随着数据量的增大而增大非原地排序:超过O(1

2021-05-07 08:08:39 14

原创 OS内存管理之页面置换

前面讲到,我们需要将一些页面加载到内存,此时刚好内存上没有可用的物理内存编号,这个时候就需要将一些页面置换到磁盘让出位置。置换的基本策略:置换最近不可能访问的页根据局部性原理,基于过去的行为来预测将来的行为。策略设计太简单,实行起来可能会很低效,如果过于精密和复杂,软硬件开销也会更大,一般需要折中。页框锁定:一些页框是绝对不允许被置换出去的,否则会出错或者影响效率,如:操作系统核心代码关键数据结构正在进行IO操作缓冲区等我们需要将这些页面锁定,不让操作系统对这些页面进行置换或者延迟进

2021-05-06 23:13:15 21

原创 基本内存管理方案2---一个进程进入内存中若干不连续的区域(页式,段式,段页式)

页式设计思想:将用户进程地址空间划分为大小相等的页、页面(一般为4K,也有4M的),并从0开始编号将物理内存地址空间划分为大小相等的区域,称为页框,也从0开始编号,也叫做物理页面,页帧,内存块以页为单位进行分配,按照进程所需要的页数来分配,进程地址空间上相邻的页,映射到物理内存上,页不一定相邻。**逻辑地址:**页号(20,页面的编号) + 页内地址(也叫页内偏移,12位)页表:记录了逻辑空间某页面对应在物理地址空间上是哪一页页表项:页表的每一行称为页表项,记录逻辑页号和物理页号的对应关系

2021-05-06 22:37:22 10

原创 OS内存管理之虚拟存储技术

概念:当进程运行时,先将其一部分数据和代码装入内存,另外一部分暂留在磁盘,当要执行的指令或者访问的数据不在内存时,由操作系统自动完成将它们从磁盘上调入内存中运行。注意:与交换技术不同,交换技术是将某一个进程换入换出,这里虚拟存储技术换入换出的粒度更加小了。虚拟地址空间:给进程分配的虚拟内存虚拟地址:虚拟内存上数据或者指令的地址,该位置可以被访问,仿佛就是内存的一部分。虚拟内存在哪里:把内存与磁盘有机的进行结合起来使用,从而得到一个容量很大的"内存",即虚拟内存虚拟内存是对内存的抽象,建立在金

2021-05-06 22:33:56 9

原创 OS内存管理之Page fault

可能产生异常的情况:需要的访问虚拟页面没有调入内存 — 缺页异常页面访问违反权限错误的访问地址…缺页异常处理主要过程:产生异常操作系统调用异常处理程序获取磁盘地址启动磁盘将该页调入内存:内存有空闲页框,分配,然后直接调入该页面;内存没有空闲页框,将内存中的某个不常用的页框置换出去(需要看具体的页面置换算法),检查该置换页面是否被修改过,如果修改过需要写入磁盘如果没有修改,直接调换出去,将我们需要加载的页面调进内存。...

2021-05-06 22:26:54 8

原创 OS内存管理之快表(TLB)的引入

在前面的文章中,讲到操作系统的多级页表映射:多级页表文章背景我们知道,要从虚拟地址转换成一个物理地址,需要访问多次内存查页表,比如2级页表,需要访问2次内存,4级页表,查询需要访问4次内存,这也是一笔不小的开销,这样会让CPU真正执行指令的时间缩短,导致CPU的超高速度优势利用不充分。快表应运而生原理:程序访问的局部性原理,对于一些指令和数据访问,在一段时间内总是高度的频繁本质:Translation Look-aside Buffers实际上就是一个缓冲区,实际上是CPU的高速缓存,可以缓解

2021-05-06 22:15:27 9

原创 OS内存管理之页表,页表项以及页目录

页表由多个页表项组成,即页表中每一行的就是一个页表项。页表项中记录的信息:页框号:记录虚页面对应的具体哪个物理页面有效位:标识该页表项对应的虚页面有没有读进内存,否则在磁盘访问位:引用位,标识该页面有没有被访问过修改位:此页面在内存中有没有被修改过,如果被修改过,将来是要被持久化到磁盘上的,该标志位就是这个目的保护位:标识该页面的读写等权限页表项一般是由硬件设计的,因为地址转换时大多数是由硬件完成的。引出页目录:对于32位虚拟地址空间,假设页面大小为4K,页表项大小为4字节:一个进程

2021-05-06 21:47:27 13

原创 OS内存管理之交换技术

产生背景:进程的地址空间大于物理地址空间,即在较小的内存空间运行较大的进程。内存"扩充"技术:1.内存紧缩技术(可变分区)可变分区概述2.覆盖技术:根据程序的逻辑来选择,一些段永远不会同时出现在内存中,假设有段A和段B,他俩永远不会同时加载到内存上运行,那么A和B就可共享某一段物理内存,进行交替的使用物理内存。这就需要程序员显式的声明覆盖结构,比较老的技术了,适用于早期的某些操作系统。3.交换技术:虚拟内存的初步设计,当内存空间紧张时,系统将一些进程暂时移动到外存,把外存中某些进程换进内

2021-05-06 07:48:58 27

原创 基本内存管理方案1---整个进程进入内存的一片连续的区域

单一连续区一段时间内,只有一个进程在内存内优点:简单缺点:内存利用率低固定分区把内存空间先分割成若干区域,称作为分区。每个分区的大小可以相同,也可以不同一旦确定,分区大小固定不能变了每个分区装一个且只能装一个进程进程装载时,根据自身所需空间大小,向操作系统进行申请,然后去相应合适分区进行排队。可变分区根据进程的需要,把内存空闲空间分割出一个分区,分配给该进程,剩余的部分成为新的空闲分区运行一段时间后,可能造成下列布局:缺点:造成大量的内存碎片(外碎片)解决方案:碎片紧缩

2021-05-05 21:38:05 10

原创 Linux伙伴系统内存分配原理概述

简介:Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担.,该算法由Knowlton设计, 后来Knuth又进行了更深刻的描述.核心思想:将内存按2的幂进行划分,组成若干空闲链表;查找该链表找到能满足进程需求的最佳匹配块。算法基本步骤:将整个可用的内存空间看做一个整体,大小为: 2^u(2的u次方)假设现在一个进程申请的空间为s:如果满足2^(u-1) < s <= 2^u,那么就将这整块内存分配给该进程否则,就将这

2021-05-05 19:19:26 25 1

原创 C++STL容器迭代器失效问题

本文拿std::vector来举例说明,什么是迭代器失效:拿两个代码片段来说明迭代器失效现象:int main(){ vector<int> vec; for(int i = 0;i < 20 ;++i){ vec.push_back(rand()%100); } //打印一下 for(const int v:vec){ std::cout<<v<<" "; } std::c

2021-05-04 21:11:36 31

原创 C++运算符重载中有些方法为什么需要定义为友元函数

C++提供运算符重载主要目的:希望对象之间的运算看起来可以和编译器内置类型一样丝滑;相当于是告知编译器,类对象之间运算应该如何去做处理。通过实现一个复数类,来阐述本文章的主题:class Complex{public: Complex(int r = 1,int i = 1):real_(r),image_(i){} ~Complex(){} void print(){ std::cout<<"real_= "<<real_&lt

2021-05-04 17:12:54 28

原创 TCP可靠传输的实现

TCP基于以字节为单位的滑动窗口来实现可靠传输

2021-05-03 22:08:14 11

原创 TCP连接的建立与释放过程

TCP连接需要解决的问题需要让通信双方能感知到对方的存在过程中需要协商一下一些参数,如最大窗口值,时间戳选项,服务质量等双方能够对运输实体资源(如数据缓存大小,连接表中的项目等)进行分配三次握手的具体过程:能否使用2次握手:不行这里假设2次握手后,双方就处于连接建立状态:ESTABLISHED客户端向服务端发送连接建立请求报文A,但是A报文由于某些原因在网络中滞留超时客户端超时重传请求报文B,此时报文B到达服务端,服务端返回报文B的确认报文此时双方建立连接,然后进行数据传输,数据传

2021-05-03 22:07:41 49

原创 TCP超时重传时间的选择

RTT:假设A向B发送数据,我们将A的数据发送出去到A收到B的确认报文的这段时间就成为RTT时间。超时重传时间(RTO)的选择:1.假设选择RTO小于RTT时间:假设A向B发送数据,此时网络正常,没有发生异常,还没等一个RTT时间到,也就是B给A的确认报文还在网络上正常传输呢,超时重传定时器就到期了,造成分组的重传,不必要的分组在网络越来越多,影响网络整体的性能。2.假设选择RTO比RTT大的比较多呢:假设A向B发送数据,此时网络有点波动,导致报文B向A确认的报文丢了,然后A等了很久,超时定时器

2021-05-03 20:59:33 31

原创 TCP的拥塞控制

网络拥塞:网络中的输入,超出了某一网络资源(交换节点缓存,处理机,带宽等等都是)所能提供的服务的能力,网络性能就会变差,大量数据分组被丢弃,直观感受是变卡。如果不对网络拥塞进行控制,整个网络吞吐量会不断的随数据输入而下降。四种拥塞控制算法:拥塞窗口是多少,就能发送几个报文段。慢开始即一开始向网络注入的报文少一些,假定这里的ssthresh = 16.即刚开始将cwnd值置为1:此时只能发送一个报文,收到B的确认报文后cwnd = cwnd +1此时cwnd = 2,给B继续发送2个报文,

2021-05-03 20:34:45 36 1

原创 TCP的流量控制---滑动窗口

流量需要控制的原因:发送方发送太快,接收方来不及接收,导致数据的丢失,引起性能下降。流量控制:让发送方发送效率不要太快,要让接收方来得及接收,整个过程是接收方(接收窗口)和发送方(发送窗口)一个动态协商的过程。滑动窗口机制A对B发送数据,B需要对A进行流量控制,B主机告诉A最多能接收几个窗口的数据,主机A会调整相应发送窗口大小。整个过程中,经过B确认收到后的数据,A可以直接将自己缓存的部分进行删除,移出滑动窗口,,如果没有收到B的确认,否则不能删除,万一出现差错,数据还需要重新发送给B。持续

2021-05-03 16:59:54 33

原创 运输层TCP与UDP的区别

运输层端口号:标识通信进程端口号屏蔽了不同操作系统上的进程不同实现的差异,取值范围0-65535熟知端口号:0-1023,FTP:21/20 HTTP:80 DNS:53登记端口号:1024-49151短暂端口号:49152-65535,留给客户进程选择暂时使用,标识了主机上进行通信的一个进程面向连接的TCP:TCP报文段必须先进行三次握手逻辑连接,结束通信需要四次挥手释放逻辑连接;TCP仅支持单播,即一对一通信;面向字节流的,无规则无边界;不会出现传输差错,误码,丢失,乱

2021-05-03 16:33:26 8

原创 路由选择协议

静态路由配置人工的通过一些指令设置网络所需的路由表,适用于一些比较小的网络结构中。动态路由配置通过一些算法,自动调整更新路由表,能较好的适应网络状态的变化。因特尔分层路由选择协议常见的路由选择协议...

2021-05-02 22:20:32 15

原创 IP数据报的发送和转发过程

源主机如何判断目标地址在不在同一个网络中:假设主机C要给F发送数据,主机C用自己的ip地址和子网掩码进行相与得出主机C所在网络的网络地址主机C再用主机F的ip地址与当前的子网掩码相与得出得出主机F所在网络的网络地址如果这两个值相同,可以证明在一个网络中,直接交付即可。如果值不同,则说明没有在同一网络,需要间接交付,通过路由器的转发。直接交付间接交付:需要通过路由器进行转发期间,如果报文出错,会向源主机发送ICMP差错报文主机C如何知道向哪个路由器发送数据呢?默认网关,这里指的是接口0

2021-05-02 22:06:30 43

原创 虚继承解决菱形继承等不友好设计的问题

假如没有虚继承对于菱形继承等多重继承中,对象继承时,会有大量的重复的数据的继承,浪费内存,影响性能。class A{public: A(){} ~A(){}protected: int a;};class B:public A{public: B(){} ~B(){}protected: int b;};class C:public A{public: C(){} ~C(){}protected: int c

2021-05-02 21:03:57 18

原创 C++虚基类以及可能引发的一些问题

什么是虚基类:当一个类被派生类用virtual继承时,这个基类就叫做虚基类c++中virtual有两个作用,一个是修饰虚函数,另外一个就是这里修饰继承方式下面例子中A就是一个虚基类:class A{public:protected: int ma;};//虚继承,此时A被称为虚基类class B:virtual public A{public:protected: int mb;};虚基类和抽象类有什么区别:抽象类指的是,类中存在纯虚函数,即函数名=0这样的函数

2021-05-02 20:21:28 37 1

原创 观察者模式 Observer

行为者模式:关注对象之间的通信观察者模式 叫观察者-监听者模式 也叫发布-订阅模式,简单来说多个对象行为依赖一个对象状态,该对象改变时,其他对象都能接收到相应的通知,以便采取相应的动作处理数据。举个例子:一组数据(一个数据对象): 当该数据对象中的数据成员发生变化时 应该及时通知这些对象 曲线图对象 柱状图对象 圆饼图对象等 ,保证他们采取相应的动作。实例:观察者:class Observer{public: //处理消息的接口 virtual void handle(co

2021-05-02 08:09:32 23

原创 适配器模式 Adapter

背景适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。再比如,我们实际开发工作中,可能会大量的使用到第三方库,往往就要去做一些接口适配的工作,设计一些适配类。举个生活中的例子你就明白了:我们轻薄笔记本与投影仪,要想将我们轻薄本和投影仪相连,往往需要一个转接头(适配器),因为一般投影仪要么是VGA要么是HDMI,但是轻薄本一般为了厚度,舍弃了这些接口,保留类似与Type-c一些比

2021-05-01 22:15:02 32

原创 装饰器模式 Decorator

简介:是一种结构型模型,创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。也不想/不能继承已有功能,在子类扩展,那么装饰器应运而生。应用场景:举个例子,目前我所在的公司是为各大车厂做一些辅助驾驶功能的,基本是在L2级别的功能,比如HWP ACC AEB .假设现在一些车厂找我们公司合作,希望将我们的某些辅助功能加到他们的车上:0.汽车基类:#include <iostream>#include <memory>class Ca

2021-05-01 19:06:01 26

原创 代理模式 Proxy

含义解释:有这样一个类,他可以做很多事情,但是他不希望客户可以直接他交互所以事宜(调用他的所有方法),所以该类(叫委托类)就 委托 代理类帮他来对客户进行“把关”,什么样的客户可以和我交流什么样的事宜(可以调用对应的哪部分方法),由代理类的实现决定。实例:经常追剧的小伙伴,对应某些视频网站的vip机制或者超前点播机制搞得有点头疼,有没想过他的实现机制可能是什么样的,今天借着学习总结的代理模式的机会,进行一下实操:1 . 委托类的实现,具备三种功能,可以看三类型视频://基类class Video

2021-05-01 12:35:39 34

原创 抽象工厂AbstractFactory

简单工厂实例工厂方法实例抽象工厂的适用场景:首先区别于工厂方法,工厂方法是针对每一个产品都去"建一个工厂",每添加一个新产品,就新建一个工厂,当产品特别多时,工厂会越来越多,我们的代码会越来越丑。抽象工厂针对的**是一组产品,他们是有关联关系的一组产品,**又叫产品簇。举个例子:手机制造商,制造一部手机设计多个产品,如屏幕,电源适配器,电池,耳机,转接器,存储介质等等一系列,来看下面这个实例:在抽象工厂中,不在对每一个产品进行单独的建工厂生产,而是 统一 到一个工厂中,因为他们是一组关联产品。#

2021-05-01 11:20:45 17

原创 除了加锁还可以这样写一个线程安全的单例模式(局部静态对象和std::call_once)

1. linux x86平台上局部静态对象构造是线程安全的class Singleton{public: static Singleton*GetInstance(){ //函数静态局部变量的初始化,汇编指令上已经自动添加了互斥指令了,所以这里是线程安全的 static Singleton instance; return &instance; }private: Singleton(){} Singleton(c

2021-04-30 23:09:28 16 1

原创 单例模式-懒汉式及其线程安全问题

所谓懒汉,讲的是对象的构造实在第一次调用获取对象接口时才进行构造的class Singleton{public: //非可重入函数 static Singleton*GetInstance(){ if(instance == nullptr){ instance = new Singleton(); } return instance; }private: static Singleton *ins

2021-04-30 23:02:38 19

原创 使用std::make_shared去构造智能指针

class Test{public: Test(int b):a(b){} ~Test(){}private: int a;};用std::shared_ptr管理资源时,常用的两种构造方式:1.直接newint main(){ std::shared_ptr<Test> p(new Test(1)); return 0;}2.使用std::make_shared:int main(){ std::shared_ptr<

2021-04-30 22:18:03 33

原创 C++11判断一个函数对象std::function是否可调用operator bool()

判断一个函数对象是否可调用: operator bool()返回true证明对象可调用#include <functional>#include <iostream>using Task = std::function<void()>;template<typename T>void CallTaskFunc(const T&f){ if(f.operator bool()){ f(); }else{

2021-04-30 21:57:16 26

原创 C++11中is_same使用

使用场景:我们在写模板代码时,希望对于某些类型做不同处理,需要对实参类型进行一个判断,std::is_same是个不错的选择。实例:假如,用户用int类型去实例化该模板,我希望做一些特殊操作,代码可以这样写:#include <iostream>#include <type_traits>template <typename T>void fun(T a){ if(std::is_same<T,int>::value){

2021-04-30 21:20:37 38

转载 模板特例化与偏特化

模板是C++中一个很重要的特性,写一份代码能用于多种数据类型(包括用户自定义类型)。例如,STL的sort()函数可以用于多种数据类型的排序,类stack可以用作多种数据类型的栈。但是,如果我们想对特定的数据类型执行不同的代码(而不是通用模板)呢?这种情况下就可以使用模板特例化(template specialization)。一、函数模板特例化当特例化一个函数模板时,必须为原模板中的每个模板参数都提供实参。使用关键字template后跟一个空尖括号<>,即template <>

2021-04-29 22:21:36 18

原创 c++11中shared_from_this的使用情景与案例

class C{public: C(int b=10):a(b){ cout<<"construct"<<endl; } ~C(){ cout<<"destruct"<<endl; } void show()const{ cout<<"a = "<<a<<endl; } C*object_ptr(){ return this; }private: int a;};使用场景:

2021-04-29 22:06:09 14

原创 记录几个C++智能指针shared_ptr常用方法

#include <memory>#include <iostream>using namespace std;class Test{public: Test(int b=10):a(b){ cout<<"construct"<<endl; } ~Test(){ cout<<"destruct"<<endl; } void show()const{ cout<<"a = "<<a

2021-04-29 21:28:39 13

原创 gdb调试传参args

假设我们的可执行程序是worker,gdb时需要传递参数arg1和arg2,有3种方式:gdb --args worker arg1 arg2或者我们先启动gdb:gdb worker//进入gdb界面,然后设置参数set args arg1 arg2查看我们传递参数:show args或者我们在run指令后面直接跟参数就行gdb workerr arg1 arg2...

2021-04-28 21:11:34 22

原创 C++常成员方法与静态成员方法

class C{public: C(int val){} ~C(){} C() = default; void show(){ std::cout<<"C *this"<<std::endl; } void show()const{ std::cout<<"const C *this"<<std::endl; } static void test(){

2021-04-27 21:46:31 14

空空如也

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人 TA的粉丝

提示
确定要删除当前文章?
取消 删除