【UEFI基础】EDK网络框架(TCP4)

news2024/12/27 17:28:09

TCP4

TCP4协议说明

相比UDP4,TCP4是一种面向连接的通信协议,因此有更好的可靠性。

TCP4的首部格式如下:

在这里插入图片描述

各个参数说明如下:

字段长度(bit)含义
Source Port16源端口,标识哪个应用程序发送。
Destination Port16目的端口,标识哪个应用程序接收。
Sequence Number32序号字段。
TCP链接中传输的数据流中每个字节都编上一个序号。
序号字段的值指的是本报文段所发送的数据的第一个字节的序号。
Acknowledgment Number32确认号。
是期望收到对方的下一个报文段的数据的第1个字节的序号。
即上次已成功接收到的数据字节序号加1。
只有ACK标识为1,此字段有效。
Data Offset4数据偏移,即首部长度。
指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。
以32比特(4字节)为计算单位。
最多有60字节的首部,若无选项字段,正常为20字节。
Reserved6保留,必须填0。
URG1紧急指针有效标识。
它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。
ACK1确认序号有效标识。
只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。
PSH1标识接收方应该尽快将这个报文段交给应用层。
接收到PSH = 1的TCP报文段,应尽快的交付接收应用进程,而不再等待整个缓存都填满了后再向上交付。
RST1重建连接标识。
当RST=1时,表明TCP连接中出现严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立连接。
SYN1同步序号标识,用来发起一个连接。
SYN=1表示这是一个连接请求或连接接受请求。
FIN1发端完成发送任务标识。
用来释放一个连接。
FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。
Window16窗口:TCP的流量控制。
窗口起始于确认序号字段指明的值,这个值是接收端期望接收的字节数。
窗口最大为65535字节。
Checksum16校验字段,包括TCP首部和TCP数据,是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。
在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。
Urgent Pointer16紧急指针,只有当URG标志置1时紧急指针才有效。
TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。
紧急指针指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)。
Options可变选项字段。
TCP协议最初只规定了一种选项,即最长报文段长度(只包含数据字段,不包括TCP首部),又称为MSS。
MSS告诉对方TCP“我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节”。
新的RFC规定有以下几种选型:选项表结束,空操作,最大报文段长度,窗口扩大因子,时间戳。
* 选项表结束。
* 空操作:没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍。
* 最大报文段长度:又称为MSS,只包含数据字段,不包括TCP首部。
* 窗口扩大因子:3字节,其中一个字节表示偏移值S。新的窗口值等于TCP首部中的窗口位数增大到(16+S),相当于把窗口值向左移动S位后获得实际的窗口大小。
* 时间戳:10字节,其中最主要的字段是时间戳值(4字节)和时间戳回送应答字段(4字节)。
Padding可变填充字段,用来补位,使整个首部长度是4字节的整数倍。
data可变TCP负载。

对应UEFI中的代码:

typedef UINT32  TCP_SEQNO;
typedef UINT16  TCP_PORTNO;

//
// TCP header definition
//
typedef struct {
  TCP_PORTNO    SrcPort;
  TCP_PORTNO    DstPort;
  TCP_SEQNO     Seq;
  TCP_SEQNO     Ack;
  UINT8         Res     : 4;
  UINT8         HeadLen : 4;
  UINT8         Flag;
  UINT16        Wnd;
  UINT16        Checksum;
  UINT16        Urg;
} TCP_HEAD;

TCP的连接过程大致如下:

在这里插入图片描述

TCP4代码综述

TCP4也是一个通用的网络协议,其实现在NetworkPkg\TcpDxe\TcpDxe.inf,这里首先需要看下它的入口:

EFI_STATUS
EFIAPI
TcpDriverEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  //
  // Install the TCP Driver Binding Protocol
  //
  Status = EfiLibInstallDriverBindingComponentName2 (
             ImageHandle,
             SystemTable,
             &gTcp4DriverBinding,
             ImageHandle,
             &gTcpComponentName,
             &gTcpComponentName2
             );

  //
  // Initialize ISS and random port.
  //
  Seed            = NetRandomInitSeed ();
  mTcpGlobalIss   = NET_RANDOM (Seed) % mTcpGlobalIss;
  mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
}

