linux网络编程6——基于UDP的可靠传输协议KCP/QUIC

文章目录

  • 基于UDP的可靠传输协议KCP/QUIC
    • 1 KCP基本原理
      • 1.1 如何做到可靠传输
      • 1.2 TCP和UDP如何选择
      • 1.3 ARQ协议
        • 1.3.1 停止等待ARQ
        • 1.3.2 回退nARQ
        • 1.3.3 选择重传ARQ
      • 1.4 RTT和RTO
      • 1.5 流量控制——滑动窗口
      • 1.6 拥塞控制
      • 1.7 KCP协议的优势
        • 1.7.1 RTO翻倍 vs 不翻倍
        • 1.7.2 选择重传 vs 全部重传
        • 1.7.3 快速重传
        • 1.7.4 延迟ACK vs 非延迟ACK
        • 1.7.5 UNA vs ACK + UNA
        • 1.7.6 非退让流控
    • 2. KCP源码分析和使用
      • 2.1 名词说明
      • 2.2 kcp协议头
        • 2.2.1 ikcp中的主要数据结构
      • 2.2 KCP的使用方式
        • 2.2.1 生成会话ID
        • 2.2.2 流程
        • 2.2.3 KCP配置模式
    • 3. 重点问题
    • 4. QUIC简介
      • 4.1 QUIC 的核心特点
    • 学习参考

基于UDP的可靠传输协议KCP/QUIC

本文详细介绍了KCP协议基本原理,并简要介绍了KCP的使用方式以及QUIC协议。

1 KCP基本原理

1.1 如何做到可靠传输

可靠传输最主要是依赖于ARQ协议,即自动重复请求协议,它的基本功能是在丢包时请求重传,它的如下机制保证了可靠的传输:

  • ACK确认机制,确保数据已被接收。

  • 重传机制,当超时或者判断丢包时重传数据。

  • 序号机制,检测是否有数据丢失和是否有序。

  • 重排机制,使乱序到达的数据重新有序。

1.2 TCP和UDP如何选择

以下是一个总结UDP和TCP之间主要区别的表格:

特性TCPUDP
连接方式面向连接(建立连接)无连接(无需建立连接)
传输方式面向字节流面向报文
可靠性提供可靠的数据传输(数据包顺序、重传机制)不保证可靠性(可能丢失数据包)
数据顺序确保数据包按顺序到达不保证数据包顺序
流控制提供流控制(使用滑动窗口协议)不提供流控制
拥塞控制提供拥塞控制机制不提供拥塞控制
适用场景适合需要可靠传输的应用(如网页、文件传输)适合实时应用(如视频、语音);游戏行业
传输速率相对较慢(由于连接管理、错误校正)相对较快(无连接管理、简单)
应用协议HTTP, FTP, SMTP 等DNS, DHCP, VoIP 等

字节流: 连续、有序。

报文:离散,无序。

1.3 ARQ协议

ARQ(Automatic Repeat reQuest),即自动重复请求,是一种确保可靠传输的机制。可以参考这篇博文详细了解。

1.3.1 停止等待ARQ

很少被采用。

1.3.2 回退nARQ

TCP采用这种重传机制。ARQ

1.3.3 选择重传ARQ

KCP采用这种方式。

1.4 RTT和RTO

RTO(Retransmission TimeOut)即重传超时时间

RTT(Round-Trip Time)即往返时延

1.5 流量控制——滑动窗口

为什么要进行流量控制:发送方的发送速率与接收方的接受速率存在差异

  1. 如果发送方速率大于接收方速率,接收方就不得不丢弃很多数据包,导致传输效率下降。
  2. 如果发送方速率小于接收方速率,会浪费带宽。

怎么进行流量控制:滑动窗口

接收方会告诉发送方自己的接收窗口的大小,还能够接收多少数据,这样发送方知道能够发送多少数据。

其他小问题总结

  • 接收窗口大小固定吗?不固定,需要根据网络情况动态调整。
  • 接收窗口越大越好吗?不是,接收窗口过大容易导致乱序和丢包。
  • 发送窗口和接收窗口相等吗?一般接收窗口>=发送窗口。

