自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Go语言context包源码剖析

context包主要提供了两种方式创建context是上下文的默认值,所有其他的上下文都应该从它衍生(Derived)出来。应该只在不确定应该使用哪种上下文时使用;在大多数情况下,我们都使用作为起始的上下文传递上面的两种方式是创建根context,不具备任何功能,具体实践还是要依靠context}) Contextcontext。

2023-01-06 13:23:57 740 3

原创 手写RPC框架(一)服务端与消息编码

消息的decode和encode的方式有很多,例如json,xml,protobuf 包括go特有的gob,所要实现的框架需要可以做到让用户自主选择编码方式。为了实现不同的Codec实例,先对消息体编解码的接口进行抽象,抽象出Codec

2022-12-25 21:41:02 936

原创 C++中istream_iterator和ostream_iterator的源码分析

在一篇博客当中无意间发现了和的使用,感觉用法很神奇,就专门去研究了一下,觉得还挺有意思的,所以就专门写了一篇博客来聊聊这两个迭代器的实现,一下为gnu2.9版本的源码。

2022-12-02 09:43:21 881

原创 设计者模式(1)观察者模式 (Observer)C++11实现

观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。该模式属于行为型模式。

2022-12-01 21:03:21 1126

原创 muduo库中实现Protbuf编码器与消息分发器

(因为很多场景下并不需要消息的长度和类型,所以protobuf序列化并没有包含这些,若在某些需要的场景下,可以在用户层自己实现就可以)根据规定好protobuf的传输格式,就可以进行书写了,过程十分简单,照着传输格式一步一步来就行。消息类型有很多种,服务器需要根据不同的消息类型去调用不同的回调处理函数,这就是消息分发器的用处。接收消息时,将Buffer根据自定义的protobuf传输格式,转化为message对象。因为一系列因素,protobuf的默认序列化格式是没有包含消息的长度和类型的。

2022-11-26 20:34:38 945

原创 muduo库的高性能日志库(五)——AsyncLogging文件

这一部分就是muduo库之所以十分高效的原因,将前端与后端联系起来,实现了多生产者单消费者的异步网络日志库。在多线程服务器程序当中,是必须的,因为如果在网络IO线程或业务线程中直接往磁盘写数据的话,写操作偶尔可能阻塞长达数秒之久。这可能导致请求方超时,或耽误发送心跳消息,在分布式系统过更可能发生连锁效应。因此在正常的实现业务处理流程中应该彻底避免磁盘IO,这在模型的非阻塞服务端程序中尤为重要。

2022-11-21 08:25:26 434

原创 muduo库的高性能日志库(四)——LogFile文件

1. 在AppendFile类在构造时将文件的默认缓冲区设置为本地缓冲区 ```为什么要这样做?能带来什么样的性能优势?```2. AppendFile中写函数采用的是fwrite_unlock函数,非线程安全的写函数,在LogFile设计写的时候又设计成是否使用互斥锁,调用AppendFile中的append函数。```为什么不直接采用线程安全的fwite函数?这样的做的优势体现在哪?```

2022-11-19 22:24:08 1067

原创 muduo库的高性能日志库(三)——Logging文件

接下看一下Logging文件,该文件主要负责全局日志级别,输出目的地设置Logger内有两个内部类SourceFile,主要负责获取文件名Impl,实际用于日志消息的处理类。

2022-11-17 22:04:15 581

原创 muduo库的高性能日志库(二)——LogStream文件

该文件下有三个类如下图所示复杂的C/C++代码很可能会包含错误,并且在编写代码后尝试对其进行测试类似于在大海捞针。一种更审慎的方法是通过添加专门针对特定区域的小型(单元)测试来测试编写的各个代码段,例如,一些计算密集型C函数或某些C++类声称对某个数据结构进行建模,例如队列。然后,以此理念构建的回归套件将具有单元测试的集合以及运行测试并报告结果的测试驱动程序。

2022-11-17 11:46:17 940

原创 muduo库的高性能日志库(一)

日志”即文本,供人阅读的日志,通常用于故障诊断和追踪,也用于性能分析服务端编程,日志必不可少,生产环境中应做到"Log Everything All The Time"。muduo日志库采用C++的stream

2022-11-16 19:48:07 600 1

原创 xv6源码阅读——文件系统

buffe catch 的两个任务1.同步对磁盘块的访问,以确保磁盘块在内存中只有一个副本,并且一次只有一个内核线程使用该副本2.缓存常用块,以便不需要从慢速磁盘重新读取它们对上提供的接口bread() ,获取一个磁盘块,拷贝到缓存中bwrite(),将缓存中的数据写回磁盘brelse(),用完需要释放缓存快通过给每一个 buffer 分配一个 sleeplock 的方式实现一个磁盘块的拷贝只能被一个内核线程使用。

