10G UDP协议栈 (9)UDP模块

news2024/12/25 1:18:40

目录

一、UDP协议简单介绍

二、UDP功能实现

三、仿真

一、UDP协议简单介绍

UDP协议和TCP协议同位于传输层,介于网络层(IP)和应用层之间:UDP数据部分为应用层报文,而UDP报文在IP中承载。

UDP 报文格式相对于简单,如下图:


源端口:端口号0-65535,1-1024保留端口号,为标准的服务端口
目的端口:无须多解释
UDP长度:header+data 总长度
UDP校验和:伪头部,头部,data 三部分校验和。
数据:上层应用层的数据。

 UDP校验和计算:UDP校验和计算-CSDN博客

二、UDP功能实现

UDP_RX模块功能:接收IP层传递过来的数据,判断数据中的目的端口号是否与本节点的源端口号相同,同时执行UDP校验和计算。(由于此时的校验是对整个UDP首部+UDP伪首部+UDP数据进行校验,所以可以参考IP校验的方式,将数据暂存在一个RAM中,根据校验和的正确性控制地址的分配)。

UDP_TX模块功能:将上层传递过来的数据封装上UDP头,并进行UDP校验和计算。(此时的校验和计算可以先将封装完毕的UDP帧存储在一个RAM中,并在一帧的结尾单独对UDP校验和所在的地址进行操作)。

UDP_TX模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/22 10:38:55
// Design Name: 
// Module Name: UDP_TX
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module UDP_TX#(
    parameter           P_SOURCE_PORT = 16'd8080    ,
    parameter           P_TARGET_PORT = 16'd8080    
)(
    input               i_clk                       ,
    input               i_rst                       ,

    input  [15:0]       i_set_source_port           ,
    input               i_set_source_valid          ,
    input  [15:0]       i_set_target_port           ,
    input               i_set_target_valid          ,

    input  [63:0]       s_axis_user_data            ,
    input  [31:0]       s_axis_user_user            ,//16'dByteLen,16'dBrust
    input  [7 :0]       s_axis_user_keep            ,
    input               s_axis_user_last            ,
    input               s_axis_user_valid           ,
    output              s_axis_user_ready           ,

    output [63:0]       m_axis_ip_data              ,
    output [70:0]       m_axis_ip_user              ,//16'dByteLen,1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dID
    output [7 :0]       m_axis_ip_keep              ,
    output              m_axis_ip_last              ,
    output              m_axis_ip_valid             ,
    input               m_axis_ip_ready             
);

reg  [15:0]             ri_set_source_port          ;
reg  [15:0]             ri_set_target_port          ;
reg  [63:0]             rs_axis_user_data           ;
reg  [31:0]             rs_axis_user_user           ;
reg  [7 :0]             rs_axis_user_keep           ;
reg                     rs_axis_user_last           ;
reg                     rs_axis_user_valid          ;
reg                     rs_axis_user_ready          ;
reg  [63:0]             rm_axis_ip_data             ;
reg  [70:0]             rm_axis_ip_user             ;
reg  [7 :0]             rm_axis_ip_keep             ;
reg                     rm_axis_ip_last             ;
reg                     rm_axis_ip_valid            ;
reg                     r_fifo_data_rden            ;
reg  [15:0]             r_cnt                       ;
reg  [7 :0]             r_last_keep                 ;
reg                     r_fifo_data_empty           ;
reg                     r_fifo_data_empty_1d        ;

wire [63:0]             w_fifo_data_dout            ;
wire                    w_fifo_data_full            ;
wire                    w_fifo_data_empty           ;

assign s_axis_user_ready = rs_axis_user_ready       ;
assign m_axis_ip_data  = rm_axis_ip_data            ;
assign m_axis_ip_user  = rm_axis_ip_user            ;
assign m_axis_ip_keep  = rm_axis_ip_keep            ;
assign m_axis_ip_last  = rm_axis_ip_last            ;
assign m_axis_ip_valid = rm_axis_ip_valid           ;
//将用户传输的数据缓存
FIFO_DATA_64X256 FIFO_DATA_64X256_u0 (
  .clk                  (i_clk                      ), 
  .srst                 (i_rst                      ),
  .din                  (rs_axis_user_data          ), 
  .wr_en                (rs_axis_user_valid         ),
  .rd_en                (r_fifo_data_rden           ),
  .dout                 (w_fifo_data_dout           ),
  .full                 (w_fifo_data_full           ),
  .empty                (w_fifo_data_empty          )
);

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        r_fifo_data_empty <= 'd0;
        r_fifo_data_empty_1d <= 'd0;
    end else begin
        r_fifo_data_empty <= w_fifo_data_empty;
        r_fifo_data_empty_1d <= r_fifo_data_empty;
    end
