MySQL数据库入门

目录

前言

一、安装软件

二、普通指令使用

三、MySQL接口API相关函数

1、API函数使用步骤

2、mysql_init-MYSQL对象初始化

3、mysql_real_connect()——数据库引擎建立连接

4、mysql_close()——关闭数据库连接

 5、mysql_query()——查询数据库某表内容

6、mysql_store_result()——向客户端检索完整的结果集

7、mysql_num_fields()——获取字段数量(列数)

8、mysql_free_result()——释放结果集使用的内存

9、mysql_fetch_row()——从结果集中获取下一行

四、使用C语言连接MySQL

五、使用示例

5.1、连接初始化

5.2、构造指令


前言

本博文是学习基于Linux+STM32+esp8266的超级智能无人超市项目里面所需要的一小些数据库使用,本博文便于学习这个项目的数据库部分,可以根据后面的最后一个使用实例来练习数据库的连接,表的删除和更正、查询!

一、安装软件

在电脑不同系统上安装使用MYSQL可以看这个视频:一小时MYSQL

二、普通指令使用

1、终端进入MYSQL:

mysql -u root -p

然后输入密码即可进入

 2、创建数据库

我们可以先查询一下已经有的数据库:

show databases;

创建数据库:

CREATE DATABASE test;

test:数据库名字 

指定使用哪个数据库:

use test;

创建表:

CREATE TABLE users(id VARCHAR(20) unique key,name VARCHAR(50),phone VARCHAR(15) unique key,balance VARCHAR(25),text VARCHAR(1000));

users:表名

 查询表:

desc users;     users:表名

退出MySQL:

exit; 

插入操作:

"INSERT INTO me(pid, pname,price,brand) VALUES('123','lll','100','ddd')";

me:表名

查询操作:

"SELECT * FROM me"; 

me:表名

 删除操作:

DELETE FROM me where name=0;

me:表名

删除me表中name为0的成员

删除全部成员:TRUNCATE TABLE usr;

usr:表名

更改操作:

UPDATE me set name = 0 where price = 100;

me:表名

将price为100的成员的name更改为0

三、MySQL接口API相关函数

1、API函数使用步骤

1,首先需要 mysql的头文件,并链接MQSQL动态库。

#include <mysql.h>

2、创建MYSQL变量

MYSQL mysql;

3、mysql_init初始化MYSQL变量

4、调用mysql_real_connect函数连接Mysql数据库

5、调用mysql_real_query函数进行数据库查询

6、通过调用mysql_store_result或mysql_use_result函数返回的MYSQL_RES变量获取查询结果数据。

7、调用mysql_fetch_row函数读取结果集数据。

8、结果集用完后,调用mysql_free_result函数释放结果集,以防内存泄露
9、不再查询Mysql数据库时,调用mysql_close函数关闭数据库连接

2、mysql_init-MYSQL对象初始化

MYSQL *mysql_init(MYSQL *mysql) 

返回值:

  • 初始化的MYSQL*句柄。如果无足够内存以分配新的对象,返回NULL。 错误,在内存不足的情况下,返回NULL。

说明:

  • 如果mysql是NULL指针,该函数将分配、初始化、并返回新对象。

  • 否则,将初始化对象,并返回对象的地址。

  • 如果mysql_init()分配了新的对象,应当在程序中调用mysql_close() 来关闭连接,以释放对象

3、mysql_real_connect()——数据库引擎建立连接

MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) 

返回值

  • 如果连接成功,返回MYSQL*连接句柄。
  • 如果连接失败,返回NULL。对于成功的连接,返回值与第1个参数的值相同。

参数说明:

  • mysql:前面定义的MYSQL变量;
  • host:MYSQL服务器的地址;
    • 如果“host”是NULL或字符串"localhost",连接将被视为与本地主机的连接。
    • 如果操作系统支持套接字(Unix)或命名管道(Windows),将使用它们而不是TCP/IP连接到服务器。
  • user:登录用户名;
    • 如果“user”是NULL或空字符串"",用户将被视为当前用户。在UNIX环境下,它是当前的登录名。
  • passwd:登录密码;
  • db:要连接的数据库,如果db为NULL,连接会将默认的数据库设为该值。
  • port:MYSQL服务器的TCP服务端口;
    • 如果“port”不是0,其值将用作TCP/IP连接的端口号。注意,“host”参数决定了连接的类型。
  • unix_socket:unix连接方式。
    • 如果unix_socket不是NULL,该字符串描述了应使用的套接字或命名管道。注意,“host”参数决定了连接的类型。
  • clientflag:Mysql运行为ODBC数据库的标记,一般取0。