2022-09-27 20:37:02 2018 1

原创 xv6源码阅读——进程切换

通过中断机制,从trap机制进入内核线程调用swtch从该进程进行上下文切换,切换到到调度进程通过调度进程切换到新进程的内核线程在通过trap机制返回到新进程用户线程上面过程就简单阐述,是怎样进行进程切换的当然,里面会有很多细节,后面会详细介绍。

2022-09-22 01:34:55 792

原创 [mit6.s081] 笔记 Lab7: Multithreading

本实验将使您熟悉多线程。您将在用户级线程包中实现线程之间的切换,使用多个线程来加速程序,并实现一个屏障。Attention在编写代码之前,您应该确保已经阅读了xv6手册中的“第7章: 调度”,并研究了相应的代码。

2022-09-20 18:39:01 530 1

原创 xv6源码阅读——中断与异常

每个RISC-V CPU都有一组控制寄存器,内核通过向这些寄存器写入内容来告诉CPU如何处理陷阱,内核可以读取这些寄存器来明确已经发生的陷阱。RISC-V文档包含了完整的内容。riscv.h(kernel/riscv.h:1)包含在xv6中使用到的内容的定义。stvec:内核在这里写入其陷阱处理程序的地址;RISC-V跳转到这里处理陷阱。sepc:当发生陷阱时,RISC-V会在这里保存程序计数器pc(因为pc会被stvec覆盖)sret(从陷阱返回)指令会将sepc复制到pc。

2022-09-19 17:05:15 1263

原创 xv6源码阅读——虚拟内存

我们在这里看到了一些使用页表的很好的例子。首先,不同进程的页表将用户地址转换为物理内存的不同页面,这样每个进程都拥有私有内存。第二,每个进程看到的自己的内存空间都是以0地址起始的连续虚拟地址,而进程的物理内存可以是非连续的。第三,内核在用户地址空间的顶部映射一个带有蹦床(trampoline)代码的页面,这样在所有地址空间都可以看到一个单独的物理内存页面。Xv6为每个进程维护一个页表,用以描述每个进程的用户地址空间,外加一个单独描述内核地址空间的页表。然后,它将PTE添加到进程的页表中,指向新的物理页面。

2022-09-07 20:35:27 1588 1

原创 [mit6.s081] 笔记 Lab3: page tables

这个实验,我们可以了解page table的实现机制,理解源码后,做起来还是相对容易的。

2022-09-07 01:50:58 2231

原创 xv6源码阅读——xv6的启动,进程初识

注意由于只有一个内核栈,内核栈部分的地址空间可以是固定,因此 xv6 启动的时候并没有开启硬件支持的 paging 策略,也就是说,对于内核栈而言,它的物理地址和虚拟地址是一样的。当 xv6 的系统启动的时候,首先会启动一个引导加载程序(存在 ROM 里面),之后装载内核程序进内存。在xv6中进程会有5中状态。在机器模式下,CPU是从。寄存器mstatus。寄存器mstatus。...

2022-09-01 16:57:47 1066 1

原创 [mit6.s081] 笔记 Lab2:system calls

这个实验相较于上一个实验,难度加大了好多,主要难点就在于阅读源码。刚开始做lab1时很蒙,不知道要干哈。在看了相关的xv6文档,视频课程,阅读部分源码和查阅资料后,才有头绪完成了该实验,收货还是很大的。后面实验肯定会越来越难,要继续坚持下去。...

2022-08-31 20:45:08 878

原创 [mit6.s081] 笔记 Lab1: Unix utilities | Unix 实用工具

准备环境,编译编译器、QEMU,克隆仓库,略过。

2022-08-29 18:00:02 607

原创 AVL树的学习

AVL树在二叉搜索树的基础上引入了平衡因子的概念平衡因子=左子树高度-右子树高度注:若子树为null则高度视为0当平衡因子的绝对值

2022-08-03 15:55:34 225 2

原创 TCP详解

如果发送者发送数据过快,接收者来不及接收,那么就会有分组丢失。为了避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。流量控制根本目的是防止分组丢失,它是构成TCP可靠性的一方面。........................

2022-07-28 14:06:24 3213 3

原创 二叉搜索树

搜索二叉树满足一下条件:树的构建查找操作二叉搜索树最大的优点在于他的查找速率很高所要查找的值:val所在节点的值:dataeg: 在下面树的上查找 16(val==16)过程如下:1.当dataval时,所要查找的值在该树的左子树上,进入左子树继续查找。3.3.当data==val时,该节点就是所要查找的节点。代码实现递归版因为当这棵树特别庞大时,递归可能会导致栈溢出的问题并且递归相对于循环效率要...