end
//动态配置源端口、目的端口
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_source_port <= P_SOURCE_PORT;
    else if(i_set_source_valid)
        ri_set_source_port <= i_set_source_port;
    else 
        ri_set_source_port <= ri_set_source_port;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_target_port <= P_TARGET_PORT;
    else if(i_set_target_valid)
        ri_set_target_port <= i_set_target_port;
    else 
        ri_set_target_port <= ri_set_target_port;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        rs_axis_user_data  <= 'd0;
        rs_axis_user_keep  <= 'd0;
        rs_axis_user_last  <= 'd0;
        rs_axis_user_valid <= 'd0;
    end else begin
        rs_axis_user_data  <= s_axis_user_data ;
        rs_axis_user_keep  <= s_axis_user_keep ;
        rs_axis_user_last  <= s_axis_user_last ;
        rs_axis_user_valid <= s_axis_user_valid;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) 
        rs_axis_user_user <= 'd0;
    else if(s_axis_user_valid)
        rs_axis_user_user  <= s_axis_user_user ;
    else 
        rs_axis_user_user <= rs_axis_user_user;
end
//控制ready信号,当一帧输入时将ready信号拉低
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rs_axis_user_ready <= 'd1;
    else if(s_axis_user_last)
        rs_axis_user_ready <= 'd0;
    else if(r_fifo_data_empty_1d)
        rs_axis_user_ready <= 'd1;
    else 
        rs_axis_user_ready <= rs_axis_user_ready;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_last_keep <= 'd0;
    else if(s_axis_user_last)
        r_last_keep <= s_axis_user_keep;
    else 
        r_last_keep <= r_last_keep;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_cnt <= 'd0;
    else if(r_cnt == rs_axis_user_user[15:0])
        r_cnt <= 'd0;
    else if(r_fifo_data_rden || r_cnt)
        r_cnt <= r_cnt + + 1;
    else 
        r_cnt <= r_cnt;
end
//控制fifo读使能,当FIFO不为空的时候开始读
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_fifo_data_rden <= 'd0;
    else if(r_cnt == rs_axis_user_user[15:0] - 1)
        r_fifo_data_rden <= 'd0;
    else if(!w_fifo_data_empty)
        r_fifo_data_rden <= 'd1;
    else         
        r_fifo_data_rden <= r_fifo_data_rden;
end 
//组UDP帧
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ip_data <= 'd0;
    else case(r_cnt)
        0           :rm_axis_ip_data <= {ri_set_source_port,ri_set_target_port,rs_axis_user_user[31:16] + 16'd8,16'd0};//源端口号、目的端口号、UDP长度、UDP校验和(暂时为0)
        default     :rm_axis_ip_data <= w_fifo_data_dout;
    endcase
end
//控制Keep信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ip_keep <= 'd0;
    else if(r_cnt && r_cnt == rs_axis_user_user[15:0] - 0)
        rm_axis_ip_keep <= r_last_keep;
    else 
        rm_axis_ip_keep <= 8'b1111_1111;
end
//控制Last信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ip_last <= 'd0;
    else if(r_cnt && r_cnt == rs_axis_user_user[15:0] - 0)
        rm_axis_ip_last <= 'd1;
    else 
        rm_axis_ip_last <= 'd0;
end
//控制Valid信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ip_valid <= 'd0;
    else if(rm_axis_ip_last)
        rm_axis_ip_valid <= 'd0;
    else if(r_fifo_data_rden)
        rm_axis_ip_valid <= 'd1;
    else        
        rm_axis_ip_valid <= rm_axis_ip_valid;
end