4、mysql_close()——关闭数据库连接

void mysql_close(MYSQL *mysql) 

 5、mysql_query()——查询数据库某表内容

查询数据库中的某一个表内容,通过函数mysql_query()来实现

int mysql_query(MYSQL *mysql, const char *query) 
//query为执行的SQL语句对应的字符长串

返回值

  • 如果查询成功,返回0。如果出现错误,返回非0值。

使用说明:

  • 执行由“Null终结的字符串”查询指向的SQL查询。
  • 正常情况下,字符串必须包含1条SQL语句,而且不应为语句添加终结分号(‘;’)或“\g”。如果允许多语句执行,字符串可包含多条由分号隔开的语句。(“多查询执行的C API处理”)
  • mysql_query()不能用于包含二进制数据的查询,应使用mysql_real_query()取而代之(二进制数据可能包含字符‘\0’mysql_query()会将该字符解释为查询字符串结束)。
  • 如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。
  • 查询成功则该函数返回0。

使用实例:

// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr) {printf("sql: %s\n", sqlstr);// 开始事务if (mysql_query(config->mysql, "BEGIN")) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}// 执行 SQL 语句if (mysql_query(config->mysql, sqlstr)) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}// 提交事务if (mysql_query(config->mysql, "COMMIT")) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}return true;
}

6、mysql_store_result()——向客户端检索完整的结果集

显示查询数据库中数据表的内容,mysql_store_result()mysql_query()查询的全部结果读取到客户端,分配1个MYSQL_RES结构(上面有介绍),并将结果置于该结构中

MYSQL_RES *mysql_store_result(MYSQL *mysql) 

返回值

具有多个结果的MYSQL_RES结果集合。如果出现错误,返回NULL。

