自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 编程框架。

框架则不同,它不仅仅是函数的集合,它更像是一个预设好的结构蓝图。框架为开发者提供了一个完整的开发架构,开发者需要根据框架的规则进行开发。框架会定义应用程序的整体结构,开发者可以在框架提供的基础上填入业务逻辑代码。开发者在需要实现某个功能时,可以在库中选择合适的函数来调用,帮助实现。库通常是面向某个具体的任务,比如有专门用于机器学习的库,专门用于网络的库,专门用于输入输出的库。框架(Framework)是一套已设计好的代码结构和组件,提供了一种标准化的方式来构建应用程序。的,先干什么,后干什么,不能乱序。

2024-09-06 11:30:14 601

原创 异构计算。

计算机刚出现的时候,最重要的硬件是cpu,内存,所有的计算在cpu中(的alu)进行,计算需要的数据存在内存中。随着时代发展,出现了针对某一领域的专门的处理器,比如图像处理器GPU,它擅长大规模并行计算,如矩阵运算和图像处理,而传统的cpu更适合处理复杂的逻辑控制。异构计算就是将一个任务分成几部分,每部分选择最合适硬件去处理,这些硬件协同合作完成任务。不同组件处理的任务若是独立的,还可以并行执行,加快速度。类似的硬件还有TPU张量处理器,FPGA等。

2024-09-05 23:07:52 312

原创 异常安全处理

程序中,很多函数可能不会正常返回,比如IO函数,atoi,itoa。在c中,如果一个函数需要改变某个结构,且这个函数可能出错,一种解决方案是传入指针,用返回值来表示成功与否。EH(Exception Handling)代替了原来的确定的方法(通过返回值确定函数是否成功),即使原来的方法也有瑕疵,但这些瑕疵是可理解的,也好解决。,比如一个函数仅仅只是new一个对象,然后返回这个对象,但因为new失败会返回异常,这个异常会沿着调用栈传递。你无法知道函数调用栈中哪个函数会引发异常,所以,异常安全的代码很重要。

2024-09-02 11:43:55 273

原创 os 虚拟内存

虚拟内存通过以上机制,使得操作系统能够有效地管理物理内存,减少不必要的内存占用,支持多个进程并发运行,从而显著提高内存利用率。这种内存管理方式不仅优化了系统性能,还提供了进程隔离和稳定性。每个进程的虚拟地址空间中,内核空间的地址经过页表翻译后,都是指向同一片物理地址吗??是的,在大多数操作系统中,每个进程的虚拟地址空间都包含一个内核空间,这个内核空间的地址经过页表翻译后,通常指向相同的物理内存区域。因此,确实,每个进程的虚拟地址空间中的内核空间的虚拟地址经过页表翻译后,通常会指向相同的物理地址。

2024-08-24 11:59:01 646

原创 go slices.Clone官方文档

基本类型:对于基本类型的切片,表现为深拷贝,因为它复制了所有元素的值。引用类型:对于包含引用类型的切片,表现为浅拷贝,因为它仅复制了引用,而不是引用所指向的数据。所以官方文档的描述是正确的,只是使用了“shallow clone”这个术语来强调在引用类型切片中,克隆操作不会复制引用所指向的底层数据。

2024-08-24 09:26:08 453 1

原创 fork exec cow

在fork()时:COW 允许父进程和子进程共享相同的内存页面,直到有一个进程进行写操作。这减少了不必要的内存复制,提高了性能。在exec()时:COW 提供的内存共享机制可以避免在调用exec()之前进行不必要的内存复制,但在exec()调用之后,这些共享内存将被新加载的可执行文件所取代。

2024-08-23 20:26:54 1013

原创 三次握手和四次挥手

在 TCP 连接的四次挥手过程中,TIME_WAIT状态具有重要意义,它主要用于确保旧连接的数据已经被成功传输并且不会干扰新的连接,此外还用于处理丢失或延迟的数据包。TIME_WAITTIME_WAIT状态在 TCP 的四次挥手过程中,起到了确保连接正确关闭和防止数据包混淆的重要作用。虽然它会暂时占用一些资源,但这是为了保证网络通信的可靠性和稳定性,是 TCP 设计中的一个重要机制。