1.6 拥塞控制

主要由四个算法组成:

  • 慢启动
  • 拥塞避免
  • 快速恢复 (TCP Reno版本开始使用)
  • 快速重传

简要了解可以参考我的博文,详细了解可以参考这篇博文。

1.7 KCP协议的优势

在不稳定的网络中,KCP以10%-20%带宽浪费的代价,换取比TCP快30%-40%的传输速度

在网络通畅的情况下,文件传输速度上,kcp < tcp。

KCP的传输速度优势本质上来自于其实现的ARQ协议的重传策略。它通过以下机制实现了这样的目标:

  • 尽量减少重传超时等待的时间(即RTO)。
  • 尽量减少丢包的成本(得益于选择重传ARQ)。

尽管实现这样的目标是以消耗的网络带宽增加为代价的。

1.7.1 RTO翻倍 vs 不翻倍

TCP的超时时长计算策略是翻倍,而KCP启动快速模式后是乘以1.5,提高了传输速度。

KCP还可以定制重传策略定制丢包策略

1.7.2 选择重传 vs 全部重传

KCP使用选择拒绝自动重复请求,只重传那些已经丢失的包。

KCP使用快速重传,KCP的快速重传是指当发现某个数据段被跳过确认多次后,不必等待RTO而直接重传,大大改善了丢包时的重传速度。

1.7.3 快速重传

发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。

1.7.4 延迟ACK vs 非延迟ACK

TCP为了充分利用带宽,选择延迟发送ACK,这样超时计算会算出较大的RTT时间,从而延长了RTO时间。而KCP的ACK是否延迟可以调节。

在TCP中,一个ACK可以确认多个数据段,因此采用延迟ACK可以减少网络包数量。

1.7.5 UNA vs ACK + UNA

ARQ的响应模式有两种,UNA(Unacknowledged Number Acknowledged)和ACK,UNA模式下确认序号指的是下一个期待收到的序号,ACK模式下确认序号指的是已经收到的数据段的序号。只用UNA会导致太多重传,只用ACK会导致丢失成本太高(ACK包丢失可能会导致不必要的重传)。在KCP协议中,除去单独的ACK包外,所有的包都有UNA信息。

1.7.6 非退让流控

KCP正常模式下通TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端窗口大小、丢包退让、拥塞窗口这四个因素决定。当采用非退让流控时,就不考虑后两个因素。

2. KCP源码分析和使用

2.1 名词说明

MTU: 最大传输单元,是数据链路层的概念,以太网为1500字节。实际在传输层考虑到PDU的消耗,使用1400字节比较合适。

cwnd:拥塞窗口大小

rwnd:接收方窗口大小

snd_queue:待发送KCP数据包的队列

snd_buf:发送缓冲区

snd_nxt:下一个即将发送的kcp数据包序列号

snd_una:下一个待确认的序列号

2.2 kcp协议头

0                            4               6           8  (BYTE)
+----------------------------+---------------+-----------+
|            conv            | cmd   |  frg  |    wnd    | 8   
+----------------------------+---------------+-----------+
|            ts              |            sn             | 16
+----------------------------+---------------------------+
|            una             |            len            | 24
+----------------------------+---------------------------+
|                        DATA (optional)                 |
+--------------------------------------------------------+
  • conv: 会话标识
  • cmd: 命令,如IKCP_CMD_ACK
  • frg: 分片标识
  • wnd: 接收窗口大小
  • ts: 时间序列
  • sn: 序列号
  • una: 下一个期待的数据序列号
  • len: 数据长度
  • data: 数据
2.2.1 ikcp中的主要数据结构
  • ikcp控制块,类似与tcp中的tcp控制块,保存每个kcp会话的核心数据。
struct IKCPCB
{
    /* 会话状态信息 */
    IUINT32 conv;   // 标识会话
    IUINT32 mtu;    // 最大传输单元,默认数据为1400,最小为50
    IUINT32 mss;    // 最大分片大小,不大于mtu
    IUINT32 state;  // 连接状态(0xffffffff表示断开连接)
    