使用说明:

  • 对于成功检索了数据的每个查询(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必须调用mysql_store_result()mysql_use_result() 。
  • 如果希望了解查询是否应返回结果集,可使用mysql_field_count()进行检查。
  • 如果查询未返回结果集,mysql_store_result()将返回Null指针(例如,如果查询是INSERT语句)。
  • 如果读取结果集失败,mysql_store_result()还会返回Null指针。通过检查mysql_error()是否返回非空字符串mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以检查是否出现了错误。
  • 如果未返回行,将返回空的结果集。(空结果集设置不同于作为返回值的空指针)。
  • 一旦调用了mysql_store_result()并获得了不是Null指针的结果,可调用mysql_num_rows()来找出结果集中的行数
  • 可以调用mysql_fetch_row()来获取结果集中的行,或调用mysql_row_seek()mysql_row_tell()来获取或设置结果集中的当前行位置
  • 一旦完成了对结果集的操作,必须调用mysql_free_result()。

7、mysql_num_fields()——获取字段数量(列数)

int mysql_num_fields(MYSQL_RES *result) 

8、mysql_free_result()——释放结果集使用的内存

释放由mysql_store_result()mysql_use_result()mysql_list_dbs()等为结果集分配的内存。完成对结果集的操作后,必须调用mysql_free_result()释放结果集使用的内存。

void mysql_free_result(MYSQL_RES *result) 

9、mysql_fetch_row()——从结果集中获取下一行

MYSQL_ROW mysql_fetch_row(MYSQL_RES* result)
//MYSQL_ROW开篇已经说明,char ** 类型

返回值

  • 下一行的MYSQL_ROW结构。如果没有更多要检索的行或出现了错误,返回NULL。

使用说明:

  • mysql_store_result()之后使用时,如果没有要检索的行,mysql_fetch_row()返回NULL。
  • mysql_use_result()之后使用时,如果没有要检索的行或出现了错误,mysql_fetch_row()返回NULL。
  • 行内值的数目由mysql_num_fields(result)给出。如果行中保存了调用mysql_fetch_row()返回的值,将按照row[0]row[mysql_num_fields(result)-1],访问这些值的指针。
  • 可以通过调用mysql_fetch_lengths()来获得行中字段值的长度。对于空字段以及包含NULL的字段,长度为0。通过检查字段值的指针,能够区分它们。如果指针为NULL,字段为NULL,否则字段为空。

四、使用C语言连接MySQL

下面我们使用C语言来写函数来连接和使用MySQL

sql_connect.c:

#include "sql_connect.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 初始化数据库连接对象
SQLifconfig* SQLifconfig_init() {SQLifconfig *config = (SQLifconfig*)malloc(sizeof(SQLifconfig));if (!config) return NULL;// 初始化成员变量config->mysql = NULL;config->row = NULL;config->result = NULL;config->field = NULL;// 初始化 MySQL 连接config->mysql = mysql_init(NULL);//参数为NULL,函数将分配初始化,并初始化、返回新对象if (!config->mysql) {printf("Init Error: %s\n", mysql_error(config->mysql));free(config);return NULL;}// 强制设置字符集if (mysql_options(config->mysql, MYSQL_SET_CHARSET_NAME, "utf8mb4")) {printf("Set UTF-8 Error: %s\n", mysql_error(config->mysql));mysql_close(config->mysql);free(config);return NULL;}return config;
}// 释放数据库连接对象
void SQLifconfig_destroy(SQLifconfig *config) {if (config) {if (config->mysql) {mysql_close(config->mysql);//关闭数据库连接}free(config);//释放空间}
}// 初始化数据库连接
bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname) {if (!mysql_real_connect(config->mysql, host, user, pwd, dbname, 3306, NULL, 0)) {printf("connect error: %s\n", mysql_error(config->mysql));return false;}return true;
}// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr) {printf("sql: %s\n", sqlstr);// 开始事务if (mysql_query(config->mysql, "BEGIN")) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}// 执行 SQL 语句if (mysql_query(config->mysql, sqlstr)) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}// 提交事务if (mysql_query(config->mysql, "COMMIT")) {printf("query_error: %s\n", mysql_error(config->mysql));return false;}return true;
}// 执行查询 SQL 语句(SELECT)
char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr) {// 执行 SQL 查询if (mysql_query(config->mysql, sqlstr)) {printf("query_error: %s\n", mysql_error(config->mysql));return NULL;}// 获取查询结果集config->result = mysql_store_result(config->mysql);if (!config->result) {return NULL; // 无结果或错误}// 获取字段数量(列数)int fieldnum = mysql_num_fields(config->result);// 初始化动态缓冲区size_t total_len = 1024; // 初始缓冲区大小char *buffer = (char*)malloc(total_len);if (!buffer) {mysql_free_result(config->result);return NULL; // 内存分配失败}buffer[0] = '\0'; // 初始化空字符串// 遍历结果集的每一行while ((config->row = mysql_fetch_row(config->result))) {// 计算当前行所需的总长度size_t row_len = 0;for (int j = 0; j < fieldnum; j++) {row_len += strlen(config->row[j] ? config->row[j] : "NULL") + 1; // 字段值 + 分隔符}// 动态扩展缓冲区(如果当前缓冲区不足以容纳新行)size_t current_len = strlen(buffer);if (current_len + row_len + 2 > total_len) {total_len += row_len + 2; // 扩展缓冲区大小char *new_buf = realloc(buffer, total_len);if (!new_buf) {free(buffer);mysql_free_result(config->result);return NULL; // 内存分配失败}buffer = new_buf;}// 拼接当前行的字段值for (int j = 0; j < fieldnum; j++) {const char *val = config->row[j] ? config->row[j] : "NULL"; // 处理 NULL 值strcat(buffer, val); // 追加字段值strcat(buffer, "#"); // 追加分隔符}buffer[strlen(buffer)-1] = '\n'; // 将最后一个#替换为换行符}// 释放结果集内存mysql_free_result(config->result);// 检查是否有有效数据if (strlen(buffer) == 0) {free(buffer);return NULL; // 无数据}// 返回格式化后的字符串return buffer;
}