因为TCP4也是一个UEFI Driver Model,所以第一步是安装gTcp4DriverBinding,其实现:

EFI_DRIVER_BINDING_PROTOCOL  gTcp4DriverBinding = {
  Tcp4DriverBindingSupported,
  Tcp4DriverBindingStart,
  Tcp4DriverBindingStop,
  0xa,
  NULL,
  NULL
};

而第二步是初始化一个随机的TCP端口,根据通用网络协议的做法,TCP的端口占两个字节(即16位),只要不是0-1023里面的公认端口都可以,且跟UDP端口的一致也没有关系。

最后还有一个mTcpGlobalIss,这里的ISS全称是Initial Sending Sequence,它的值本身不是很重要,从名字也知道它的作用就是指定TCP发送的第一个包的序列号,这是因为TCP一次发送的包可能会有很多,所以需要排序。

UDP4在UEFI网络协议栈中的关系图:

支持
提供
支持
支持
提供
支持
提供
提供
提供
支持
提供
提供
支持
支持
提供
提供
提供
支持
提供
提供
gEfiPciIoProtocolGuid
UNDI
gEfiNetworkInterfaceIdentifierProtocolGuid_31
gEfiDevicePathProtocolGuid
SNP
gEfiSimpleNetworkProtocolGuid
MNP
gEfiVlanConfigProtocolGuid
gEfiManagedNetworkServiceBindingProtocolGuid
gEfiManagedNetworkProtocolGuid
ARP
gEfiArpServiceBindingProtocolGuid
gEfiArpProtocolGuid
IP4
gEfiIp4ServiceBindingProtocolGuid
gEfiIp4Config2ProtocolGuid
gEfiIp4ProtocolGuid
UDP4
gEfiTcp4ServiceBindingProtocolGuid
gEfiTcp4ProtocolGuid

Tcp4DriverBindingSupported

TCP4依赖于IP4:

EFI_STATUS
EFIAPI
Tcp4DriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
  )
{
  //
  // Test for the Ip4ServiceBinding Protocol
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiIp4ServiceBindingProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  return Status;
}

Tcp4DriverBindingStart

Start函数里面只有一个函数TcpCreateService(),它的作用就是初始化TCP_SERVICE_DATA

TCP_SERVICE_DATA

该结构体本身也比较简单:

typedef struct _TCP_SERVICE_DATA {
  UINT32                          Signature;
  EFI_HANDLE                      ControllerHandle;
  EFI_HANDLE                      DriverBindingHandle;
  UINT8                           IpVersion;
  IP_IO                           *IpIo;
  EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;
  LIST_ENTRY                      SocketList;
} TCP_SERVICE_DATA;

其重点其实就是一个SocketList,它对应列表成员是SOCKET

SOCKET

Socket就是TCP的子项。该结构体如下:

///
/// The socket structure representing a network service access point.
///
struct _TCP_SOCKET {
  //
  // Socket description information
  //
  UINT32                      Signature;     ///< Signature of the socket
  EFI_HANDLE                  SockHandle;    ///< The virtual handle of the socket
  EFI_HANDLE                  DriverBinding; ///< Socket's driver binding protocol
  EFI_DEVICE_PATH_PROTOCOL    *ParentDevicePath;
  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
  LIST_ENTRY                  Link;
  UINT8                       ConfigureState;
  SOCK_TYPE                   Type;
  UINT8                       State;
  UINT16                      Flag;
  EFI_LOCK                    Lock;         ///< The lock of socket
  SOCK_BUFFER                 SndBuffer;    ///< Send buffer of application's data
  SOCK_BUFFER                 RcvBuffer;    ///< Receive buffer of received data
  EFI_STATUS                  SockError;    ///< The error returned by low layer protocol
  BOOLEAN                     InDestroy;