2024-08-22 21:42:39 693

原创 线程池和连接池

线程池还包括一个任务队列,线程池中的线程是主动从任务队列中取出任务,若没有任务则阻塞。连接池(如数据库连接池,redis连接池,http连接池)是被动的,等待被取出。

2024-08-22 00:21:52 160

原创 https加密

在 HTTPS 连接中,非对称加密主要用于连接建立的初始阶段,特别是在 SSL/TLS 握手过程中。握手完成后,通信的加密方式会切换为对称加密。具体来说,过程如下:非对称加密算法通常包括 RSA、ECDSA 等。这些算法虽然安全性高,但加密和解密过程相对耗时和资源密集,因此通常只用于会话初始阶段的密钥交换。这种组合使用非对称加密和对称加密的方式使得 HTTPS 既能保证安全性,又能在性能上保持高效。HTTPS 的握手过程(SSL/TLS 握手)是建立安全连接的关键步骤,确保数据在传输过程中的机密性和完整性。

2024-08-22 00:19:49 822

原创 http的host字段

如果使用了反向代理,那么更需要host来区分。因为用户的请求会发到反向代理服务器(所以,一般nginx监听80端口 ,因为是常用端口),在反向代理服务器上,通过host来确定请求发送到哪个机器上。通过host字段来区分该http请求是发送给哪个服务进程。因为一台物理机器上可能有多个服务进程,他们共享一个ip地址。

2024-08-21 23:10:00 580

原创 shell如何实现管道符号‘|‘

在 Shell 中使用的管道符属于。它用于将一个命令的输出直接传递给另一个命令作为输入,实现了进程间的数据流转。

2024-08-19 16:32:21 627

原创 http请求和响应

是的,HTTP 请求和响应在发送之前通常都需要进行序列化。序列化是将数据结构或对象转换为适合传输的格式的过程。在 HTTP 通信中,数据的序列化和反序列化是关键步骤。

2024-08-13 16:00:53 412

原创 etcd实现服务注册和发现

etcd在微服务中用于服务注册和发现。原来的rpc调用是客户端直接向服务器发起,现在,服务器将自己的地址和提供的服务以kv对形式存入etcd(注册),客户端先访问etcd,查询对应服务是否存在(即是否有服务器提供了相应的服务),若存在,便可从etcd处得到提供服务的服务器地址,然后向服务器发起rpc调用。etcd只起到查询作用,不直接参与rpc。客户端可从etcd处查到某个服务有多个服务器都提供了,可以采用负载均衡技术发起rpc。服务器和客户端其实互为peer,可以互相调用。

2024-08-09 19:38:02 266

原创 为什么需要分布式锁

传统的锁,只能运行在一个进程内,或者说只能锁住一个进程内的共享资源。而如果有多个进程,如服务器的负载均衡需要多个进程,那么传统的锁就无法保证共享资源的正确使用。这时需要分布式锁,在请求到达服务器之前,先获取锁。如图,客户端同时发送三个请求到3个server,但只有一个能获得锁,进入服务器执行。

2024-08-08 15:53:46 240

原创 判断两个区间是否重叠

【代码】判断两个区间是否重叠。

2024-07-28 10:37:58 335

原创 gin中间件,路由匹配和启动

初始值为-1.所以,第一次调用Next,先将index加到0,然后进入循环,执行了注册的中间件m1,在m1中又调用了Next,再进到Next中,此时的index++后等于1,进入循环,执行c.handlers[1](c),也就是m2。index再加一,退出循环,退出Next函数,就回到了m3.m3再执行完,退出到m2调用的Next中,此时index已经等于len(c.handlers)了,所以循环直接退出,也就退出了m2。同样,退出m2执行流来到m1调用的Next中,再退出。可以看出,是一个嵌套的调用。