2022-07-13 20:24:12 360 1

原创 二叉树再学习

一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。二叉树作为树的一种,是一种重要的数据结构,二叉树中的面试题比较常见的题型大概有下面几个:创建一颗二叉树(先序,中序,后序)、遍历一颗二叉树(先序,中序,后序和层次遍历)、求二叉树中叶子节点的个数、求二叉树的高度、求二叉树中两个节点的最近公共祖先、打印和为某一值的全部路径、求某一节点是否在一个树中等等。二叉树节点BinTreeNode:二叉树:BinTree创建二叉树我们以#代替空指针3 7

2022-07-13 09:54:33 111

原创 OSI参考模型

OSI参考模型,应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

2022-07-12 02:12:23 627

原创 TCP 数据粘包问题的处理

TCP是传输层的协议,它是一个面向连接,安全的,流传输协议。因为数据传输基于流的所以发送端和接收端每次处理的数量,处理数据的频率是不对等的,传递的数据是没有消息边界的。根据上面的描述,我们可能遇到如下情况1.一次接收到客户端发送过来的一个完整的数据包2.一次接收到客户端发送的N个数据包,因为每个包长度不定,无法将每个数据包拆开3.一次接受到一个或者多个数据包+下一个数据包的一部分,无法将数据包拆开4.一次收到半个数据包,下一次接收数据的时候收到剩下的一部分+下一个数据包的一部分,当然这种情况更难拆包

2022-06-15 14:53:48 913 5

原创 描述符就绪条件

可读性和可写性对于普通文件这样的描述符显而易见,但我们需要对select返回套接字“就绪”的条件需要明确讨论以下四点满足一点即可一.“监听socket”:该套接字是一个监听套接字且已完成的连接数不为0。而这样的套接字处于可读状态,是因为套接字收到了对方的connect请求,执行了三次握手的第一步:对方发送SYN请求过来,使该方监听套接字处于可读状态;通常情况下,对这样的套接字执行accept操作不会阻塞;二.“已连接socket”:该套接字的接收缓冲区中的数据字节大于等于该套接字的接收缓冲区低水位标记的当前

2022-06-08 18:35:45 175

原创 epoll的两种模式和epoll反应堆

边缘触发只有数据到来才触发,不管缓存区中是否还有数据。当被监控的文件描述符上有可读写事件发生时,epoll_wait() 会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太大),那么下次调用 epoll_wait() 时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!Level Triggered (LT)水平触发只要有数据都会触发(默认就是水平触发)。当被监控的文件描述符上有可

2022-06-08 11:38:11 309 9

原创 C语言线程池

线程池什么是线程池为什么要使用线程池线程池的工作流程图任务队列线程池的创建线程池的初始化工作者添加任务线程池的销毁完整代码threadpool.hpthreadpool.c总结什么是线程池线程池就是一个容纳多个线程的容器,对于一线线程我们可以多次对此线程进行重复使用,从而省去频繁创建线程对象的操作。为什么要使用线程池频繁的进行进程的创建与销毁将带来很多开销。不但如此,进程间频繁的切换也将减低 CPU 的利用率。 如果能复用之前创建的进程,而不是为每个并发任务创建一个进程,能有效降低进程创建与销毁的开

2022-05-24 21:23:53 3781 5

原创 线程学习笔记总结