sql_connect.h:

#ifndef __SQL_CONNECT_H
#define __SQL_CONNECT_H#include <mysql.h>
#include <stdbool.h>// 数据库连接结构体
typedef struct {MYSQL *mysql;       // MySQL 连接对象MYSQL_ROW row;      // 当前行数据MYSQL_RES *result;  // 查询结果集MYSQL_FIELD *field; // 字段信息
} SQLifconfig;// 初始化数据库连接
SQLifconfig* SQLifconfig_init();// 释放数据库连接
void SQLifconfig_destroy(SQLifconfig *config);// 初始化数据库连接
bool SQLifconfig_SQL_init(SQLifconfig *config, const char *host, const char *user, const char *pwd, const char *dbname);// 执行查询 SQL 语句(SELECT)
char* SQLifconfig_Dql_sql(SQLifconfig *config, const char *sqlstr);// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)
bool SQLifconfig_Dml_sql(SQLifconfig *config, const char *sqlstr);#endif

五、使用示例

5.1、连接初始化

建立两个表,并且数据库名为shopping,后面的实验都会围绕这两个表进行实验:

CREATE DATABASE shopping;CREATE TABLE users(
id VARCHAR(20) unique key,
name VARCHAR(50),
phone VARCHAR(15) unique key,
balance VARCHAR(25),
text VARCHAR(1000)
)CREATE TABLE me(
pid VARCHAR(20) unique key,
pname VARCHAR(50),
price VARCHAR(15),
brand VARCHAR(25)
)
SQLifconfig *MySQL_Handler;int main() 
{// 初始化数据库连接对象MySQL_Handler = SQLifconfig_init();if (!MySQL_Handler) {printf("初始化数据库失败\n");return -1;}// 连接数据库                                                               //数据库名字if (!SQLifconfig_SQL_init(MySQL_Handler, "127.0.0.1", "root", "123456", "shopping")) {printf("连接数据库失败\n");SQLifconfig_destroy(MySQL_Handler);return -1;}}

5.2、构造指令

下面就是一些项目中所使用到的指令,可能有一些没有写,不过应该是都写了,类似相同的就不写了!

/* 删除me表中的pid为str的成员 */
// 构造 SQL 删除语句
sprintf(buf, "DELETE FROM me WHERE pid='%s'", str);
// 执行 SQL 删除操作
int result = SQLifconfig_Dml_sql(MySQL_Handler, buf);/* 查询users表中phone为str的成员的id, name, phone, balance */
sprintf(buf, "SELECT id, name, phone, balance FROM users WHERE phone='%s'", str);
// 执行查询
char* ret = SQLifconfig_Dql_sql(MySQL_Handler, buf);/* 更新users表中的ide为pid的成员的balance ,修改为balance+num */
sprintf(buf, "UPDATE users SET balance = balance + %d WHERE id='%s'", num, pid);
if (SQLifconfig_Dml_sql(MySQL_Handler, buf)) /* 删除users表中的所有成员 */
SQLifconfig_Dml_sql(MySQL_Handler, "TRUNCATE TABLE users"))/* 可以用来练习 *///执行插入操作                         //表名const char *insert_sql = "INSERT INTO users(id, name,phone,balance) VALUES('888','hxy','666',100)";if (SQLifconfig_Dml_sql(MySQL_Handler, insert_sql)) {// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)printf("插入成功\n");} else {printf("插入失败\n");}insert_sql = "INSERT INTO me(pid, pname,price,brand) VALUES('888','hxy','666',100)";if (SQLifconfig_Dml_sql(MySQL_Handler, insert_sql)) {// 执行操作 SQL 语句(INSERT/UPDATE/DELETE)printf("插入成功\n");} else {printf("插入失败\n");}// 执行查询操作                        //表名     const char *select_sql = "SELECT * FROM users";char *result = SQLifconfig_Dql_sql(MySQL_Handler, select_sql);// 执行查询 SQL 语句(SELECT)if (result) {printf("查询结果:\n%s", result);free(result); // 必须手动释放内存} else {printf("查询失败或无结果\n");}select_sql = "SELECT * FROM me";result = SQLifconfig_Dql_sql(MySQL_Handler, select_sql);// 执行查询 SQL 语句(SELECT)if (result) {printf("查询结果:\n%s", result);free(result); // 必须手动释放内存} else {printf("查询失败或无结果\n");}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S学习之基础五十七:部署代码扫描工具sonarqube