//16'dByteLen,1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dID
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ip_user <= 'd0;
    else 
        rm_axis_ip_user <= {rs_axis_user_user[31:16] + 16'd8,1'b0,rs_axis_user_user[15:0] + 16'd1,1'b0,8'd17,13'd0,16'd0};
end

endmodule

UDP_RX模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/22 10:38:55
// Design Name: 
// Module Name: UDP_RX
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module UDP_RX#(
    parameter           P_SOURCE_PORT = 16'd8080    ,
    parameter           P_TARGET_PORT = 16'd8080    
)(
    input               i_clk                       ,
    input               i_rst                       ,

    input  [15:0]       i_set_source_port           ,
    input               i_set_source_valid          ,
    input  [15:0]       i_set_target_port           ,
    input               i_set_target_valid          ,

    input  [63:0]       s_axis_ip_data              ,
    input  [54:0]       s_axis_ip_user              ,//1'bMF,16'dlen,1'bsplit,8'dtype,13'doffset,16'dID
    input  [7 :0]       s_axis_ip_keep              ,
    input               s_axis_ip_last              ,
    input               s_axis_ip_valid             ,
//上层数据
    output [63:0]       m_axis_user_data            ,
    output [31:0]       m_axis_user_user            ,
    output [7 :0]       m_axis_user_keep            ,
    output              m_axis_user_last            ,
    output              m_axis_user_valid           
);

reg  [15:0]             ri_set_source_port          ;
reg  [15:0]             ri_set_target_port          ;
reg  [63:0]             rs_axis_ip_data             ;
reg  [54:0]             rs_axis_ip_user             ;
reg  [7 :0]             rs_axis_ip_keep             ;
reg                     rs_axis_ip_last             ;
reg                     rs_axis_ip_valid            ;
reg  [63:0]             rm_axis_user_data           ;
reg  [31:0]             rm_axis_user_user           ;
reg  [7 :0]             rm_axis_user_keep           ;
reg                     rm_axis_user_last           ;
reg                     rm_axis_user_valid          ;
reg  [15:0]             r_cnt                       ;
reg  [15:0]             r_source_port               ;
reg  [15:0]             r_target_port               ;
reg  [15:0]             r_len                       ;
reg  [7 :0]             r_last_keep                 ;   
reg                     r_udp_flag                  ;
reg                     r_port_check                ;

assign m_axis_user_data  = rm_axis_user_data        ;
assign m_axis_user_user  = rm_axis_user_user        ;
assign m_axis_user_keep  = rm_axis_user_keep        ;
assign m_axis_user_last  = rm_axis_user_last        ;
assign m_axis_user_valid = rm_axis_user_valid       ;

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        rs_axis_ip_data  <= 'd0;
        rs_axis_ip_user  <= 'd0;
        rs_axis_ip_keep  <= 'd0;
        rs_axis_ip_last  <= 'd0;
        rs_axis_ip_valid <= 'd0;
    end else begin
        rs_axis_ip_data  <= s_axis_ip_data ;
        rs_axis_ip_user  <= s_axis_ip_user ;
        rs_axis_ip_keep  <= s_axis_ip_keep ;
        rs_axis_ip_last  <= s_axis_ip_last ;
        rs_axis_ip_valid <= s_axis_ip_valid;
    end    
end
//动态配置端口号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_source_port <= P_SOURCE_PORT;
    else if(i_set_source_valid)
        ri_set_source_port <= i_set_source_port;
    else 
        ri_set_source_port <= ri_set_source_port;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ri_set_target_port <= 'd0;
    else if(i_set_target_valid)
        ri_set_target_port <= i_set_target_port;
    else 
        ri_set_target_port <= ri_set_target_port;
end
//保存最后一次的Keep信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_last_keep <= 'd0;
    else if(s_axis_ip_last)
        r_last_keep <= s_axis_ip_keep;
    else 
        r_last_keep <= 8'b1111_1111;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_cnt <= 'd0;
    else if(rs_axis_ip_valid)
        r_cnt <= r_cnt + 1;
    else 
        r_cnt <= 'd0;
end
//获取IP层传递过来的数据的源端口号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_source_port <= 'd0;
    else if(rs_axis_ip_valid && r_cnt == 0)
        r_source_port <= rs_axis_ip_data[63:48];
    else 
        r_source_port <= r_source_port;
end
//获取IP层传递过来的数据的目的端口号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_target_port <= 'd0;
    else if(rs_axis_ip_valid && r_cnt == 0)
        r_target_port <= rs_axis_ip_data[47:32];
    else 
        r_target_port <= r_target_port;
end
//检测获取的源端口号是否等于本节点的目的端口号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_port_check <= 'd0;
    else if(r_cnt == 1 && r_target_port != ri_set_source_port)       
        r_port_check <= 'd0;
    else if(r_cnt == 1 && r_target_port == ri_set_source_port)
        r_port_check <= 'd1;
    else 
        r_port_check <= r_port_check;