进程:有独立的进程地址空间,有独立的PCB线程:没有独立的地址空间,是共享的,有独立的PCBLinux下,线程是最小的执行单位,进程是最小的分配资源的单位LWP: 轻量级进程也就是线程命令 ps -Lf pid 可以查看该进程的线程号线程创建 int pthread_create(pthread_t *thread, //传出参数,表示创建的线程的线程id const pthread_attr_t *

2022-05-09 19:41:22 447 3

原创 线程同步的四种方法

线程同步线程同步,指的是一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。多个控制流,共同操作一个共享资源的情况,都需要同步数据混乱原因1.资源共享(独享资源不会)2.调度随机(意味着数据访问会出现竞争)3.线程间缺乏必要同步机制restrict关键字用来限定指针变量,被该关键字限定的指针变量所指向的内存操作,必须由本指针完成互斥锁pthread_mutex_t lock;//创建锁pthread_mutex_init();//

2022-05-03 17:33:36 2400 5

原创 生产者消费者问题

文章目录问题概述单生产者单消费者队列思路概述代码多生产者多消费者队列(这里以3个生产者3个消费者为例)思路概述代码问题概述生产者消费者共享缓冲区,生产者向缓冲区中放数据,消费者从缓冲取中取数据,当缓冲区中被放满时,生产者线程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲取中没有数据时,消费者线程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。单生产者单消费者队列思路概述使用队列的方式来存储产品,创建

2022-05-02 22:55:44 577 3

原创 信号深入学习

目录信号机制信号特质信号产生以及处理方式信号处理方式阻塞信号集和未决信号集阻塞信号集(信号屏蔽字)未决信号集信号查看信号机制A给B发送信号,B收到信号之前执行自己的代码,收到信号后,不管执行到程序的什么位置,都要暂停运行,先去处理信号,处理完毕后再继续执行程序。与硬件中断类似——异步模式。但信号是软件层面上实现中断。信号特质由于信号是通过软件方法实现,其实现手段导致信号有很强的的延时性。但对于用户来说,这个延迟非常短,不易察觉每个进程收到的所有信号,都是由内核负责发送的,内核处理。信号共

2022-04-21 01:02:43 455 2

原创 Linux命令myshell的自我实现

myshell打造一个绝无伦比的 xxx-super-shell (xxx 是你的名字),它能实现下面这些功能:要求:Example知识要点参考资料代码实现打造一个绝无伦比的 xxx-super-shell (xxx 是你的名字),它能实现下面这些功能:实现 管道 (也就是 |)实现 输入输出重定向(也就是 < > >>)实现 后台运行(也就是 & )实现 cd,要求支持能切换到绝对路径,相对路径和支持 cd -屏蔽一些信号(如 ctrl + c 不能终止)界

2022-04-19 16:43:47 681 3

原创 inode详解

什么时inode?理解inode,要从文件储存说起。文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件

2022-03-28 13:12:47 9310 5

原创 Linux命令pwd的自我实现

mypwd参考资料pwd概述pwd的工作原理所要用到的函数分析(运行的步骤逻辑)代码实现效果展示参考资料man手册Unix-Linux编程实践教程pwd概述命令pwd用来显示到达当前目录的路径。例如:pwd的工作原理在每个目录文件下都会有".“和” . . “两个目录,”.“指的是当前目录,”. .“指的是上一级目录。我们可以通过”.“获得当前目录的inode-id,然后再进入该目录的上一级目录,通过刚刚获得的inode-id去匹配当前目录中文件的inode-id从而找到刚刚目录的目录名

2022-03-26 17:02:21 13770 1

原创 Shell脚本

Shellshell概述Shell脚本入门Shell脚本1:hello worldShell脚本2:多命令处理Shell的常用系统变量和自定义变量shell概述shell时一个命令解释器,它接收应用程序,用户命令,然后调用操作系统内核。shell还是一个功能强大的编程语言,易编写,易调试,灵活性强。Linux提供的Shell解析器可以通过下面命令查看cat /etc/shellsbash和sh的关系:sh是bash的软连接查看系统默认的解析器可以用下面的命令echo $SHELL

2022-03-25 17:23:53 458 1

原创 linux基础指令(2)

Linux中的文件名+后缀,是给用户看的,inode系统层标识文件·ls -i显示文件的inode信息ls -R列出子目录文件Linux中的 /有两种身份1.一串路径的分隔符2./我们称之为根目录绝对路径时唯一的相对路径时不唯一的所以一般系统中或者你的软件对应的配置文件,一般采用的是绝对路径日常操作,可以多多使用相对路径(简单)statstat命令主要用于显示文件或文件系统的详细信息。文件=内容 + 属性 (都会被保存下来)to

2022-03-08 14:18:35 428 2

原创 linux基础指令(1)

指令命令对应英文作用lslist查看当前文件夹下的内容pwdprint work directory查看当前所在的文件路径cd [目录]change directory切换文件夹touch [文件名](只可删除文件,不可删除文件名)touch如果文件不在就新建一个文件(非文件夹)mkdir [目录]make directory切换文件夹rm [文件名] (只可删除文件,不可删除文件名)remove删除文件clearclea

2022-03-07 11:09:16 209 1

原创 类和对象—多态(一)

多态多态的概念地址早绑定地址晚绑定原理剖析多态的优点以及实例多态的概念多态分为两类静态多态:函数重载和运算符重载属于静态多态,复用函数名动态多态:派生类和虚函数实现运行时多态静态多态和动态多态的区别静态函数的函数地址早绑定——编译阶段确定函数地址动态函数的函数地址晚绑定——运行阶段确认函数地址下面通过案例进行讲解多态地址早绑定#include<iostream>using namespace std;class animal{public: void speak()

2022-02-27 16:31:14 190 1

原创 继承的详解

继承基础继承得好处:减少重复代码语法:class 子类 : 继承方式 父类子类也称为:派生类父类也称为:基类eg:#include<iostream>using namespace std;//公共部分class BasePage{public: void test() { cout << "java,C++,Python" << endl; }};//继承class java : public BasePage{public

2022-02-23 03:25:33 1057

空空如也

空空如也

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

TA关注的人

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