部署代码扫描工具sonarqube 拉取postgres、sonarqube镜像&#xff0c;在harbor上创建postgres、sonarqube项目&#xff0c;将镜像上传至harbordocker pull postgres docker pull sonarqube docker tat postgres:latest 172.16.80.140/postgres/postgres:latest docker tat sona…

个人学习编程(3-24) 数据结构

括号的匹配&#xff1a; if((s[i]) && now() || (s[i]] && now[)){ #include <bits/stdc.h>using namespace std;int main() {char s[300];scanf("%s",&s);int i;int len strlen(s);stack <char> st;for (i 0; i < len; i){if(…

Redis6为什么引入了多线程?

大家好&#xff0c;我是锋哥。今天分享关于【Redis6为什么引入了多线程&#xff1f;】面试题。希望对大家有帮助&#xff1b; Redis6为什么引入了多线程&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Redis 6 引入了多线程的主要目的是为了提升 Redis…

电力物联网数据采集装置 高精度电能计量表

摘要 随着现代电力系统的复杂化和负荷多样化&#xff0c;电能质量问题日益突出。高精度电能质量监测装置在配电系统中的应用&#xff0c;可以有效监测和分析谐波、不平衡、电压暂升暂降等电能质量问题&#xff0c;为电网优化运行和故障诊断提供重要数据支持。本文以APM电能质量…

element-plus中,Tour 漫游式引导组件的使用

目录 一.Tour 漫游式引导组件的简单介绍 1.作用 2.基本使用 3.展示效果 二.实战1&#xff1a;介绍患者病历表单 1.要求 2.实现步骤 3.展示效果 结语 一.Tour 漫游式引导组件的简单介绍 1.作用 快速了解一个功能/产品。 2.基本使用 从官网复制如下代码&#xff1a; &…

【Unity网络编程知识】使用Socket实现简单TCP通讯

1、Socket的常用属性和方法 创建Socket TCP流套接字 Socket socketTcp new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 1.1 常用属性 1&#xff09;套接字的连接状态 socketTcp.Connected 2&#xff09;获取套接字的类型 socketTcp.So…

【C++游戏引擎开发】《线性代数》(1):环境配置与基础矩阵类设计

一、开发环境配置 1.1 启用C 20 在VS2022中新建项目后右键项目 1.2 启用增强指令集 1.3 安装Google Test vcpkg安装使用指南 vcpkg install gtest:x64-windows# 集成到系统目录&#xff0c;只需要执行一次&#xff0c;后续安装包之后不需要再次执行 vcpkg integrate inst…

Flutter完整开发实战详解(一、Dart语言和Flutter基础)

前言 在如今的 Flutter 大潮下&#xff0c;本系列是让你看完会安心的文章。本系列将完整讲述&#xff1a;如何快速从0开发一个完整的 Flutter APP&#xff0c;配套高完成度 Flutter 开源项目 GSYGithubAppFlutter。同时也会提供一些 Flutter 的开发细节技巧&#xff0c;并针对…

Spring 事件监听机制介绍以及源码分析

在复杂的业务系统中&#xff0c;模块间的过度耦合往往会导致代码维护困难、扩展性受限。Spring 事件监听机制基于观察者模式&#xff0c;提供了一种优雅的解耦方案&#xff0c;使得组件间通过事件驱动实现松耦合通信。这种机制不仅被 Spring 框架内部使用&#xff08;如容器生命…

【VSCode的安装与配置】

目录&#xff1a; 一&#xff1a;下载 VSCode二&#xff1a;安装 VSCode三&#xff1a;配置 VSCode 一&#xff1a;下载 VSCode 下载地址&#xff1a;https://code.visualstudio.com/download 下载完成之后&#xff0c;在对应的下载目录中可以看到安装程序。 二&#xff1a;安装…