end
//获取数据净荷的长度
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_len <= 'd0;
    else if(rs_axis_ip_valid && r_cnt == 0)
        r_len <= rs_axis_ip_data[31:16] - 16'd8;
    else 
        r_len <= r_len;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_user_data <= 'd0;
    else
        rm_axis_user_data <= rs_axis_ip_data;
end
//控制向上传递的USER信号,其中r_len代表字节长度,(r_len - 16'd1) >> 16'd3代表以8字节为单位的传输次数
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_user_user <= 'd0;
    else 
        rm_axis_user_user <= {r_len,((r_len - 16'd1) >> 16'd3) + 16'd1};
end 
//控制keep信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_user_keep <= 'd0;
    else if(rs_axis_ip_last)
        rm_axis_user_keep <= r_last_keep;
    else 
        rm_axis_user_keep <= 8'b1111_1111;
end
//控制Last信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)   
        rm_axis_user_last <= 'd0;
    else if(rs_axis_ip_last && rm_axis_user_valid)
        rm_axis_user_last <= 'd1;
    else 
        rm_axis_user_last <= 'd0;
end
//控制Valid信号
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)  
        rm_axis_user_valid <= 'd0;
    else if(rm_axis_user_last)
        rm_axis_user_valid <= 'd0;
    else if(rs_axis_ip_valid && r_cnt == 1 && r_port_check && r_udp_flag)
        rm_axis_user_valid <= 'd1;
    else 
        rm_axis_user_valid <= rm_axis_user_valid;
end
//检查本次从IP层获取的信号是否为UDP数据
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)  
        r_udp_flag <= 'd0;
    else if(s_axis_ip_valid && !rs_axis_ip_valid && s_axis_ip_user[36:29] != 17)
        r_udp_flag <= 'd0;
    else if(s_axis_ip_valid && !rs_axis_ip_valid && s_axis_ip_user[36:29] == 17)
        r_udp_flag <= 'd1;
    else 
        r_udp_flag <= r_udp_flag;
end

endmodule

三、仿真

UDP_TX模块:

UDP_RX模块:

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单工无线发射接收系统

1 绪论 随着无线电技术的发展,通讯方式也从传统的有线通讯逐渐转向无线通讯。由于传统的有线传输系统有配线的问题,较不便利,而无线通讯具有成本廉价、建设工程周期短、适应性好、扩展性好、设备维护容易实现等特点,故未来通讯方式将向无线传输系统方向发展。同时,实现系…

leedcode【203】. 移除链表元素——Java解法

Problem: 203. 移除链表元素 题目思路解题方法复杂度Code效果 题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val…

【图解IO与Netty系列】IO多路复用

IO多路复用 为什么要使用IO多路复用Linux的IO多路复用接口selectpollepoll 为什么要使用IO多路复用 我们常用的IO模型是BIO&#xff0c;我们Java里的IO流大多数都是BIO&#xff0c;也就是同步阻塞式IO&#xff0c;这种IO操作的好处是简单方便&#xff0c;但是缺点也很明显——…

【技术实操】银河高级服务器操作系统实例分享,TCP长连接与短连接详细说明

1.服务器环境以及配置 物理机/虚拟机/云/容器 物理机 处理器&#xff1a; HUAWEI Kunpeng 920 具体操作系统版本 Kylin-Server-10-SP1-Release-Build20-20210518- aarch64 内核版本 kernel-4.19.90-23.8.v2101.ky10.aarch64 2.问题现象描述 对TCP长连接有疑问 1、如何…

Yolov8训练自己的数据集(脱离ultralytics库)

最近在整理关于yolov8的相关内容&#xff0c;有个很大的问题&#xff0c;抛开yolov8性能不谈&#xff0c;yolov8代码的使用灵活性不如yolov5&#xff0c;尤其是对于一些新手或者对yolo框架不是很熟悉的人(这也是因人而异&#xff0c;有些人可能会喜欢v8代码的使用方式)。比如在…

牛客网刷题 | BC94 反向输出一个四位数

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 将一个四位数&…

1.int 与 Integer 的简单区别

蓝桥杯刷题从此开始&#xff1a; 第一题就是两个数的和&#xff0c;个人看来主要考察 int与integer 的区别&#xff1b; 这是我提交的答案&#xff0c;竟然会报错&#xff1a; import java.util.*; //输入A、B&#xff0c;输出AB。 class add {public static void main(String …

MT7628原厂Uboot修改交互串口

工作中&#xff0c;遇到用户用Skylab的SKW92A模组&#xff0c;在参考设计时&#xff0c;将UART接口预留错的情况&#xff0c;对于这种情况&#xff0c;需要将原厂SDK默认的交互串口UART0&#xff0c;改为UART1。在开发过程中&#xff0c;经常需要在Uboot阶段升级固件&#xff0…