    int nocwnd;     // 取消拥塞控制
    int stream;     // 是否采用流传输模式

    int logmask;    // 日志的类型,如IKCP_LOG_IN_DATA,方便调试
    
    /* 用于ARQ的字段 */
    IUINT32 snd_una;    // 第一个未确认的包
    IUINT32 snd_nxt;    // 下一个待分配包的序号
    IUINT32 rcv_nxt;	// 待接收消息序号
    
    IUINT32 ts_recent;	// 最近收到的数据的时间  
    IUINT32 ts_lastack;	// 上一个收到的ACK的时间
    
    IINT32  rx_rttval;      // RTT的变化量,代表连接的抖动情况
    IINT32  rx_srtt;        // smoothed round trip time,平滑后的RTT;
    IINT32  rx_rto;         // 收ACK接收延迟计算出来的重传超时时间
    IINT32  rx_minrto;      // 最小重传超时时间
    
    IUINT32 *acklist;   //待发送的ack的列表。当收到一个数据报文时,将其对应的ACK报文的 sn 号以及时间戳 ts 同时加入到acklist 中,即形成如 [sn1, ts1, sn2, ts2 …] 的列表
	
    /* 滑动窗口 */
    struct IQUEUEHEAD snd_queue;    //发送消息的队列 
    struct IQUEUEHEAD rcv_queue;    //接收消息的队列, 是已经确认可以供用户读取的数据
    struct IQUEUEHEAD snd_buf;      //发送消息的缓存 和snd_queue有什么区别
    struct IQUEUEHEAD rcv_buf;      //接收消息的缓存, 还不能直接供用户读取的数据
    
	/* 拥塞控制 */
    IUINT32 ssthresh;       // 拥塞窗口的阈值
    IUINT32 cwnd;           // 拥塞窗口大小, 动态变化
    ...;
    
    int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);//发送消息的回调函数
    void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);  // 写日志的回调函数
}
  • ikcp每个分片的数据结构
struct IKCPSEG
{
    struct IQUEUEHEAD node;
    IUINT32 conv;   // 会话编号,和TCP的con一样,确保双方需保证conv相同,相互的数据包才能被接收.conv唯一标识一个会话
    IUINT32 cmd;    // 区分不同的分片.IKCP_CMD_PUSH数据分片;IKCP_CMD_ACK:ack分片;IKCP_CMD_WASK:请求告知窗口大小;IKCP_CMD_WINS:告知窗口大小
    IUINT32 frg;    // 标识segment分片ID,用户数据可能被分成多个kcp包发送, 为0时代表   
    IUINT32 wnd;    // 剩余接收窗口大小(接收窗口大小-接收队列大小),发送方的发送窗口不能超过接收方给出的数值
    IUINT32 ts;     // 发送时刻的时间戳
    IUINT32 sn;     // 分片segment的序号,按1累加递增
    IUINT32 una;    // 待接收消息序号(接收滑动窗口左侧).对于未丢包的网络来说,una是下一个可接收的序号,如收到sn=10的包,una为11
    IUINT32 len;    // 数据长度
    IUINT32 resendts;   // 下次超时重传时间戳
    IUINT32 rto;        //该分片的超时等待时间,其计算方法同TCP
    IUINT32 fastack;    // 收到ack时计算该分片被跳过的累计次数,此字段用于快速重传,自定义需要几次确认开始快速重传
    IUINT32 xmit;       // 发送分片的次数,每发一次加1.发送的次数对RTO的计算有影响,但是比TCP来说,影响会小一些.
    char data[1];
};

2.2 KCP的使用方式

2.2.1 生成会话ID

会话ID用来标识客户端与服务器端的一条逻辑连接。

两种方式:

  • 客户端使用随机数产生uuid。
  • 服务器端产生唯一id然后通过http协议等传给客户端。

ikcp中的实现:

// read conv 获取会话id
IUINT32 ikcp_getconv(const void *ptr)
{
	IUINT32 conv;
	ikcp_decode32u((const char*)ptr, &conv);
	return conv;
}

/* decode 32 bits unsigned int (lsb) */
static inline const char *ikcp_decode32u(const char *p, IUINT32 *l)
{
#if IWORDS_BIG_ENDIAN || IWORDS_MUST_ALIGN
	*l = *(const unsigned char*)(p + 3);
	*l = *(const unsigned char*)(p + 2) + (*l << 8);
	*l = *(const unsigned char*)(p + 1) + (*l << 8);
	*l = *(const unsigned char*)(p + 0) + (*l << 8);
#else 
	memcpy(l, p, 4);
#endif
	p += 4;
	return p;
}

每个会话都对应一个kcp控制块,会话在构造时也会设置ikcpcb中的output回调函数,这样只需要封装号session类,用户就只需要与session打交道了。

2.2.2 流程
  • 创建KCP对象
ikcpcb *kcp = ikcp_create(conv, user);
  • 设置发送回调函数(如UDP的send函数)
kcp->output = udp_output;
  • 循环调用update
ikcp_update(kcp, millisec);	// 在一个线程、定时器5ms/10ms做调度
  • 输入一个应用层数据包(如UDP收到的数据包)
ikcp_input(kcp, received_udp_packet, received_udp, size);
  • 发送数据
ikcp_send(kcp1, buffer, 8);
  • 接收数据
hr = ikcp_recv(kcp2, buffer, 10);

需要注意,接收数据时需要用户先用UDP socket的API读取出数据,然后调用ikcp_input(),然后再调用ikcp_recv()。

2.2.3 KCP配置模式

工作模式

int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc)
  • nodelay: 是否开启ACK延迟确认,0不启用,1启用
  • interval: 协议内部工作工作的interval,单位ms,默认10ms
  • resend:是否开启快速重传模式,默认不开启
  • nc:是否关闭流控,默认不关闭

最大窗口

int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);	// 默认32

最大传输单元:

int ikcp_setmtu(ikcpcb *kcp, int mtu);	// 默认1400

最小RTO:

kcp->rx_minrto = 10;	// 快速模式下为30ms,可以手动更改

3. 重点问题

  1. tcp为什么可靠?

tcp的可靠性来自于滑动窗口和ARQ协议,它们保证了数据不丢失、不乱序。

  1. kcp为什么牺牲带宽换取速度?

kcp适用于对实时通讯要求较高的场景,例如直播、网络游戏等领域。它基于UDP协议,省去了三次握手的过程。kcp使用了自定义重传机制(如RTO、快速重传)、自定义是否启用拥塞控制,选择决绝ARQ也降低了重传成本。因此综合来看,kcp增加了网络中数据包的数量,但是提高了数据包的实时性。在不稳定的网络环境下,kcp的优势更为明显。

  1. udp怎么实现客户端和服务端编程?服务端怎么维护和客户端的逻辑连接?

UDP不能像tcp那样建立连接并长时间维持上下文信息,而只能通过每个数据包来源的目的地址和端口识别对方。为了维护逻辑连接,通常服务端可以使用一个具有唯一ID的会话保存特定客户端的信息。这个会话机制包括:

  • 客户端标识
  • 状态管理
  • 心跳机制

4. QUIC简介

QUIC(Quick UDP Internet Connections)是一种基于 UDP 的传输层协议,由 Google 开发,旨在为网络通信提供更快、更可靠的体验。QUIC 的设计目标是在保持低延迟的同时,提供与 TCP 相似的可靠性和拥塞控制,并解决一些传统 TCP 和 TLS 协议的缺点,比如慢启动、连接延迟高等问题。

4.1 QUIC 的核心特点

  • 低延迟连接建立

QUIC 通过将握手和加密合并到一个过程,使客户端和服务端能够在一次往返(1-RTT)中完成握手。对于已经建立过连接的客户端,QUIC 还支持 0-RTT 握手,这意味着客户端可以在发送初始请求的同时发送数据,极大地减少了连接延迟。

  • 集成的 TLS 加密