2024-07-27 16:24:09 228

原创 gin路由组

这行代码调用了方法,返回一个新的路由组对象v1。所有在这个组内定义的路由都会自动加上/v1作为前缀。

2024-07-25 19:51:51 1243

原创 有向图BFS

在有向图的bfs中,注意将vis数组设置在for循环中。在无向图中,vis定义在外面。

2024-07-22 13:19:54 178

原创 go recover

在second中发生panic,second中没有defer,故立即退出,panic沿着调用栈传递到first中,first因为调用的second函数发生panic,也应该退出,但是由于first中有recover,故执行defer的recover,捕获了这个panic,使得它不会再沿着调用栈传到main中。但是main随后调用second,又发生panic,panic沿着调用栈传递到main中,导致main退出,不会输出”End of main“

2024-07-17 22:41:01 259

原创 不整理worker和coordinator,越写越乱

6.824lab1,应该整理好worker和coordinator需要掌握哪些信息,需要发送哪些信息?明确具体需求,比如worker到底输出几个文件,整理好,画好流程图,才不会边写边改,越写越乱。

2024-07-16 21:48:06 287

原创 go 匿名递归

【代码】go 匿名递归。

2024-07-12 10:26:35 127

原创 go222

只要一个具体类型bar的方法(method)中实现了Write函数(签名相同),就是实现了Writer接口。那么在一些要求io.Writer类型作为参数的函数中,就可以传入这个具体类型bar。具体类型比如int,type foo struct{},其中foo就是一个具体类型(struct。接口类型只定义这个接口可以做什么,如在io包里的writer。因此,可以通过接口来实现多态。go分具体类型和接口类型。这就是一个接口类型。

2024-06-29 20:25:53 142

原创 go111

go中,数组作为函数参数是值传递,所以在函数中改变数组不能反映到调用者的数组中,如果传数组的slice,则可以改变,因为slice中包含数组的指针。

2024-06-26 15:56:39 262

原创 网络编程1

服务器接收到 FIN 包后,会向客户端发送一个 ACK(Acknowledgment)包,确认已经接收到 FIN。客户端接收到服务器的 FIN 包后,向服务器发送一个 ACK 包,确认已经接收到 FIN。网络编程中,客户端调用close或者shutdown后,操作系统会给服务器发送一个FIN。操作系统会发送一个 FIN 包给服务器,表示客户端不会再发送数据。服务器进入半关闭状态,可以继续向客户端发送数据,但不能再接收数据。当双方都发送并接收到 FIN 和 ACK 包后,连接才完全关闭。

2024-06-21 15:44:22 357

原创 malloc lab

抄书代码,测试结果:

2024-06-09 20:20:25 148

原创 webserver timer

在eventLoop函数中,epoll会监听到该管道的读端有事件发生,而处理该事件的方法是调用deal_signal函数。在eventloop中处理,因为超时事件优先级不高,故先处理完epoll的事件,再处理timeout。处理timeout的函数time_handler中,会调用tick函数,而tick函数会遍历定时器升序链表,查看是否有定时器超时。调用alarm()系统调用,设置好时间,这段时间结束后,alarm会发出sig_alarm信号。webserver项目中,通过信号函数来实现定时。

2024-06-04 09:52:02 226

原创 listen 和 accept

也就是listen会将sockfd标记为一个被动的socket,它将通过accept系统调用接受连接请求。其中,backlog参数指定了sockfd用于pending connection的队列的最大长度。(也就是说listen的具体实现中有队列?总之,accept的第二三个参数是会在调用函数后被赋值的(所以传入的是指针)。accept会从sockfd的队列中拿出第一个连接请求,创建一个新的socket,并返回其fd。

2024-06-03 13:38:55 198

原创 man 7 socket

AF_UNIX)

2024-06-03 10:20:11 232

原创 【无标题】

IO多路复用是通过单个线程记录多个IO流的状态,来起到同时管理多个io流的作用。epoll是如何知道它管理的io流有事件发生?epoll是io多路复用的一种实现。

2024-06-03 10:17:29 432

原创 离散数学 哈密顿图

注意:目前没有找到哈密顿图的简单的充要条件。破坏以上诸条件中的一条,都不是哈密顿图。

2024-06-02 12:40:40 657

原创 ubuntu使用mysql

【04-Ubuntu20.04配置最新的Mysql8.0数据库】 https://www.bilibili.com/video/BV1DV411P7mz/?

2024-06-01 18:27:11 143

原创 upperbound lowerbound

upper_bound的第四个参数是自定义的匿名函数cmp,返回值为bool类型,cmp有两个参数,一个是value,对,你没看错,就是upper_bound的第3个参数value,另一个是element,也就是查找过程中与value比较的那个数。在从小到大的排好序的数组中,在数组的[begin, end)区间中二分查找第一个大于等于value的数,找到返回该数字的地址,没找到则返回end。// 3(value是3,第一个大于等于value的数)// 3(value是3,第一个大于等于value的数)

2024-05-03 18:48:13 683

原创 cs144

基本上,对于服务器端,使用顺序是socket() -> bind() -> listen() -> accept(),而对于客户端,使用顺序是socket() -> connect()。1.创建套接字(Socket):使用socket()函数创建一个套接字,指定地址族(通常是AF_INET或AF_INET6)和套接字类型(SOCK_STREAM用于TCP套接字)。这一步是可选的,但通常在服务器端进行。6.发送和接收数据:一旦连接建立,服务器和客户端都可以使用send()和recv()函数来发送和接收数据。

2024-05-02 14:50:22 51

原创 ecall

而ecall指令会将user mode换为supervisor mode,保存当前pc寄存器的值(因为系统调用结束后我们会回来继续执行),并把trampoline page的首地址送pc寄存器。trampoline的代码是用汇编写的,在kernel/trampoline.S中。2.切换到内核页表,栈指针指向内核栈,准备好执行usertrap代码 3.跳转到usertrap。用户空间下的调用syscall,如read(), write(),fork(),都会被编译成汇编指令。

2024-04-27 16:15:39 338

原创 lazy allocation

在page fault handler中,会检查触发page fault的地址是否合法,是否处于(brk, brk + n)中,如果是,那么就马上分配一页内存,然后将其映射到虚拟内存(即在页表中添加新的页表项)。对于未初始化的全局变量,通常存放在bss段中,但bss段是统一映射到一个全为0的内存页,且这个内存页的PTE_V为0。如果os采用lazy allocation,sbrk的实现将会是只将brk指针的值+n,然后返回brk的旧值。注意,并没有分配内存,因为没有在页表中添加新的页表项。

2024-04-21 11:22:53 151

原创 虚拟内存111

虚拟内存就是页表提供的一种“假象”

2024-04-19 15:56:22 355

原创 syscall

假设我现在要执行另一个系统调用write,相应的流程是类似的,write系统调用不能直接调用内核中的write代码,而是由封装好的系统调用函数执行ECALL指令。所以write函数实际上调用的是ECALL指令,指令的参数是代表了write系统调用的数字。之后控制权到了syscall函数,syscall会实际调用write系统调用。

2024-04-19 15:55:45 105

原创 【无标题】xv6 trap

从user space到kernel:每个进程结构体有一个成员trapframe,它指向一块内存页,这块内存用来保存进程的现场,即所有寄存器的值。同时,trapframe中还存有内核的栈指针和其他内核相关的东西,用于从用户空间切换到内核空间做准备。

2024-04-18 18:48:16 141

原创 c++函数模板

1.如果函数的定义不是inline,那么函数定义时的不能加上默认实参的等号,即。如果函数模板声明中包含默认参数,如。2.如果在声明时就定义了,那没事了。

2024-04-14 18:19:42 151 1

原创 attack lab phase4

phase4需要活用rsp寄存器,通过popq,ret这些会改变rsp的指令来完成。

2024-03-23 20:23:14 156 1

空空如也

空空如也

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

TA关注的人

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