  //
  // Fields used to manage the connection request
  //
  UINT32                      BackLog;        ///< the limit of connection to this socket
  UINT32                      ConnCnt;        ///< the current count of connections to it
  SOCKET                      *Parent;        ///< listening parent that accept the connection
  LIST_ENTRY                  ConnectionList; ///< the connections maintained by this socket
  //
  // The queue to buffer application's asynchronous token
  //
  LIST_ENTRY                  ListenTokenList;
  LIST_ENTRY                  RcvTokenList;
  LIST_ENTRY                  SndTokenList;
  LIST_ENTRY                  ProcessingSndTokenList;

  SOCK_COMPLETION_TOKEN       *ConnectionToken; ///< app's token to signal if connected
  SOCK_COMPLETION_TOKEN       *CloseToken;      ///< app's token to signal if closed
  //
  // Interface for low level protocol
  //
  SOCK_PROTO_HANDLER          ProtoHandler;                      ///< The request handler of protocol
  UINT8                       ProtoReserved[PROTO_RESERVED_LEN]; ///< Data fields reserved for protocol
  UINT8                       IpVersion;
  NET_PROTOCOL                NetProtocol;                      ///< TCP4 or TCP6 protocol socket used
  //
  // Callbacks after socket is created and before socket is to be destroyed.
  //
  SOCK_CREATE_CALLBACK        CreateCallback;  ///< Callback after created
  SOCK_DESTROY_CALLBACK       DestroyCallback; ///< Callback before destroyed
  VOID                        *Context;        ///< The context of the callback
};

该结构体的创建来自SockCreate(),其调用流程:

TcpServiceBindingCreateChild
SockCreateChild
PktRcvdNotify
TcpRxCallback
TcpInput
TcpCloneTcb
SockClone
SockCreate

左边的PktRcvdNotify是IP4中的回调函数,右边就是常用的创建子项的函数。

SOCKET中的主要成员说明如下:

  • SockHandleNetProtocol:这两个参数需要一起看,它们的初始化位于SockCreate()函数中:
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Sock->SockHandle,
                  TcpProtocolGuid,
                  &Sock->NetProtocol,
                  NULL
                  );

事实上就是安装了一个Protocol,对应的GUID是TcpProtocolGuid,它其实就是两个选择,v4和v6,对应到NetProtocol也就有了两个版本:

  if (SockInitData->IpVersion == IP_VERSION_4) {
    TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
    ProtocolLength  = sizeof (EFI_TCP4_PROTOCOL);
  } else {
    TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
    ProtocolLength  = sizeof (EFI_TCP6_PROTOCOL);
  }

我们需要关注的是gEfiTcp4ProtocolGuidEFI_TCP4_PROTOCOL,后者对应结构体:

struct _EFI_TCP4_PROTOCOL {
  EFI_TCP4_GET_MODE_DATA    GetModeData;
  EFI_TCP4_CONFIGURE        Configure;
  EFI_TCP4_ROUTES           Routes;
  EFI_TCP4_CONNECT          Connect;
  EFI_TCP4_ACCEPT           Accept;
  EFI_TCP4_TRANSMIT         Transmit;
  EFI_TCP4_RECEIVE          Receive;
  EFI_TCP4_CLOSE            Close;
  EFI_TCP4_CANCEL           Cancel;
  EFI_TCP4_POLL             Poll;
};

就是真正用于收发数据的TCP接口。

  • DriverBinding:这个值来自SOCK_INIT_DATA中的DriverBinding
Sock->DriverBinding       = SockInitData->DriverBinding;

而后者有来自TCP_SERVICE_DATA中的DriverBindingHandle

mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;

所以说到底SOCKET中的DriverBinding就是TCP_SERVICE_DATA中的DriverBindingHandle,最终就是EFI_DRIVER_BINDING_PROTOCOL中的DriverBindingHandle

  • ParentDevicePath:它跟上一个参数是有关联的:
  Status = gBS->OpenProtocol (
                  TcpServiceData->ControllerHandle,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **)&This->ParentDevicePath,
                  TcpServiceData->DriverBindingHandle,
                  This->SockHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

实际上就是代表网卡的设备路径,其值以字符串表示大概是这样的:

PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)

PCI路径可以不用关注,重点在于到MAC为止。

  • DevicePath:它是在ParentDevicePath之上增加了IPv4_DEVICE_PATH的结果:
  Sock->DevicePath = AppendDevicePathNode (Sock->ParentDevicePath, DevicePath);
  Status = gBS->InstallProtocolInterface (
                  &Sock->SockHandle,
                  &gEfiDevicePathProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  Sock->DevicePath
                  );