QUIC 将 TLS 1.3 协议集成在其协议栈中,从而在连接开始时即提供加密通信。这种方式不仅能提高连接安全性,还避免了传统 TCP 和 TLS 分别握手带来的延迟。

  • 多路复用

传统 TCP 实现 HTTP/2 的多路复用时,存在着“队头阻塞”问题(某个流的丢包会阻塞其他流的数据传输)。QUIC 通过流的独立处理机制,使每个流都可以独立地进行数据传输,避免了队头阻塞的情况。

  • 灵活的拥塞控制

QUIC 的拥塞控制算法可由实现方选择或配置,这使得它更具灵活性,可以根据网络情况灵活调整,进一步提高传输效率和稳定性。此外,QUIC 的流量控制机制可以控制流级别的数据量,以防止客户端或服务端被大量数据淹没。

  • 基于 UDP

QUIC 通过 UDP 实现,不受操作系统内核中 TCP 堆栈限制的影响,便于快速更新和改进协议,特别适合现代互联网的需求。

学习参考

学习更多相关知识请参考零声 github。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/901631.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 部署 mysql

Linux&#xff08;四&#xff09;- Ubuntu安装Mysql_mysql-community-server-core depends on libaio1 (>-CSDN博客 #创建用户 打开终端。 登录到MySQL服务器&#xff1a; mysql -u root -p 创建新用户。替换new_user为您想要的用户名&#xff0c;password为新用户的密码&am…

