- 博客(13)
- 收藏
- 关注
原创 Linux学习笔记12.2: kv 存储
本文介绍了KV存储服务器协议解析部分的实现过程,主要包括:1) 定义请求格式和命令枚举;2) 实现字符串分割函数用于解析请求;3) 设计协议处理模块,根据命令类型执行相应操作并生成响应;4) 整合KV引擎初始化与网络I/O管理,使用Reactor模式处理客户端请求。文章详细说明了从请求解析到命令执行、响应返回的完整流程,并提到后续可改进的方向如使用红黑树或哈希实现KV引擎,以及采用Proactor模式替代Reactor。
2025-09-20 08:30:00
571
原创 Linux学习笔记12.1:kv存储
本文介绍了基于顺序数组和哈希表两种数据结构实现的KV存储引擎。KV存储是一种高性能的键值对数据库模型,通过简单的键值映射实现快速数据访问。文章首先展示了基于数组的实现,包括数据结构定义、创建销毁、查找、插入、修改和删除等核心操作。随后简要介绍了更高效的哈希表实现方式,包括哈希函数设计、节点创建和冲突处理方法。这两种实现方式对比展示了KV存储引擎的基本原理,为后续学习更复杂的存储系统奠定了基础。
2025-09-19 18:16:01
1041
原创 Linux学习笔记11:异步io
本文介绍了Linux内核中的高性能异步I/O接口io_uring的实现原理和使用方法。io_uring通过共享内存环形缓冲区(SQ和CQ)减少系统调用和数据拷贝,实现高效异步I/O。文章详细讲解了如何利用io_uring构建TCP服务器,包括事件类型定义、服务器初始化、读写事件注册等关键步骤,并展示了通过批量处理完成队列条目来提高性能的方法。代码示例演示了如何实现接受连接、数据读取和发送回传的完整流程。
2025-09-17 16:22:48
714
原创 Linux学习笔记10:协程
以下是 main 函数的实现,也是调度器。简单描述一个调度流程即为:main 函数中第一次调用 swapcontext 时会切换到 ctx[0] 的上下文(即 func1 函数),在 func1 函数中运行到 swapcontext(&ctx[0], &main_ctx) 时会重新回到上次 main 运行到的位置,而当 main 函数第 n 次调用 swapcontext 第二次切换到 ctx[0] 保存的上下文(func1)时,会从 swapcontext(&ctx[0], &main_ctx);
2025-09-17 10:53:53
2012
原创 Linux学习笔记9:基于 KCP 协议的服务器
为这样一个流程:调用 recvfrom接收数据包–>调用 ikcp_input 将数据发送给 KCP 协议进行解析–>调用 ikcp_recv 从 KCP 协议中提取排序好的数据–>调用 ikcp_send 将响应数据发送给客户端。需要注意的是,ikcp_update 是 KCP 协议中的一个关键函数,它会更新 KCP 控制块中的当前时间,并计算从上次刷新到现在的逝去时间。后续作为用户数据与 KCP 控制块关联。定义一个KCP协议的输出回调函数,用于将KCP协议生成的数据包通过UDP发送到客户端地址。
2025-09-07 10:56:24
946
原创 Linux学习笔记8:Posix API
需要说明的是,每个数据包的序列号是初始序列号加上该数据包在数据流中的位置,用于确保数据包的顺序和完整性,防止数据包出现重复和乱序问题。这个包的 SYN 和 ACK 位都被设置为 1,表示服务器已经收到客户端的连接请求,并且确认了客户端的初始序列号(ACK number)。这个包的 ACK 位被设置为 1,表示客户端确认了服务器的 SYN-ACK 包。接受一个连接请求,即检查全连接队列是否有待处理的连接,若存在待处理的连接,从其中取出一个连接并创建一个新的 fd ,并将 fd 与对应连接进行映射。
2025-09-06 13:53:10
1717
原创 Linux学习笔记7:Reactor 模式的网络服务器
创建接受回调函数(accept,用于获取接入的客户端的fd),接收回调函数(recv,接收来自客户端的数据),发送回调函数(send,向客户端发送数据)。需要强调的是,由于 EPOLLIN 事件实际上会对应两种状况,一种为 sockfd(监听套接字) 触发了可读事件(即有客户端接入,此时应调用 accept_cb),另一种为客户端建立连接后发送数据触发可读事件(应调用recv_cb)。事件设置函数,使用epoll监视fd,将fd注册到epoll实例中,并设置所关注的事件。
2025-09-06 08:00:00
938
原创 Linux学习笔记6:TCP服务器
接着遍历就绪事件,如果监听套接字 sockfd 发生事件(即有连接接入),调用 accept 接受客户端连接,其中client_addr 用于存储客户端地址 ,然后将将客户端文件描述符添加到 epoll 监控列表中(epoll_ctl),监听可读事件,并启用边缘触发模式(即有数据传入就会触发)。如果当前事件不是监听套接字事件,表示是某个客户端文件描述符上的事件(即客户端有数据传入),使用 recv 函数从客户端文件描述符 clientfd 读取数据,存储到 buffer 中,并将数据打印出来。
2025-08-29 17:47:05
297
原创 Linux学习笔记5:http请求
最后如果套接字刻度(即有数据了),使用 recv 接收数据,同时动态分配内存以存储响应内容(realloc 保留原有内存的情况下追加内存空间),并将接收到的数据追加到结果中(strncat 会自动从末尾追加数据)。调用 connect 将套接字连接到指定的地址,并调用 fcntl 设置套接字为非阻塞模式,参数 O_NONBLOCK 表示非阻塞模式。首先需要将将主机名解析为IP地址,传入主机名,使用 gethostbyname 函数将主机名解析为IP地址,返回的是一个指向包含主机名解析信息的结构体的指针。
2025-08-29 17:10:14
450
原创 Linux学习笔记4:DNS协议和请求
DNS报文有固定的形式,如下所示,其中主要包含 Header(头部)、Question(问题部分)、Answer(回答部分)、Authority(权威部分)和 Additional(附加信息部分)共五个部分。而问题部分包含 name(查询名)、type(查询类型)、class(查询类),其中查询名的长度是不固定的,查询名即为要查询的域名,例如 www.example.com,写入查询名中的内容应为 3www7example3com0,数字x表示后面跟着的有x个字母,最后以0结尾。
2025-08-29 16:18:50
800
原创 Linux学习笔记3:实现一个线程池
然后要创建数量为 numWorkers 的工作线程,首先初始化 worker ,设置 manager 指向线程池(线程池就是任务和工作线程的管理者),接着调用 pthread_create 创建线程,创建的线程的 id 会自动存入 worker->threadid 中,nThreadPoolCallback 即之前定义的线程回调函数,worker 为传入回调函数的变量。线程池应中包含任务队列、工作者线程、条件变量(cond)和互斥锁(mutex),线程池用于管理任务和线程。至此,线程学习初步完成。
2025-08-29 13:51:33
1405
原创 Linux学习笔记2:实现通讯录
需要注意的点为使用了指向指针的指针(**ppeople)接收了指向联系人链表头部指针的指针,这是因为在LIST_INSERT 中会涉及头部指针变量本身的赋值操作,使用 *ppeople 即可对指针变量原本的内容进行修改。如果 item 不是链表头部节点,则将它的前向节点的 next 指针指向 item 的后向节点,从而跳过 item这个节点;搜索联系人,对链表进行遍历,每次循环调用 strcmp 对传入的联系人姓名和当前链表节点存储的联系人姓名进行比较,如果相等返回0,表示找到了对应的存储节点。
2025-08-29 02:38:49
612
原创 Linux学习笔记1:统计文本单词数量
使用状态机思想计算文本单词数量,当遇到分割符(如 ‘,’,空格)表示当前不在单词中(OUT),如果当前不在单词中且遇到非分隔符(IN),说明进入了一个新单词,单词计数加一(当状态从 OUT → IN 转变时,说明遇到一个新单词)。首先需要打开文件,返回一个 文件指针 fp,指向一个FILE 结构体(里面保存文件缓冲区、文件描述符等信息),可以通过该指针操作文件。批量读取,buf存放读取内容,'1’表示每个元素的字节数为1,也就是你想把文件内容分成多大的“块”来读写,sizeof(buf)为读取的元素个数。
2025-08-29 01:12:45
162
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