其值以字符串表示大概是这样的:

PciRoot(0x0)/Pci(0x2,0x0)/MAC(525400123456,0x1)/IPv4(0.0.0.0)
  • Link:该值与TCP_SERVICE_DATA中的SocketList连接。
  • ConfigureState:表示Socket的配置状态,有以下的值:
///
/// Socket configure state
///
#define SO_UNCONFIGURED        0
#define SO_CONFIGURED_ACTIVE   1
#define SO_CONFIGURED_PASSIVE  2
#define SO_NO_MAPPING          3
  • Type:Socket有两种类型,分别是流格式套接字和数据报格式套接字,对应如下代码:
///
///  The socket type.
///
typedef enum {
  SockDgram, ///< This socket providing datagram service
  SockStream ///< This socket providing stream service
} SOCK_TYPE;

流格式套接字也叫“面向连接的套接字”,它有以下的特征:

  1. 数据在传输过程中不会消失;
  2. 数据是按照顺序传输的;
  3. 数据的发送和接收不是同步的(有的教程也称“不存在数据边界”)。

数据报格式套接字也叫“无连接的套接字”,它有以下的特征:

  1. 强调快速传输而非传输顺序;
  2. 传输的数据可能丢失也可能损毁;
  3. 限制每次传输的数据大小;
  4. 数据的发送和接收是同步的(有的教程也称“存在数据边界”)。
  • State:表示Socket本身的状态,有如下的值:
///
/// Socket state
///
#define SO_CLOSED         0
#define SO_LISTENING      1
#define SO_CONNECTING     2
#define SO_CONNECTED      3
#define SO_DISCONNECTING  4
  • Flag:表示TCP头部中的标识,有如下的值:
///
/// Flags in the TCP header
///
#define TCP_FLG_FIN  0x01
#define TCP_FLG_SYN  0x02
#define TCP_FLG_RST  0x04
#define TCP_FLG_PSH  0x08
#define TCP_FLG_ACK  0x10
#define TCP_FLG_URG  0x20

在TCP4协议说明可以找到它们的说明。

  • SndBufferRcvBuffer:收发数据使用的缓存。
  • SockError:Socket的状态。
  • BackLog:表示Socket连接数上限。
  • ConnCnt:表示当前的Socket连接数。
  • Parent:它的类型也是SOCKET,从这里可以看出来Socket之间也有父子关系。从前面的调用流程可以看到,Socket可以通过SockCreate()函数创建,而后者又由两个函数调用:
SockCreateChild
SockCreate
SockClone

它们对应的入参是不同的,SockCreateChild()的入参是mTcpDefaultSockData

SOCK_INIT_DATA  mTcpDefaultSockData = {
  SockStream,
  SO_CLOSED,
  NULL,	// Parent
  TCP_BACKLOG,
  TCP_SND_BUF_SIZE,
  TCP_RCV_BUF_SIZE,
  IP_VERSION_4,
  NULL,
  TcpCreateSocketCallback,
  TcpDestroySocketCallback,
  NULL,
  NULL,
  0,
  TcpDispatcher,
  NULL,
};

SockClone()的实现:

SOCKET *
SockClone (
  IN SOCKET  *Sock
  )
{
  SOCKET          *ClonedSock;
  SOCK_INIT_DATA  InitData;

  InitData.BackLog         = Sock->BackLog;
  InitData.Parent          = Sock;	// 注意这里的Parent
  InitData.State           = Sock->State;
  InitData.ProtoHandler    = Sock->ProtoHandler;
  InitData.Type            = Sock->Type;
  InitData.RcvBufferSize   = Sock->RcvBuffer.HighWater;
  InitData.SndBufferSize   = Sock->SndBuffer.HighWater;
  InitData.DriverBinding   = Sock->DriverBinding;
  InitData.IpVersion       = Sock->IpVersion;
  InitData.Protocol        = &(Sock->NetProtocol);
  InitData.CreateCallback  = Sock->CreateCallback;
  InitData.DestroyCallback = Sock->DestroyCallback;
  InitData.Context         = Sock->Context;
  InitData.ProtoData       = Sock->ProtoReserved;
  InitData.DataSize        = sizeof (Sock->ProtoReserved);

  ClonedSock = SockCreate (&InitData);

从这里带出了新的父子关系。实际的测试中发现,SockCreateChild()会在启动中执行,并且Parent的值都是0,而SockClone()会在使用TCP时创建Socket,此时的Parent是一个有效的值。

  • ConnectionList:当前Socket维护的连接。
  • ListenTokenListRcvTokenListSndTokenListProcessingSndTokenList:处理收发数据的Token列表。
  • ConnectionToken:Socket连接后调用的Token。
  • CloseToken:Socket关闭时调用的Token。
  • ProtoHandlerProtoReserved:Socket请求的回调函数以及对应的入参,回调函数就是TcpDispatcher(),根据入参会执行不同的操作:
EFI_STATUS
TcpDispatcher (
  IN SOCKET  *Sock,
  IN UINT8   Request,
  IN VOID    *Data    OPTIONAL
  )
{
  switch (Request) {
    case SOCK_POLL:
    case SOCK_CONSUMED:
    case SOCK_SND:
    case SOCK_CLOSE:
    case SOCK_ABORT:
    case SOCK_SNDPUSH:
    case SOCK_SNDURG:
    case SOCK_CONNECT:
    case SOCK_ATTACH:
    case SOCK_FLUSH:
    case SOCK_DETACH:
    case SOCK_CONFIGURE:
    case SOCK_MODE:
    case SOCK_ROUTE:
    default:
  }
}
  • IpVersion:这里就是IP_VERSION_4
  • CreateCallbackDestroyCallbackContext:对应mTcpDefaultSockData中的函数,以及它们的入参。

EFI_TCP4_PROTOCOL

该Protocol的结构体如下:

///
/// The EFI_TCP4_PROTOCOL defines the EFI TCPv4 Protocol child to be used by
/// any network drivers or applications to send or receive data stream.
/// It can either listen on a specified port as a service or actively connected
/// to remote peer as a client. Each instance has its own independent settings,
/// such as the routing table.
///
struct _EFI_TCP4_PROTOCOL {
  EFI_TCP4_GET_MODE_DATA    GetModeData;
  EFI_TCP4_CONFIGURE        Configure;
  EFI_TCP4_ROUTES           Routes;
  EFI_TCP4_CONNECT          Connect;
  EFI_TCP4_ACCEPT           Accept;
  EFI_TCP4_TRANSMIT         Transmit;
  EFI_TCP4_RECEIVE          Receive;
  EFI_TCP4_CLOSE            Close;
  EFI_TCP4_CANCEL           Cancel;
  EFI_TCP4_POLL             Poll;
};

对应的实现在NetworkPkg\TcpDxe\TcpDriver.c:

EFI_TCP4_PROTOCOL  gTcp4ProtocolTemplate = {
  Tcp4GetModeData,
  Tcp4Configure,
  Tcp4Routes,
  Tcp4Connect,
  Tcp4Accept,
  Tcp4Transmit,
  Tcp4Receive,
  Tcp4Close,
  Tcp4Cancel,
  Tcp4Poll
};

相比于其它的网络Protocol,这个稍有不同,它包含了Connect、Accept、Close等TCP常用操作。

后面会介绍这些函数的实现。

Tcp4.Connect

对应的实现是Tcp4Connect,其实现是Socket的连接:

EFI_STATUS
EFIAPI
Tcp4Connect (
  IN EFI_TCP4_PROTOCOL          *This,
  IN EFI_TCP4_CONNECTION_TOKEN  *ConnectionToken
  )
{
  return SockConnect (Sock, ConnectionToken);
}

其它的Tcp4Accept、Tcp4Transmit、Tcp4Receive、Tcp4Close等也都是Socket的操作。

TCP代码示例

TCP的代码示例可以在beni/BeniPkg/DynamicCommand/TestDynamicCommand/TestTcp.c · jiangwei/edk2-beni - 码云 - 开源中国 (gitee.com)中找到,它实际上来自EmbeddedPkg\Drivers\AndroidFastbootTransportTcpDxe\FastbootTransportTcpDxe.inf,这是一个开源的模块,不过在编译过程中会报错,所以这里进行了移植,对应BeniPkg\Dxe\TransportTcpDxe\TcpTransportDxe.inf,而TestTcp.c模块就是调用了这个模块。

它将开启一个TCP服务端,可以通过TCP客户端(这里使用了Packet Sender,来自Packet Sender - Free utility to for sending / receiving of network packets. TCP, UDP, SSL.)来与它交互。

其运行结果如下:

在这里插入图片描述

这里接收数据并打印出来,所以能够在右边Shell下看到左边程序传递过来的数据。

注意这里的Address(192.168.3.128)和Port(1234)是硬编码的,需要根据实际情况修改。

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

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

相关文章

爬虫案例—爬取ChinaUnix.net论坛板块标题

爬虫案例—爬取ChinaUnix.net论坛板块标题 ChinaUnix.net论坛网址&#xff1a;http://bbs.chinaunix.net 目标&#xff1a;抓取各个板块的标题和内容的标题 网站截图&#xff1a; 利用requests和xpath实现目标。源码如下&#xff1a; import requests from lxml import etr…

Vue——计算属性

文章目录 计算属性computed 计算属性 vs methods 方法计算属性完整写法 综合案例&#xff1a;成绩案例 计算属性 概念&#xff1a;基于现有的数据&#xff0c;计算出来的新属性。依赖的数据变化&#xff0c;自动重新计算 语法: ①声明computed配置项中&#xff0c;一个计算属性…

vue3-模版引用ref

1. 介绍 概念&#xff1a;通过 ref标识 获取真实的 dom对象或者组件实例对象 2. 基本使用 实现步骤&#xff1a; 调用ref函数生成一个ref对象 通过ref标识绑定ref对象到标签 代码如下&#xff1a; 父组件&#xff1a; <script setup> import { onMounted, ref } …

必看——SSL安全证书

SSL&#xff08;Secure Socket Layer&#xff09;安全证书是一种用于确保在网络上数据传输过程中的安全性和加密性的数字证书。SSL证书通过对数据进行加密&#xff0c;确保敏感信息在用户和服务器之间的传输过程中不被窃取或篡改。下面是获取和配置SSL安全证书的基本步骤&#…

【大数据】YARN常用命令及Rest API

YARN 1.YARN常用命令 1.1 作业 命令说明yarn application -list列出所有的applicationyarn application -list -appStates [ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED]根据application状态过滤yarn application -kill [applicationId]…

【GitHub项目推荐--不错的 C 开源项目】【转载】

大学时接触的第一门语言就是 C语言&#xff0c;虽然距 C语言创立已过了40多年&#xff0c;但其经典性和可移植性任然是当今众多高级语言中不可忽视的&#xff0c;想要学好其他的高级语言&#xff0c;最好是先从掌握 C语言入手。 今天老逛盘点 GitHub 上不错的 C语言 开源项目&…

commit 历史版本记录修正

commit 历史版本记录修正 当 Bug 发生的时候&#xff0c;我们会需要去追踪特定 bug 的历史记录&#xff0c;以查出该 bug 真正发生的原因&#xff0c;这个时候就是版本控制带来最大价值的时候。 因此&#xff0c;要怎样维持一个好的版本记录是非常重要的&#xff0c;下面是一…

第91讲:MySQL主从复制集群主库与从库状态信息的含义

文章目录 1.主从复制集群正常状态信息2.从库状态信息中重要参数的含义 1.主从复制集群正常状态信息 通过以下命令查看主库的状态信息。 mysql> show processlist;在主库中查询当前数据库中的进程&#xff0c;看到Master has sent all binlog to slave; waiting for more u…

通俗易懂理解小波池化/WaveCNet

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 github代码&#xff1a;WaveCNet 通俗易懂理解小波变换(Wavelet Transform) 二、相关介绍 关于小波变换的详细介绍&#xff0c;请参考另一篇博客&…

【工具与中间件】GitGitHub相关知识与一些问题解决、工具推荐

文章目录 前言1. Git 基础快速回顾1.1 Git 相关概念简单回顾1.2 Git 基本命令1.2.1 分支命令1.2.2 推拉命令 2. Git Hub 创建仓库3. 版本控制实战3.1 创建本地项目3.2 绑定远程仓库3.3 代码推拉3.3.1 推拉实战3.3.2 合并请求 4. 补充与总结4.1 可能会遇到的问题4.2 补充&#x…

Unity -简单键鼠事件和虚拟轴

简单键鼠事件 — “Test_03” KeyTest 键鼠事件每帧都要监听&#xff0c;要放在Update()中处理 public class KeyTest : MonoBehaviour {// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){// 【鼠标点击事件…

15.1_使用Verilog设计:一个简单的状态机设计——序列检测器(可实现重复性检测)

使用Verilog设计&#xff1a;一个简单的状态机设计——序列检测器&#xff08;可实现重复性检测&#xff09; 1&#xff0c;一个简单的状态机设计&#xff1a;可重复性序列检测器2&#xff0c;可重复性状态机序列检测实现2.1&#xff0c;RTL设计代码实现2.2&#xff0c;tb测试代…

加码OT安全丨Fortinet与施耐德电气携手共创工业零信任安全创新方案

近日&#xff0c;专注于推动网络与安全融合的全球网络安全领导者 Fortinet在施耐德电气举办的第四季“绿色智能制造创赢计划”结营仪式上&#xff0c;正式与其签署联创方案合作协议&#xff0c;成为施耐德电气“生态合作伙伴”。双方将依托“基于关键装置/设备的微隔离防护”这…

【RT-DETR有效改进】Google | EfficientNetV2一种超轻量又高效的网络 (轻量化网络)

前言 大家好&#xff0c;我是Snu77&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持Re…

Oracle 高级网络压缩 白皮书

英文版白皮书在这里 或 这里。 本文包括了对英文白皮书的翻译&#xff0c;和我觉得较重要的要点总结。 执行概述 Oracle Database 12 引入了一项新功能&#xff1a;高级网络压缩&#xff0c;作为高级压缩选项的一部分。 本文概述了高级网络压缩、其优点、配置细节和性能分析…

基于SpringBoot的儿童疫苗预约系统的设计与实现-计算机毕业设计源码12222

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 儿童疫苗预约管理&#xff0c;主要的模块包括查看首页、站点管理&#xff08;轮播图、公告栏&#xff09;用户管理&#xff08;管理员、系统用…

【开源】基于JAVA语言的课程案例资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员需求分析2.2 用户需求分析 三、系统设计3.1 业务流程设计3.1.1 管理员业务流程设计3.1.2 用户业务流程设计3.1.3 首页功能模块及业务流程分析3.1.4 案例资源中心功能模块及业务流程分析3.1.5 用户信息中心功能模块…

seaborn可视化示例详解

目录 1、散点图 2、散点图回归线 3、折线图 4、频数柱状图 5、分组散点图 6、箱型图 7、数值分布柱状图 8、频数分布图 9、联合分布图 10、数值分布柱状图 11、相关系数热力图 划重点 少走10年弯路 Seaborn是一个基于Python的数据可视化库&#xff0c;Seaborn提供了许多用…

Keepalived + Nginx双主架构

Keepalived Nginx双主架构 环境准备&#xff1a; keepalived_master1服务器nginx&#xff1a;172.20.26.167 keepalived_master2服务器nginx&#xff1a;172.20.26.198 各服务器关闭selinux、防火墙等服务。 开机安装部署nginx 在172.20.26.167服务器上 yum install ngi…

(2023版)斯坦福CS231n学习笔记:DL与CV教程 (15) | 变分自编码器和扩散模型

前言 &#x1f4da; 笔记专栏&#xff1a;斯坦福CS231N&#xff1a;面向视觉识别的卷积神经网络&#xff08;23&#xff09;&#x1f517; 课程链接&#xff1a;https://www.bilibili.com/video/BV1xV411R7i5&#x1f4bb; CS231n: 深度学习计算机视觉&#xff08;2017&#xf…