2024年认证杯SPSSPRO杯数学建模C题(第二阶段)云中的海盐全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 C题 云中的海盐 原题再现&#xff1a; 巴黎气候协定提出的目标是&#xff1a;在2100年前&#xff0c;把全球平均气温相对于工业革命以前的气温升幅控制在不超过2摄氏度的水平&#xff0c;并为1.5摄氏度而努力。但事实上&#xff0c;许多之前的…

Scala基础语法与简介

对象 -对象有属性和行为。例如&#xff1a;一只狗的状属性有&#xff1a;颜色&#xff0c;名字&#xff0c;行为有&#xff1a;叫、跑、吃等。对象是一个类的实例。 类 -类是对象的抽象&#xff0c;而对象是类的具体实例。 方法 -方法描述的基本的行为&#xff0c;一个类可以…

鸿蒙UI开发

鸿蒙UI开发 本文旨在分享一些鸿蒙UI布局开发上的一些建议&#xff0c;特别是对屏幕宽高比发生变化时的应对思路和好的实践。 折叠屏适配 一般情况&#xff08;自适应布局/响应式布局&#xff09; 1.自适应布局 1.1自适应拉伸 左右组件定宽 TypeScript //左右定宽 Row() { …

BeeWorks:为企业打造专网部署即时通讯解决方案

在数字化快速发展的今天&#xff0c;企业的沟通与协作越来越依赖于高效的即时通讯工具。然而&#xff0c;保障信息安全和数据隐私也变得愈发重要。这种情况下&#xff0c;专网部署即时通讯软件成为许多企业的首要选择。BeeWorks作为一款优质的专网部署即时通讯软件&#xff0c;…

uniapp笔记-swiper组件实现轮播图

思路 主要就是参考 swiper | uni-app官网 实现轮播图。 实例 新建一个banner.vue通用组件。 代码如下&#xff1a; <template><view>轮播图</view> </template><script> </script><style> </style> 随后在index.vue中导…

企业在人工智能创新与安全之间走钢丝

2025 年全球 AI/ML 工具使用量将激增&#xff0c;企业将 AI 融入运营之中&#xff0c;员工也将 AI 嵌入日常工作流程中。报告显示&#xff0c;企业对 AI/ML 工具的使用同比增长 3,000% 以上&#xff0c;凸显了各行各业迅速采用 AI 技术&#xff0c;以提升生产力、效率和创新水平…

vue - [Vue warn]: Duplicate keys detected: ‘0‘. This may cause an update error.

问题描述&#xff1a; vue项目中&#xff0c;对表单数组赋值时&#xff0c;控制台抛出警告&#xff1a; 问题代码&#xff1a; 问题分析&#xff1a; 1、Vue 要求每个虚拟 DOM 节点必须有唯一的 key。该警告信息通常出现在使用v-for循环的场景中&#xff0c;多个同级节点使用…

Containerd+Kubernetes搭建k8s集群

虚拟机环境设置&#xff0c;如果不是虚拟机可以忽略不看 1、安装配置containerd 1.1 添加 Kubernetes 官方仓库 安装cri-tools的时候需要用到 cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kub…

ubuntu服务器server版安装,ssh远程连接xmanager管理,改ip网络连接。图文教程

ventoy启动服务器版iso镜像&#xff0c;注意看server名称&#xff0c;跟之前desktop版ubuntu不一样。没有gui界面。好&#xff0c;进入命令行界面。语言彻底没汉化了&#xff0c;选英文吧&#xff0c;别的更看不懂。 跟桌面版ubuntu类似&#xff0c;选择是否精简系统&#xff0…

QOpenGLWidget视频画面上绘制矩形框

一、QPainter绘制 在QOpenGLWidget中可以绘制&#xff0c;并且和OpenGL的内容叠在一起。paintGL里面绘制完视频后&#xff0c;解锁资源&#xff0c;再用QPainter绘制矩形框。这种方式灵活性最好。 void VideoGLWidget::paintGL() {glClear(GL_COLOR_BUFFER_BIT);m_program.bi…