深入理解Linux网络随笔(七):容器网络虚拟化--Veth设备对
深入理解Linux网络随笔(七):容器网络虚拟化
微服务架构中服务被拆分成多个独立的容器,docker网络虚拟化的核心技术为:Veth设备对、Network Namespace、Bridg。
Veth设备对
veth
设备是一种 成对 出现的虚拟网络接口,作用是 在 Linux 网络命名空间或不同网络栈之间建立一个虚拟的点对点连接,实现数据通信。例如实现容器与宿主机间的通信、不同neths间传递流量。
如图所示:
虚拟网络设备并不会直接连接物理网络设备,而是一端连接到协议栈,另一端连接到另一个 veth 设备。从一对 veth 设备中发出的数据包会直接传送到另一个 veth 设备。每个 veth 设备都可以配置 IP 地址,并作为 路由的一个接口,可以进行IP层通信。
特点:
(1)成对出现:创建时总是 两个设备*成对出现,例如 veth0
和 veth1
,它们之间类似于一条网络隧道
(2)工作方式:一端发送的流量会从另一端收到,就像网线直连一样
(3)不处理 L2/L3 转发:veth
设备 不会执行交换、路由*等功能,只是简单地在两端传输数据包
底层源码分析
veth设备的初始化通过函数veth_init进行。
static __init int veth_init(void)
{//注册veth_link_ops veth设备的操作方法return rtnl_link_register(&veth_link_ops);
}
veth_link_ops
中定义了veth设备的操作回调函数。
static struct rtnl_link_ops veth_link_ops = {.kind = DRV_NAME,//设备类型.priv_size = sizeof(struct veth_priv),//私有数据大小.setup = veth_setup,//设备启动.validate = veth_validate,//检查netlink请求参数的合法性.newlink = veth_newlink,//处理新建的veth设备回调函数.dellink = veth_dellink,//处理删除的veth设备回调函数.policy = veth_policy,//netlink配置参数解析策略.maxtype = VETH_INFO_MAX,// netlink 解析时允许的最大属性编号.get_link_net = veth_get_link_net,// 获取 veth 设备所在的网络命名空间.get_num_tx_queues = veth_get_num_queues,// 获取设备的 TX 队列数.get_num_rx_queues = veth_get_num_queues,// 获取设备的 RX 队列数
};
veth设备创建调用veth_newlink
函数。
static int veth_newlink(struct net *src_net, struct net_device *dev,struct nlattr *tb[], struct nlattr *data[],struct netlink_ext_ack *extack)
{int err;struct net_device *peer;struct veth_priv *priv;char ifname[IFNAMSIZ];struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;unsigned char name_assign_type;struct ifinfomsg *ifmp;struct net *net;.....//创建peer设备peer = rtnl_create_link(net, ifname, name_assign_type,&veth_link_ops, tbp, extack);if (IS_ERR(peer)) {put_net(net);return PTR_ERR(peer);}....//注册peer设备err = register_netdevice(peer);...//获取dev的私有数据privpriv = netdev_priv(dev);//将dev的指针赋值给peer的私有数据peer->priv,建立连接,通过dev访问peer设备rcu_assign_pointer(priv->peer, peer);//初始化dev的TX、RX队列err = veth_init_queues(dev, tb);if (err)goto err_queues;//获取 peer 设备的 priv 结构体priv = netdev_priv(peer);//让 peer->priv->peer 指向 dev,建立 veth 设备对的双向连接rcu_assign_pointer(priv->peer, dev);//初始化peer设备的队列err = veth_init_queues(peer, tb);if (err)goto err_queues;.....
}
启动veth设备,通过veth_netdev_ops
操作表找到发送过程中的回调函数veth_xmit。
static void veth_setup(struct net_device *dev)
{ether_setup(dev);dev->priv_flags &= ~IFF_TX_SKB_SHARING;dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;dev->priv_flags |= IFF_NO_QUEUE;dev->priv_flags |= IFF_PHONY_HEADROOM;//veth操作列表dev->netdev_ops = &veth_netdev_ops;dev->ethtool_ops = &veth_ethtool_ops;dev->features |= NETIF_F_LLTX;dev->features |= VETH_FEATURES;dev->vlan_features = dev->features &~(NETIF_F_HW_VLAN_CTAG_TX |NETIF_F_HW_VLAN_STAG_TX |NETIF_F_HW_VLAN_CTAG_RX |NETIF_F_HW_VLAN_STAG_RX);dev->needs_free_netdev = true;dev->priv_destructor = veth_dev_free;dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;dev->max_mtu = ETH_MAX_MTU;dev->hw_features = VETH_FEATURES;dev->hw_enc_features = VETH_FEATURES;dev->mpls_features = NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE;netif_set_tso_max_size(dev, GSO_MAX_SIZE);
}
static const struct net_device_ops veth_netdev_ops = {.ndo_init = veth_dev_init,.ndo_open = veth_open,.ndo_stop = veth_close,.ndo_start_xmit = veth_xmit,//veth发送函数.ndo_get_stats64 = veth_get_stats64,.ndo_set_rx_mode = veth_set_multicast_list,.ndo_set_mac_address = eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER.ndo_poll_controller = veth_poll_controller,
#endif.ndo_get_iflink = veth_get_iflink,.ndo_fix_features = veth_fix_features,.ndo_set_features = veth_set_features,.ndo_features_check = passthru_features_check,.ndo_set_rx_headroom = veth_set_rx_headroom,.ndo_bpf = veth_xdp,.ndo_xdp_xmit = veth_ndo_xdp_xmit,.ndo_get_peer_dev = veth_peer_dev,
};
通信过程
数据包发送过程中到达网络设备层会进入dev_hard_start_xmit
函数,遍历链表上的所有skb包调用xmit_one
发送数据包。
//网络设备数据包发送路径(TX Path) 的关键部分,负责调用底层驱动的 ndo_start_xmit() 发送数据包
static int xmit_one(struct sk_buff *skb, struct net_device *dev,struct netdev_queue *txq, bool more)
{unsigned int len;int rc;//监测是否有协议栈上层监听if (dev_nit_active(dev))//AF_PACKET 套接字正在监听,发送数据包副本给监听进程dev_queue_xmit_nit(skb, dev);
//记录数据包长度len = skb->len;//触发tracepoint机制,记录数据包发送开始trace_net_dev_start_xmit(skb, dev);//调用底层驱动的ndo_start_xmit()方法发送数据包rc = netdev_start_xmit(skb, dev, txq, more);trace_net_dev_xmit(skb, rc, dev, len);return rc;
}
获取驱动设备回调函数集合ops,结构体net_device_ops
,调用__netdev_start_xmit
发送数据包。
static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev,struct netdev_queue *txq, bool more)
{const struct net_device_ops *ops = dev->netdev_ops;netdev_tx_t rc;//发送数据包rc = __netdev_start_xmit(ops, skb, dev, more);if (rc == NETDEV_TX_OK)txq_trans_update(txq);return rc;
}
在这里会首先判断当前cpu发送队列是否还有数据待处理,然后调用驱动的ndo_start_xmit函数发送数据包,回调函数veth_xmit,lo是loopback_xmit。也就是在veth启动的时候注册的回调函数。
static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,struct sk_buff *skb, struct net_device *dev,bool more)
{__this_cpu_write(softnet_data.xmit.more, more);return ops->ndo_start_xmit(skb, dev);
}
在veth_xmit
核心是获取veth设备数据,将数据发送到对端设备。
static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
{struct veth_priv *rcv_priv, *priv = netdev_priv(dev);struct veth_rq *rq = NULL;int ret = NETDEV_TX_OK;struct net_device *rcv;int length = skb->len;bool use_napi = false;int rxq;rcu_read_lock();//获取veth设备rcv = rcu_dereference(priv->peer);...//获取rcv设备私有数据rcv_priv = netdev_priv(rcv);//获取skb队列索引rxq = skb_get_queue_mapping(skb);if (rxq < rcv->real_num_rx_queues) {rq = &rcv_priv->rq[rxq];//rq绑定了napi,且数据包适合GRO,开启NAPI机制轮询数据包use_napi = rcu_access_pointer(rq->napi) &&veth_skb_is_eligible_for_gro(dev, rcv, skb);}skb_tx_timestamp(skb);//尝试将skb转发到对端veth设备if (likely(veth_forward_skb(rcv, skb, rq, use_napi) == NET_RX_SUCCESS)) {//未使用NAPI机制,更新统计信息if (!use_napi)dev_sw_netstats_tx_add(dev, 1, length);} else {
.....
}
veth_forward_skb
会根据数据包选择不同路径,数据包转发到对端设备dev_forward_skb
,对端开启XDP则调用veth_xdp_rx
,普通数据包调用netif_rx
。
static int veth_forward_skb(struct net_device *dev, struct sk_buff *skb,struct veth_rq *rq, bool xdp)
{return __dev_forward_skb(dev, skb) ?: xdp ?veth_xdp_rx(rq, skb) :__netif_rx(skb);
}
函数调用关系:__dev_forward_skb-->__dev_forward_skb2-->____dev_forward_skb
。
//处理dev设备的转发数据包
static int __dev_forward_skb2(struct net_device *dev, struct sk_buff *skb,bool check_mtu)
{//实际数据包转发处理int ret = ____dev_forward_skb(dev, skb, check_mtu);if (likely(!ret)) {//将skb所属设备设置成刚才取到的veth对端设备rcvskb->protocol = eth_type_trans(skb, dev);//修正skb校验和skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);}return ret;
}
在eth_type_trans
设置完成会继续执行__netif_rx
路径,函数调用逻辑netif_rx_internal-->enqueue_to_backlog
,在这里获取每个CPU核心对应的softnet_data数据结构,将skb添加到等待队列input_pkt_queue
,在函数__test_and_set_bit
检查sd->backlog.state
是否已包含 NAPI_STATE_SCHED
,NAPI_STATE_SCHED
是NAPI轮询处理的一个 状态标志位,防止同一个 NAPI
任务被重复调度,未设置调用napi_schedule_rps
触发NAPI调度,触发软中断 NET_RX_SOFTIRQ
。
static int enqueue_to_backlog(struct sk_buff *skb, int cpu,unsigned int *qtail)
{enum skb_drop_reason reason;struct softnet_data *sd;unsigned long flags;unsigned int qlen;//丢包原因:未指定reason = SKB_DROP_REASON_NOT_SPECIFIED;sd = &per_cpu(softnet_data, cpu);if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state))napi_schedule_rps(sd);
.....
}
在这里根据是否开启RPS机制走不同的路径,RPS 是 Linux 内核的一种 多核负载均衡机制,将收到的数据包分配到多个 CPU 进行处理,避免所有网络流量只由单个 CPU 处理,减少 CPU 瓶颈,在这里通过rps_ipi_list将数据包从一个CPU转发到另外一个CPU上,提高多核环境下的负载均衡,减少CPU之间的竞争。如果没有开启RPS机制,数据包会在当前CPU软中断上下文中处理NAP任务。
static int napi_schedule_rps(struct softnet_data *sd)
{struct softnet_data *mysd = this_cpu_ptr(&softnet_data);
// RPS将接收的数据包调度到 不同的 CPU 进行处理
#ifdef CONFIG_RPS
//sd不等于mysd,说明要在另一个 CPU 上执行 NAPI 任务,而不是本 CPU 处理if (sd != mysd) {//rps_ipi_list 负责存储要在其他 CPU 处理的 softnet_data 队列,并通过 NET_RX_SOFTIRQ 触发软中断来完成调度。sd->rps_ipi_next = mysd->rps_ipi_list;mysd->rps_ipi_list = sd;//出发软中断,处理softnet_data队列的NAPI任务__raise_softirq_irqoff(NET_RX_SOFTIRQ);return 1;}
//本地CPU处理
#endif /* CONFIG_RPS */
//直接调度 mysd->backlog 设备的 NAPI 任务,并安排 net_rx_action() 来执行数据包处理。__napi_schedule_irqoff(&mysd->backlog);return 0;
}
实践操作
Linux 中创建 veth 设备对,设备名veth,指定的虚拟网卡类型为veth,创建的另一端设备名为veth1。
ip link add veth0 type veth peer name veth1
使用ip link show
可以看到veth0
和 veth1
设备已创建,但还未启用。
veth设备需要配置IP地址才能进行通信,为veth0
和 veth1
设备配置ip。
sudo ip addr add 192.168.1.1/24 dev veth0
sudo ip addr add 192.168.1.2/24 dev veth1
启动设备
sudo ip link set veth1 up
sudo ip link set veth0 up
使用ip link show
可以看到veth0
和 veth1
设备状态已变成开启
为了使veth设备之间能够顺利通信,需要关闭反向路径过滤(rp_filter)并设置允许接收本机数据包。root角色下修改系统配置如下:
ping测试veth0
和 veth1
设备间通信
相关文章:
深入理解Linux网络随笔(七):容器网络虚拟化--Veth设备对
深入理解Linux网络随笔(七):容器网络虚拟化 微服务架构中服务被拆分成多个独立的容器,docker网络虚拟化的核心技术为:Veth设备对、Network Namespace、Bridg。 Veth设备对 veth设备是一种 成对 出现的虚拟网络接口&…...
实战指南:鸿蒙ArkTS中实现列表下拉刷新与触底加载的完整解析
前言: 在移动应用开发中,下拉刷新和触底加载更多是提升用户体验的核心功能。鸿蒙ArkUI框架通过Refresh组件和List组件的onReachEnd事件,为开发者提供了简洁高效的实现方案。本文将通过代码示例,详解如何利用ArkTS实现这两个功能。…...
【栈数据结构应用解析:常见算法题详细解答】—— Leetcode
文章目录 栈的模拟实现删除字符串中的所有相邻重复项比较含退格的字符串基本计算器||字符串解码验证栈序列 栈的模拟实现 #include <iostream>using namespace std;const int N 1e5 10;// 创建栈 int stk[N], n;// 进栈 - 本质就是顺序表里面的尾插 void push(int x) …...
Git常用操作之GitLab
Git常用操作之GitLab 小薛博客官网:小薛博客Git常用操作之GitLab官方地址 1、GitLab安装 https://gitlab.cn/install/ 1、Docker安装GitLab https://docs.gitlab.cn/jh/install/docker.html 1、设置卷位置 在设置其他所有内容之前,请配置一个新的…...
2025探索短剧行业新可能报告40+份汇总解读|附PDF下载
原文链接:https://tecdat.cn/?p41043 近年来,短剧以其紧凑的剧情、碎片化的观看体验,迅速吸引了大量用户。百度作为互联网巨头,在短剧领域积极布局。从早期建立行业专属模型冷启动,到如今构建完整的商业生态…...
各省水资源平台 水资源遥测终端机都用什么协议
各个省水资源平台 水资源遥测终端机 的建设大部分从2012年开始启动,经过多年建设,基本都已经形成了稳定的通讯要求;河北瑾航科技 遥测终端机,兼容了大部分省市的通讯协议,如果需要,可以咨询和互相学习&…...
C#+EF+SqlServer性能优化笔记
文章目录 前言一、C#EF 代码优化1.接口代码改异步2.查询异步,只查询需要的数据3.查询数据判断时4.直接使用sql查询 二、数据库优化1.减少关联表,一些基础数据,字典表可以考虑放到redis中,在代码中映射2.增加索引,删除无…...
列表动态列处理
1、在initialize()方法里,获取列表控件,添加CreateListColumnsListener监听 public void initialize(){ BillList billlist(BillList)this.getControl("billlistap"); billlist.addCreateListColumnsListener(this::beforeCreateListColumns)…...
电机控制常见面试问题(十二)
文章目录 一.电机锁相环1.理解锁相环2.电机控制中的锁相环应用3.数字锁相环(DPLL) vs 模拟锁相环(APLL)4.锁相环设计的关键技术挑战5.总结 二、磁链观测1.什么是磁链?2.为什么要观测磁链?3.怎么观测磁链&am…...
芯驿电子 ALINX 亮相德国纽伦堡,Embedded World 2025 精彩回顾
2025年3月13日,全球规模最大的嵌入式行业盛会——德国纽伦堡国际嵌入式展(embedded world 2025)圆满落幕。 在这场汇聚全球 950 家展商、3 万余专业观众的科技盛宴中,芯驿电子 ALINX 展位人头攒动,多款尖端产品吸引客户…...
西门子S7-1200 PLC远程上下载程序方案
西门子S7-1200 PLC远程上下载程序方案(巨控GRM552YW-C模块) 三步完成配置 | 全球适用 | 稳定高效 三步快速完成远程配置 硬件部署 准备巨控GRM552YW-CHE模块1台,通过网口连接西门子S7-1200 PLC以太网口。 模块支持4G/5G/Wi-Fi/网线接入外网…...
MFC窗口的创建/消息映射机制
mfc.h #include<afxwin.h>//mfc头文件//应用程序类 class MyApp:public CWinApp //继承于应用程序类 { public://程序入口virtual BOOL InitInstance(); };//框架类 class MyFrame:public CFrameWnd { public:MyFrame();//声明宏 提供消息映射机制DECLARE_MESSAGE_MAP()…...
【每日学点HarmonyOS Next知识】tab对齐、相对布局、自定义弹窗全屏、动画集合、回到桌面
1、HarmonyOS Tabs 是否能支持 tabbar 居左对齐? 当前方案为自定义tabbar实现,示例demo: Entry Component struct TabsExample {State tabArray: Array<number> [0, 1,2]State focusIndex: number 0State pre: number 0State inde…...
如何在TikTok网页版切换地区设置
今天我们来聊聊如何在TikTok网页版上更改地区设置。TikTok作为全球知名的短视频社交应用,不仅仅局限于某个国家或地区。修改地区设置可以让你探索来自不同地方的内容,享受更为丰富的社交互动体验。那么,具体该如何操作呢?让我一步…...
redis工具类
前言 Redis 是一个高性能的键值存储系统,广泛应用于缓存、消息队列、实时分析等场景。为了更高效地操作 Redis,许多开发者会选择使用 Redisson 客户端库。 依赖配置 首先确保您的项目中已经包含了 Redisson 的最新版本(如 3.44.0ÿ…...
【Python办公】Excel通用匹配工具(双表互匹)
目录 专栏导读1、背景介绍2、库的安装3、核心代码4、完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文章专栏:请点击——>Python办公自动化专…...
安徽省青少年信息学奥林匹克竞赛初中组第1题LuoguP762
先放题目: 【题目背景】.你 .可 .以 .选 .择 .跳 .过 .背 .景 .部 .分。初春的一天,正是乍暖还寒时候,狂风乍起。小可可裹紧了单薄的外衣,往小雪家中赶去。“今天真不是个出门的时候啊!”小可可感叹道。“但是我还有东西要买………...
AVL树的平衡算法的简化问题
AVL树是一种紧凑的二叉查找树。它的每个结点,都有左右子树高度相等,或者只相差1这样的特性。文章https://blog.csdn.net/aaasssdddd96/article/details/106291144给出了一个例子。 为了便于讨论,这里对AVL树的结点平衡情况定义2个名称&#…...
NFS实验配置笔记
NFS NFS服务 nfs,最早是Sun这家公司所发展出来的,它最大的功能就是可以透过网络,让不同的机器,不同的操作系统,进行实现文档的共享。所以你可以简单的将他看做是文件服务器。 实验准备 ①先准备一个服务器端的操作…...
C盘清理技巧分享:释放空间,提升电脑性能
目录 1. 引言 2. C盘空间不足的影响 3. C盘清理的必要性 4. C盘清理的具体技巧 4.1 删除临时文件 4.2 清理系统还原点 4.3 卸载不必要的程序 4.4 清理下载文件夹 4.5 移动大文件到其他盘 4.6 清理系统缓存 4.7 使用磁盘清理工具 4.8 清理Windows更新文件 4.9 禁用…...
【云馨AI-大模型】RAGFlow功能预览:Dify接入外部知识库RAGFlow指南
介绍 Dify介绍 开源的 LLM 应用开发平台。提供从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等能力,轻松构建和运营生成式 AI 原生应用。比 LangChain 更易用。官网:https://dify.ai/zh RAGFlow介绍 RAGFlow 是一款基于深度文档理解构建的…...
大模型学习笔记------Llama 3模型架构之旋转编码(RoPE)
大模型学习笔记------Llama 3模型架构之旋转编码(RoPE) 1、位置编码简介1.1 绝对位置编码1.2 相对位置编码 2、旋转编码(RoPE)2.1 基本概念---旋转矩阵2.2 RoPE计算原理2.2.1 绝对位置编码2.2.2 相对位置编码 3、旋转编码…...
Anthropic 的模型
Anthropic 的模型(特别是 Claude 系列)之所以在性能和推理能力上表现强劲,可以从技术设计、研究理念、训练方法以及应用优化等多个方面进行详细分析。以下是基于当前信息(截至 2025 年 3 月 13 日)和行业趋势的深入剖析…...
初探大模型开发:使用 LangChain 和 DeepSeek 构建简单 Demo
最近,我开始接触大模型开发,并尝试使用 LangChain 和 DeepSeek 构建了一个简单的 Demo。通过这个 Demo,我不仅加深了对大模型的理解,还体验到了 LangChain 和 DeepSeek 的强大功能。下面,我将分享我的开发过程以及一些…...
FPGA初级项目10——基于SPI的DAC芯片进行数模转换
FPGA初级项目10——基于SPI的DAC芯片进行数模转换 DAC芯片介绍 DAC 芯片(数字模拟转换器)是一种将数字信号转换为连续模拟信号(如电压或电流)的集成电路,广泛应用于电子系统中,连接数字世界与模拟世界。 …...
【论文解读】Contrastive Learning for Compact Single Image Dehazing(AECR-Net)
文章目录 问题创新网络主要贡献Autoencoder-like Dehazing NetworkAdaptive Mixup for Feature PreservingDynamic Feature Enhancement1. 可变形卷积的使用2. 扩展感受野3. 减少网格伪影4. 融合空间结构信息 Contrastive Regularization1. 核心思想2. 正样本对和负样本对的构建…...
unity基础——线段与拖尾
1、LineRenderer(线段渲染器) 为空物体加上组件添加材质 选择默认线段的材质 Default—Line Color:可以修改颜色Corner Vertices:角顶点 圆滑度 End Cap Vertices:边缘顶点 线段编辑 1、可以移动线段点的位置…...
【服务器知识】Nginx路由匹配规则说明
Nginx路由匹配规则说明 **一、Nginx路由匹配核心机制****二、匹配规则语法详解**1. **精确匹配 ()**2. **前缀匹配 (^~ 或 /)**3. **正则匹配 (~ 或 ~*)**4. **通配符匹配 (*)** **三、路由匹配优先级顺序****四、高级路由技巧**1. **条件判断 (if语句)**2. **路径重写 (rewrit…...
Python----数据可视化(Pyecharts三:绘图二:涟漪散点图,K线图,漏斗图,雷达图,词云图,地图,柱状图折线图组合,时间线轮廓图)
1、涟漪特效散点图 from pyecharts.globals import SymbolType from pyecharts.charts import EffectScatter from pyecharts.faker import Faker from pyecharts import options as opts from pyecharts.globals import ThemeType # 绘制图表 es (EffectScatter(init_optsop…...
机器学习中的梯度下降是什么意思?
梯度下降(Gradient Descent)是机器学习中一种常用的优化算法,用于最小化损失函数(Loss Function)。通过迭代调整模型参数,梯度下降帮助模型逐步逼近最优解,从而提升模型的性能。 1.核心思想 梯…...
C语言中的字符串与数组的关系
在C语言中,字符串和数组之间有着紧密的关系。理解它们的区别和联系对于编写高效且可靠的代码至关重要。在本篇博文中,我们将详细分析字符串和数组在C语言中的概念、它们的关系以及如何在编程中应用它们。 一、字符串与数组的基础知识 1.1 数组概念 在C语言中,数组是一组相…...
Ubuntu 18,04 LTS 通过APT安装mips64el的交叉编译器。
安装 g-5v的版本: sudo apt update sudo apt install g-5-mips64el-linux-gnuabi64 How to Install g-5-mips64el-linux-gnuabi64 in Ubuntu 18.04 安装 gcc/g-7v的版本: sudo apt-get install gcc-mips64el-linux-gnu* g-mips64el-linux-gnu* -y 安装…...
MySQL 衍生表(Derived Tables)
在SQL的查询语句select …. from …中,跟在from子句后面的通常是一张拥有定义的实体表,而有的时候我们会用子查询来扮演实体表的角色,这个在from子句中的子查询会返回一个结果集,这个结果集可以像普通的实体表一样查询、连接&…...
C++ vector 核心知识:常用操作与示例详解
在C编程中,vector 是标准模板库(STL)中最常用的容器之一。它以其动态数组的特性、高效的尾部操作和便捷的随机访问能力,成为处理动态数据的首选工具。无论是初学者还是经验丰富的开发者,掌握 vector 的使用方法和性能优…...
不同开发语言对字符串的操作
一、字符串的访问 Objective-C: 使用 characterAtIndex: 方法访问字符。 NSString *str "Hello, World!"; unichar character [str characterAtIndex:0]; // 访问第一个字符 H NSLog("%C", character); // 输出: H NSString 内部存储的是 UTF-16 编…...
Qt从入门到入土(十) -数据库操作--SQLITE
认识 数据库是用于存储、管理和检索数据的系统化集合。它是一种按照特定结构组织数据的存储方式,通过软件(数据库管理系统,DBMS)来实现数据的高效存储、查询、更新和管理。通过文件存储数据适用于少量的数据,而当拥有…...
硬件驱动——51单片机:独立按键、中断、定时器/计数器
目录 一、独立按键 1.原理 2.封装函数 3.按键控制点灯 数码管 二、中断 1.原理 2.步骤 3.中断寄存器IE 4.控制寄存器TCON 5.打开外部中断0和1 三、定时器/计数器 1.原理 2.控制寄存器TCON 3.工作模式寄存器TMOD 4.按键控制频率的动态闪烁 一、独立按键 1…...
pgsql创建新用户并赋只读权限
在 PostgreSQL 中,为新用户赋予只读权限的步骤如下: —### 1. 创建新用户首先,创建一个新用户(角色),并设置密码:sqlCREATE ROLE 用户名 WITH LOGIN PASSWORD 密码;例如:sqlCREATE R…...
【量化策略】动量突破策略
【量化策略】动量突破策略 🚀量化软件开通 🚀量化实战教程 技术背景与应用场景 动量突破策略是一种基于市场趋势的量化交易策略,它通过识别和利用资产价格的持续上升或下降趋势来获取利润。这种策略特别适用于那些价格波动较大、趋势明显…...
QT编程之QGIS
一、QGIS介绍 Quantum GIS(QGIS)是开源地理信息系统桌面软件,使用GNU(General Public License)授权, 属于 Open Source eospatial Foundation( OSGeo )的官方计划。在 GNU 授权下&am…...
LangChain-chatchat 0.3.x入门级教程
前言 一种利用 langchain 思想实现的基于本地知识库的问答应用,目标期望建立一套对中文场景与开源模型支持友好、可离线运行的知识库问答解决方案。该项目支持市面上主流的开源 LLM、 Embedding 模型与向量数据库,可实现全部使用开源模型离线私有部署。…...
Vi/Vim命令详解:高效文本编辑的利器
Vi/Vim命令详解:高效文本编辑的利器 Vi和Vim是Unix/Linux系统中极为流行的文本编辑器,它们以其强大的功能和高效的操作方式赢得了广大用户的喜爱。无论是对于程序员、系统管理员还是普通用户,掌握Vi/Vim的基本命令和高级技巧都是非常有必要的…...
【前端三剑客】万字总结JavaScript
一、初识JavaScript 1.1 JavaScript 的作用 表单动态校验(密码强度检测) ( JS 产生最初的目的 )网页特效服务端开发(Node.js)桌面程序(Electron)App(Cordova)控制硬件-物联网(Ruff)游戏开发(cocos2d-js) 1.2 HTML/CSS/JS 的关系…...
MySQL | MySQL表的增删改查(CRUD)
目录 前言:什么是 CRUD ?一、Creat 新增1.1 语法1.2 示例1.2.1 单行数据全列插入1.2.2 单行数据指定列插入1.2.3 多行数据指定列插入 二、Retrieve 检索2.1 语法2.2 示例2.2.1 全列查询2.2.2 指定列查询2.2.3 查询字段为表达式2.2.4 结果去重查询2.2.5 where条件查…...
【愚公系列】《高效使用DeepSeek》003-DeepSeek文档处理和其他顶级 AI模型的区别
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...
OSC32IN与OSC32OUT对于无源晶振而言有区别吗?
OSC32IN与OSC32OUT对于无源晶振而言有区别吗? 答:没有区别。对晶振本身而言,两个频率管脚反接也是一样的。 如下图所示: 使用示波器连接晶振的两个引脚,并观察波形可以帮助确定输入和输出端口。 当晶振工作正常时&…...
究竟什么是虚拟同步机???虚拟同步机巨简单理解
1同步发电机 1.1同步发电机工作原理 同步发电机定子铁芯的内圆均匀分布着定子槽,槽内按一定规律嵌放着对称的三相绕组U1-U2、V1-V2、W1-W2,如图1所示。 图1 同步发电机的结构原理图 工作原理: 转子铁芯上装有制成一定形状的成对磁极,磁极上绕有励磁绕组。励磁绕组上通直流…...
ZVA-Z90,罗德与施瓦茨毫米波变换器
罗德与施瓦茨 ZVA-Z90毫米波变换器 商品品牌:R&S/罗德与施瓦茨 商品型号:ZVA-Z90 商品名称:毫米波变换器 产品简介: ZVA-Z 毫米波变换器 简介 R&SZVA-Zxx 毫米波变换器支持在 V、E、W、F、D、G、J 以及 Y 频段内的毫米波测量…...
TCP/IP 协议精讲-精华总结版本
序言 本文旨在介绍一下TCP/IP涉及得所有基础知识,为大家从宏观上俯瞰TCP/IP提供一个基石,文档属于《TCP/IP图解(第五版)》的精简版本。 专业术语 缩写 全称 WAN Wide area network广域网 LAN Local area network局域网 TC…...
电脑内存不足怎么办?
常规解决方法盘点 关闭后台程序:按下【Ctrl Shift Esc】组合键打开任务管理器,在 “进程” 选项卡里,把当前不用的程序统统 “结束任务” ,像那些自动更新的软件、常驻后台的播放器,关了能释放不少内存。比如音乐软…...