- 博客(44)
- 收藏
- 关注
原创 Libevent源码深度刨析
Libevent 是基于事件驱动(event-driven)的,从名字也可以看到 event 是整个库的核心。event 就是 Reactor 框架中的事件处理程序组件;它提供了函数接口,供 Reactor 在事件发生时调用,以执行相应的事件处理,通常它会绑定一个有效的句柄。structtype;structtype;下面详细解释一下结构体中各字段的含义。
2024-10-04 15:33:35
863
原创 内核是如何发送数据包
网络发包总流程图如下:从上图中可以看到用户数据被拷贝到内核态,然后经过协议栈处理后进入RingBuffer。随后网卡驱动真正的将数据发送了出去。当发送完成的时候,是通过硬中断来通知CPU,然后清理RingBuffer。下面从源码的角度给出一个流程图。
2024-09-22 12:24:05
1224
原创 网络-内核是如何与用户进程交互
socket在内核中是怎么创建的?在__sock_create里首先调用sock_alloc来分配一个struct sock内核对象,接着获取协议簇的操作函数表,调用其create方法。对于AF_INET协议簇来说,执行到的是inet_create函数。在inet_create中根据类型SOCK_STREAM查找到对于TCP定义的操作方法实现集合inet_stream_ops和tcp_port,并把它们分别设置到socket->ops和sock->sk_port上。
2024-09-19 15:59:20
1185
原创 内核是如何接收网络包的
在__netif_receive_skb_core中可以看到tcpdump命令的抓包点和netfilter的输入的第一个挂接点,tcpdump将抓包函数以协议形式挂到ptype_all上,设备层遍历所有协议,就能抓到数据包了,tcpdump会执行packet_create。_igb_open函数调用了igb_setup_all_tx_resources和igb_setup_all_rx_resources。inet_protos中保存着tcp_v4_rcv和udp_rcv的函数地址。
2024-09-18 23:33:23
1369
原创 Linux内存管理
Glibc 的 malloc 可以支持多线程,增加了非主分配区(non main arena)支持,主分配区与非主分配区用环形链表进行管理。每一个分配区利用互斥锁(mutex)使线程对于该分配区的访问互斥。每个进程只有一个主分配区,但可能存在多个非主分配区,ptmalloc 根据系统对分配区的争用情况动态增加非主分配区的数量,分配区的数量一旦增加,就不会再减少了。主分配区可以访问进程的 heap 区域和 mmap 映射区域,也就是说主分配区可以使用 sbrk 和 mmap向操作系统申请虚拟内存。
2024-06-11 23:54:48
1267
原创 零拷贝技术
sendfile方式只使用一个函数就可以完成之前的read+write 和 mmap+write的功能,这样就少了2次状态切换,由于数据不经过用户缓冲区,因此该数据无法被修改。目前来看,零拷贝技术的几个实现手段包括:mmap+write、sendfile、sendfile+DMA收集、splice等。升级后的sendfile将内核空间缓冲区中对应的数据描述信息(文件描述符、地址偏移量等信息)记录到socket缓冲区中。mmap+write方式有一定改进,但是由系统调用引起的状态切换并没有减少。
2024-06-11 21:42:56
820
原创 深入理解Linux网络总结
在硬中断的处理中,发起软中断的时候是基于当前CPU核的smp_processor_id的,这意味着哪个核响应的硬中断,那么该硬中断发起的软中断任务就必然由这个核来处理。不过硬中断的上下文里做的工作很少,将传过来的poll_list添加到CPU变量softnet_data的poll_list里(softnet_data中的poll_list是一个双向列表,其中的设备都带有输入帧等着被处理),接着触发软中断NET_RX_SOFTIRQ。服务端响应的第一次握手的时候,会进行半连接队列和全连接队列满的判断。
2024-06-02 21:39:34
1097
原创 Strace使用
e open等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none.只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all.-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪.-t 在输出中的每一行前加上时间信息.
2024-06-01 17:31:29
1024
原创 音视频基础 (九)---FFmpeg过滤器框架
AVFilterGraph是FFmpeg中用于管理音视频滤镜的数据结构。它表示一个完整的滤镜图,可以包含多个输入输出,并通过连接不同的滤镜节点来实现各种音视频处理操作。AVFilterGraph提供了创建、配置和管理滤镜的接口,允许用户构建复杂的滤镜拓扑结构,以实现音视频的处理和编辑。通AVFilterGraph,用户可以添加各种滤镜(如变换、剪切、合并、调节等)并将它们连接起来,最终实现所需的音视频处理效果。
2024-03-31 09:46:46
1944
原创 音视频实战---音视频解码
1、使用avcodec_find_decoder查找解码器2、 使用av_parser_init获取裸流解析器和方法3、使用avcodec_alloc_context3分配编解码器上下文4、使用avcodec_open2将解码器和解码器上下文进行关联5、使用fopen打开输入、输出文件6、使用fread读取文件7、使用av_frame_alloc分配存储解码数据结构体,以接收解码数据8、使用av_parser_parse2解析数据包获取到编码后的音视频帧,将获取到的音视频帧使用avcodec_
2024-03-14 22:58:50
730
原创 音视频实战---从音视频文件中提取h264裸流
1、使用avformat_alloc_context分配解复用器上下文内存2、使用avformat_open_input打开音视频文件或网络流3、使用avformat_find_stream_info获取码流信息4、使用 av_find_best_stream获取视频流下标5、分配编码数据av_packet_alloc内存空间6、使用av_init_packet初始化编码数据帧结构7、使用av_bsf_get_by_name函数根据名字获取相应的比特流过滤器8、 初始化过滤器上下文av_bsf
2024-03-14 22:38:59
844
原创 音视频编码实战--读取音视频文件
使用函数打开音视频文件,获取该文件构成和基本信息的结构体。AVFormatContext是描述一个媒体文件或媒体流的构成和基本信息的结构体。
2024-03-10 15:58:10
479
原创 股票选股-
如何估算股票价值?要估算每股股票值多少钱,一个方法是知道整个公司值多少钱,然后再除以股份总数就行了。如何估计公司值多少钱?挑选一是业务简单且稳定,二是有持续竞争优势,三是盈利持续稳定的公司。预测公司未来几年的利润究竟会有多少。巴菲特选股的成功秘诀在于两大关键点:如何辨别一家公司是不是具有持久竞争优势的优质企业?如何估算这家具有持久竞争优势的优秀公司值多少钱?如果一个公司的竞争优势能在很长一段时间内持续不变——竞争优势具有稳定持续性,那么公司价值会一直保持增长。
2024-02-23 00:30:50
973
1
原创 音视频基础(八)---H264 NALU分析
H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。
2024-02-19 00:34:19
1195
原创 音视频基础(七)---FLV
FLV(Flash Video)是Adobe公司推出的⼀种流媒体格式,由于其封装后的⾳视频⽂件体积⼩、封装简单等特点,⾮常适合于互联⽹上使⽤。⽬前主流的视频⽹站基本都⽀持FLV。采⽤FLV格式封装的⽂件后缀为.flv。,在解析时需要注意。
2024-02-18 08:18:19
1230
原创 音视频基础(六)---AAC ADTS格式
有的时候当你编码AAC裸流的时候,会遇到写出来的AAC⽂件并不能在PC和⼿机上播放,很⼤的可能就是AAC⽂件的每⼀帧⾥缺少了ADTS头信息⽂件的包装拼接。所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有⼀个AAC数据块。且这两种的header的格式也是不同的,⽬前⼀般编码后的和抽取出的都是ADTS格式的⾳频流。观察第⼀帧的⻓度确实为263个字节。每⼀帧的ADTS的头⽂件都包含了⾳频的采样率,声道,帧⻓度等信息,这样解码器才能解析读取。
2024-02-17 23:26:14
1230
原创 音视频基础(五)---FFmpeg内存模型
◼ 对于多个AVPacket共享同一个缓存空间,FFmpeg使用的引。◼ 初始化引用计数为0,只有真正分配AVBuffer的时候,◼ 当释放了引用共享空间的Packet,就将引用计数-1;◼ 当有新的Packet引用共享的缓存空间时,就将引用计数。用计数为0时,就释放掉引用的缓存空间AVBuffer。◼ AVFrame也是采用同样的机制。引用计数初始化为1;
2024-02-17 21:41:16
419
原创 音视频基础(四)---FFmpeg库基础
FFMPEG有8个常用库AVUtil:核心工具库,下面的许多其他模块都会依赖该库做一些基本的音视频处理操作。AVFormat:文件格式和协议库,该模块是最重要的模块之一,封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。
2024-02-17 15:54:14
976
原创 音视频基础(3)---ffmepg及faplay命令
ffmepg查看帮助文档命令◼基本信息:ffmpeg -h◼高级信息:ffmpeg -h long◼所有信息:ffmpeg -h full若嫌打印过多: ffmepg -h full > ffmpeg_h_full.log,然后再打开ffmpeg_h_full.log文件查看usage:ffmpeg [options] [[infile options] -i infile]…{[outfile options] outfile}…ffplay命令查看帮助文档所有信息:ffplay
2023-11-25 23:41:29
1253
原创 音视频基础(二)---封装格式+音视频同步
PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。封装格式(也叫容器)就是将已经编码压缩好的视频流、音频流及字幕按照一定的方案放到一个文件中,便于播放软件播放。对于视频也是一个道理,同样的音视频流可以用不同容器来承载。External Clock Master:同步音频和视频到外部时钟。
2023-11-25 22:57:35
147
原创 音视频基础(一)---原理
下图是一个3位量化的示意图,可以看出3位量化只能表示8个值:0.75,0.5,0.25,0,─0.25,─0.5,─0.75和 ─1,因而量化位数越少,波形就越难辨认,还原后的声音质量也就越差(可能除了一片嗡嗡声之外什么都没有)。YUV存在多种格式,比如YUV420p,YUV420sp等,不同的YUV格式的数据在存储时的排列顺序是不一样的,在开发的过程中必须非常注意,否则画面会显示不正常。声音的频率是周期的倒数,它表示的是声音在1秒钟内的周期数,单位是赫兹(Hz)。帧率越高,给人的视觉就越流畅。
2023-11-25 22:50:54
1067
原创 设计模式之责任链模式
责任链模式定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成⼀条链,并沿着这条链传递请求,直到有⼀个对象处理它为止。 ——《设计模式》GoF要点:解耦请求⽅和处理⽅,请求⽅不知道请求是如何被处理,处理⽅的组成是由相互独⽴的⼦处理构成,⼦处理流程通过链表的⽅式连接,⼦处理请求可以按任意顺序组合;责任链请求强调请求最终由⼀个⼦处理流程处理;通过了各个⼦处理条件判断;责任链扩展就是功能链,功能链强调的是,⼀个请求依次经由功能链中的⼦处理流程处理;充分体现了
2022-03-23 23:40:08
101
原创 STL之vector
vector是线性连续空间,它以两个迭代器start和finish分别指向配置得来的连续空间中已被使用的范围,并以迭代器end_of_storage指向整块连续空间(含备用空间)的尾端。vector在insert插入时,插入的元素超过备用空间的大小,需要重新分配空间,而这一块新分配空间的大小为原空间的两倍或原空间大小加新插入的元素个数(这是因为原空间大小加新插入的元素个数大于原空间的两倍大小);使用push_back()插入时,没有备用空间,扩容是按照原空间的两倍大小,如果原空间为0,则扩充为1;ve
2022-03-21 20:14:03
96
原创 KCP原理与源码解析
什么是KCP?为什么使用KCP?KCP是⼀个快速可靠协议,能以⽐ TCP浪费10%-20%的带宽的代价,换取平均延迟降低 30%-40%,且 最⼤延迟降低三倍的传输效果。纯算法实现,并不负责底层协议(如UDP)的收发,需要使⽤者⾃⼰定义 下层数据包的发送⽅式,以 callback的⽅式提供给 KCP。 连时钟都需要外部传递进来,内部不会有任何⼀次系统调⽤。TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利⽤带宽。⽽ KCP是为流速设计 的(单个数据包从⼀端发送到⼀端需要多少时间),以1
2022-03-20 14:54:38
5352
原创 高级IO函数
在I/O操作上设置超时在涉及套接字的I/O操作上设置超时的方法有以下三种。(1)调用alarm,它在指定超时期满时产生SIGALRM信号。这个方法涉及信号处理,而信号处理在不同的实现上存在差异,而且可能干扰进程中现有的alarm调用。(2)在select中阻塞等待I/O (select有内置的时间限制),以此代替直接阻塞在read或 write 调用上。(3)使用较新的SO_RCVTIMEO和SO_SNDTIMEO套接字选项。这个方法的问题在于并非所有实现都支持这两个套接字选项。前两个技术适用于任
2022-01-06 20:51:03
914
原创 服务器规范名字与IP地址的转换
使用名字代替地址的原由出于许多理由,我们应该使用名字而不是数值:名字比较容易记住;数值地址可以变动而名 字保持不变;随着往IPv6上转移,数值地址变得相当长,手工键入数值地址更易出错。本章讲 述在名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IPv4 地址之间进行转换,getservbyname和getservbyport在服务名字和端口号之间进行转换。本 章还讲述两个协议无关的转换函数:getaddrinfo和getnameinfo,分别用于主机名字和
2022-01-03 16:38:02
2601
原创 基本UDP套接字编程
图8-1给出了典型的UDP客户/服务器程序的函数调用。recvfrom和sendto函数#include<sys/socket.h>ssize_t recvfrom(int sockfd,void *buff,size_t nbytes, int flags, struct sockaddr *from,socklen_t *addrlen);ssize_t sendto(int sockfd,const void *buff,size_t nbytes,int flags,
2022-01-02 21:12:56
1092
原创 套接字选项及作用
套接字选项获取和设置影响套接字的选项的方法getsockopt和setsockopt函数fcntl函数ioctl函数getsockopt和setsockopt函数这两个函数仅用于套接字。#include<sys/socket.h>int getsockopt(int sockfd,int level,int optname, void *optval,socklen_t *optlen);int setsockopet(int sockfd,int level,in
2022-01-02 14:29:08
997
原创 唤醒机制的实现
唤醒机制在linux下的实现(1)使用管道fd(pipe)创建一个管道,将管道的一端(管道fd中的一个)绑定到epollfd上,需要唤醒时,向管道的另一端(管道fd中的另一个)写入1字节,工作线程会被立即唤醒。创建管道的相关API函数如下:#include<unistd.h>#include<fcntl.h>int pipe(int pipefd[2]);int pipe(int pipefd[2], int flags);(2)使用Linux2.6新增的even
2021-12-31 20:39:17
351
原创 提高网络通信组件的性能
尽量少等待如何检测有新的客户端连接的到来?如何接受客户端的连接请求?如何检测客户端是否有数据发送过来?如何收取客户端发送的数据?如何检测异常的客户端连接?检测到之后,如何处理?如何向客户端发送数据?如何在客户端发送完数据后关闭连接?对于第1、3个问题,使用I/O复用技术的select、poll、epoll等相关套接字函数。对于第2个问题,使用socket API accept函数。对于第4个问题,使用recv函数对于第6个问题使用send函数。能尽量满足少等待原则的程序就是高性能
2021-12-29 23:08:23
409
原创 网络字节序与地址转换函数
网络字节序是大端编码,编码方式有两种:①小端编码:高位数字存放在高地址字节中,如0x1234,小端编码机器将12存放在高位地址字节,34存放在低地址字节中,将其转化为1字节的char时,高地址字节被丢弃,剩余低地址字节,就是34。②大端编码:高位数字存放在低地址字节中,将0x1234转化为1字节的char,高地址字节被丢弃,剩余低地址字节,即12。htons函数将一个short类型从本机字节序转换为网络字节序。#include<arpa/inet.h>uint32_t htonl(u
2021-12-27 23:32:26
1337
原创 纤程与协程
纤程纤程是Windows中的概念。在windows中一个线程可以有多个纤程,用户可以根据需要在各个纤程之间自由切换。如果需要在某个线程中使用纤程,则必须先将该线程切换成纤程模式,这可以通过调用如下API函数实现:LPVOID ConvertThreadToFiber(LPVOID lpParameter);该函数可以将当前线程切换成纤程模式,也可以得到线程中的第一个纤程。我们可以通过函数的返回值来引用和操作纤程,这个纤程是线程的主纤程。但是这个主纤程无法指定纤程函数,所以什么也做不了。我们可以通过
2021-12-27 20:25:06
654
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人