5.25机器人基础-空间描述和变换1

参考资料&#xff1a;《机器人学导论》John.J.Craig 彻底搞懂“旋转矩阵/欧拉角/四元数”&#xff0c;让你体会三维旋转之美_欧拉角判断动作-CSDN博客 机器人操作的定义是指通过某种机构使零件和工具在空间运动。因此&#xff0c;对于坐标系的定义显得尤为重要&#xff0c;相…

【docker】Docker的基本指令和HTML/PYTHON/C++的简单创建示例

目录 &#x1f30a;1. 什么是 Docker&#xff1f; &#x1f30a;2. Docker 安装 &#x1f30a;3. Docker基本指令 &#x1f30a;4. Docker 创建示例【联网情况】 &#x1f30d;4.1 示例&#xff1a;HTML &#x1f30d;4.2 示例&#xff1a;Python 脚本 &#x1f30d;4.3…

log4j2远程代码执行

漏洞复现 漏洞复现2 这个框架不是web框架了&#xff0c;不是服务器web网站框架了&#xff0c;是java日志框架&#xff0c;就是记录日志信息&#xff0c;每一个程序都有一个日志文件&#xff0c;这个就是java里面记录日志的一个框架&#xff0c;它存在的点也是日志框架那几个代…

Python语法(全)

前言&#xff1a; 下面是Python基本的语法&#xff0c;大家耐心观看&#xff01; 1.基础语法 1.1字面量 字面量&#xff1a;在代码中&#xff0c;被写下来的的固定的值&#xff0c;称之为字面 1.2字符串 字符串&#xff08;string&#xff09;&#xff0c;又称文本&#xff…

防火墙——域网络、专用网络、公用网络

在防火墙设置中&#xff0c;域网络、专用网络和公用网络是指计算机连接到网络时所处的不同环境。每种环境都有不同的安全级别和配置。 1、域网络&#xff08;宽松&#xff09; 域网络是指计算机加入了一个Windows域&#xff08;Domain&#xff09;环境&#xff0c;这通常在企业…

v-rep---script-function

作用&#xff0c;实现&#xff0c;参数讲解。 script-function标签 作用 问题&#xff1a;如何在插件的接口中调用lua脚本中定义的函数&#xff1f; 用于声明一个函数&#xff0c;这个函数的作用是通过v-rep提供的接口sim::callScriptFunctionEx()调用脚本的函数&#xff0…

用AI比赛助手降维打击数学建模,比赛过程详细介绍,这保研不就稳了吗

数学建模是个小众的赛道&#xff0c;可能很多大学生不知道&#xff0c;简单来说&#xff1a;他能薅学分、保研加分、毕业好找工作(简历上写一辈子)&#xff0c;尤其是基于GPT-4o模型&#xff0c;简直对他们是降维打击。 数学建模每年的比赛非常多&#xff0c;像国赛、美赛、深…

直流电机的基本原理与结构

一些基本定理 磁感应强度&#xff08;又称磁通密度&#xff09;B —— 表征磁场强弱及方向的物理量。单位&#xff1a;T 右手定则&#xff1a;伸开右手&#xff0c;使拇指与其余四个手指垂直&#xff0c;并且都与手掌在同一平面内&#xff1b;让磁感线从手心进入&#xff0c;…

软件设计师基础知识难点总结

软件设计师基础知识难点 I/O设备管理软件一般分为4个层次&#xff0c;如下图所示。 用户进程与设备无关的系统软件设备驱动程序中断处理程序硬件 直接查询控制 分为有无条件传送和程序查询方式&#xff0c;都需要通过CPU执行程序来查询外设的状态&#xff0c;判断外设是否准备好…

牛客热题:有效括号

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;有效括号题目链接方法一&#x…

数据结构--二叉搜索树

目录 二叉搜索树的概念 二叉树的实现 结点类 函数接口总览 实现二叉树 二叉搜索树的应用 K模型 KV模型 二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称BST&#xff09;是一种特殊的二叉树&#xff0c;其具有以下几…

CSP俄罗斯方块(简单易懂)

开始将题目理解成了&#xff0c;开始的列应该是从输入图案的最左端开始计算&#xff0c;将前面所有的空列都删掉&#xff0c;代码如下&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e410; const int M 1e510; int a[20][20]; int b[5][5];int…