python异常监测-ARIMA(自回归积分滑动平均模型)

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 Python异常检测- DBSCAN Python异常检测- 单类支持向量机(…

python之数据结构与算法(数据结构篇)-- 元组

一、元组的概念 其实&#xff0c;所谓的“元组”就是一组不能改变的特殊数组(一般情况下)&#xff0c;这里我们去创建一个“小羊元组”&#xff0c;大家就能更加明白其中的意思了。 二、元组实现思路 1.我们去定义一个“羊村小羊”的元组 # 创建一个"羊村小羊"的元…

SystemC学习(2)— APB_SRAM的建模与测试

SystemC学习&#xff08;2&#xff09;— APB_SRAM的建模与测试 一、前言 二、APB_SRAM建模 编写APB_SRAM模型文件apb_sram.h文件如下所示&#xff1a; #ifndef __APB_SRAM_H #define __APB_SRAM_H#include "systemc.h"const int ADDR_SIZE 32; const int DATA_…

【专题】计算机网络之数据链路层

数据链路层的地位&#xff1a;网络中的主机、路由器等都必须实现数据链路层。 数据链路层信道类型&#xff1a; 点对点信道。 使用一对一的点对点通信方式。 广播信道。 使用一对多的广播通信方式。 必须使用专用的共享信道协议来协调这些主机的数据发送。 1. 使用点对点信道…

三次握手与四次挥手

1.三次握手 1.1状态机 客户端 SYN_SENT&#xff1a;客户端发送SYN报文段请求建立连接 ESTABLISHED&#xff1a;在收到服务端发来的SYN请求报文以及确认报文后就建立客户端到服务端的连接 服务端 LISTEN&#xff1a;一开始时LISTEN状态&#xff0c;等待客户端的SYN请求 SY…

群晖系统基本命令

切换超级管理员 sudo -i 查询系统 运行的所有服务 synoservicecfg --list 启动服务命令(该命令需要使用超级管理员) #老版本群晖使用synoservice命令 synoservice --start 服务名称#新版本群晖使用systemctl命令 systemctl start 服务名称 synoservice所管理的服务配置文…

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型&#xff0c;其中主要分为四类&#xff1a;数值类型、文本和二进制类型、时间日期、String 类型。如下&#xff08;图片来源&#xff1a;MySQL数据库&#xff09;&#xff1a; 目录如下&#xff1a; 目录 数值类型 1. 整数类型 2. …

【网站项目】SpringBoot397学校财务管理系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

【论文阅读】SRGAN

学习资料 论文题目&#xff1a;基于生成对抗网络的照片级单幅图像超分辨率&#xff08;Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network&#xff09;论文地址&#xff1a;https://arxiv.org/abs/1609.04802 代码&#xff1a;GitHub - x…

【Python爬虫实战】Selenium自动化网页操作入门指南

#1024程序员节&#xff5c;征文# &#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、准备工作 &#xff08;一&#xff09;安装 Selenium 库 &#xff0…

SpringBoot项目里怎么简单高效使用Redis?我选择使用Lock4j

文章目录 前言正文1、Lock4j的代码仓库2、pine-manage-common-redis的项目结构3、pine-manage-common-redis 的完整代码3.1 maven依赖&#xff1a;pom.xml3.2 redis连接参数&#xff1a;application.yaml3.3 RedisCache.java3.4 CacheConfig.java3.5 RedissonClientUtil.java3.…

Python | Leetcode Python题解之第509题斐波那契数

题目&#xff1a; 题解&#xff1a; class Solution:def fib(self, n: int) -> int:if n < 2:return nq [[1, 1], [1, 0]]res self.matrix_pow(q, n - 1)return res[0][0]def matrix_pow(self, a: List[List[int]], n: int) -> List[List[int]]:ret [[1, 0], [0, …

Redisson(三)应用场景及demo

一、基本的存储与查询 分布式环境下&#xff0c;为了方便多个进程之间的数据共享&#xff0c;可以使用RedissonClient的分布式集合类型&#xff0c;如List、Set、SortedSet等。 1、demo <parent><groupId>org.springframework.boot</groupId><artifact…

spygalss cdc 检测的bug(二)

当allow_qualifier_merge设置为strict的时候&#xff0c;sg是要检查门的极性的。 如果qualifier和src经过与门汇聚&#xff0c;在同另一个src1信号或门汇聚&#xff0c;sg是报unsync的。 假设当qualifier为0时&#xff0c;0&&src||src1src1&#xff0c;src1无法被gat…

Mysql入门3——多表操作、事务、索引

Mysql入门3——多表操作、事务、索引 一、多表设计 ​ 在项目开发中&#xff0c;在进行数据库表的结构设计时&#xff0c;会根据业务需求及业务模块之前的关系&#xff0c;分析并设计表的结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表之间也存在着各种关系&am…

基于SSM的智慧篮球馆预约系统

前言 近些年&#xff0c;随着中国经济发展&#xff0c;人民的生活质量逐渐提高&#xff0c;对网络的依赖性越来越高&#xff0c;通过网络处理的事务越来越多。随着智慧篮球馆预约的常态化&#xff0c;如果依然采用传统的管理方式&#xff0c;将会为工作人员带来庞大的工作量&a…

css设置滚动条样式

效果图&#xff1a; // 滚动条样式 div::-webkit-scrollbar {width: 4px; } /* 滚动条滑块&#xff08;里面小方块&#xff09; */ div::-webkit-scrollbar-thumb {border-radius: 10px;-webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);opacity: 0.2;background-color…

【面试经典150】day 8

#1024程序员节 | 征文# 作为一个未来的程序员&#xff0c;现在我要继续刷题了。 力扣时刻。 目录 1.接雨水 2.罗马数字转整数 3.最后一个单词的长度 4.最长公共前缀 5.反转字符串中的单词 1.接雨水 好好好好好好&#xff0c;一开始就接雨水。我记得接了n次了。。。 痛苦战…

【读书笔记·VLSI电路设计方法解密】问题25:为什么时钟如此重要

时钟是一种在高电平和低电平之间振荡的电信号。它通常是一个具有预定周期(频率)的方波,如图3.6所示。在同步数字电路中,时钟信号协调芯片上所有电路元件的动作。电路在时钟信号的上升沿、下降沿或两者的边缘处变为活动状态以实现同步。时钟信号相关问题是任何VLSI芯片设计中…