iMX6ULL 库移植 | Libgpiod 库的交叉编译及使用指南(linux)

news2024/12/25 1:53:20

GPIO口的操作,是很常见的功能。传统的GPIO sysfs接口已被弃用。自Linux 4.8起,内核提供了全新的操作gpio的方式libgpiod(C library and tools for interacting with the linux GPIO character device),当然也更高效,推荐使用。

libgpiod简介

libgpiod - 用于与Linux GPIO字符设备进行交互的C库和工具(gpiod代表GPIO设备)

libgpiod/libgpiod.git - C library and tools for interacting with the linux GPIO character device

自Linux 4.8起,GPIO sysfs接口已被弃用。用户空间应改用字符设备。该库封装了ioctl调用和数据结构,提供了一个简单直观的API。

新的字符设备接口保证在关闭设备文件描述符后释放所有分配的资源,并添加了一些在已过时的sysfs接口中不存在的新功能(如事件轮询、一次设置/读取多个值或开源和开漏GPIO)。

不幸的是,不再可以仅使用标准命令行工具与Linux设备文件进行交互。这就是创建一个库的原因,它封装了繁琐的、基于ioctl的内核-用户空间交互,并提供了一组方便的函数和不透明的数据结构。 此外,该项目还包含一组命令行工具,可方便地将用户脚本转换为使用字符设备。

旧的方式 GPIO sysfs 接口使用

在linux4.8之前,没有libgpiod,传统操作GPIO口使用的是sysfs方式控制。使用方式举例如下:

1.sysfs 先导出 GPIO 17 和 GPIO 18

echo 17 > /sys/class/gpio/export
echo 18 > /sys/class/gpio/export

现在再去 ls /sys/class/gpio/ 目录,就会多出来 gpio17 和 gpio18 目录。

2.设置 gpio 模式为输出。

echo out > /sys/class/gpio/gpio17/direction
echo out > /sys/class/gpio/gpio18/direction

3.设置 gpio 高电平点亮 LED,点亮绿色(G)灯。

echo 1 > /sys/class/gpio/gpio18/value
#熄灭写 0 即可
echo 0 > /sys/class/gpio/gpio18/value

如何构建libgpiod

这是一个相当标准的autotools项目。核心C库除了标准C库与GNU扩展之外,没有任何外部依赖项。 命令行工具可选择依赖于libedit以获得交互功能。 要构建项目(包括命令行工具),

运行:

./autogen.sh --enable-tools=yes --prefix=<安装路径>

make

make install

autogen脚本将执行./configure并将所有命令行参数传递给它。

有关所有configure功能,请参阅:./configure --help。

自带工具

目前有六个可用的命令行工具:

* gpiodetect - 列出系统上存在的所有gpiochips,它们的名称、标签和GPIO线数

* gpioinfo - 列出线路、它们的gpiochip、偏移量、名称和方向,如果在使用中,则列出使用者名称和任何其他配置的属性,如活动状态、偏置、驱动、边缘检测和去抖动周期

* gpioget - 读取指定GPIO的值

* gpioset - 设置指定GPIO的值,保持线路状态直到进程被终止或退出

* gpiomon - 等待GPIO上的边缘事件,指定要监视的边缘,处理多少个事件后退出,或者是否将事件报告到控制台

* gpionotify - 等待GPIO信息的更改,指定要监视的更改,处理多少个事件后退出,或者是否将事件报告到控制台

工具使用举例

# 检测可用的gpiochips。 
$ gpiodetect 
gpiochip0 [pinctrl-bcm2711]
gpiochip1 [raspberrypi-exp-gpio]
 
# 读取gpiochip上所有的信息。 
$ gpioinfo -c 1 
gpiochip1 - 8个: 
  0:“BT_ON” 输出 
  1:“WL_ON” 输出 
  2:“PWR_LED_OFF” 输出低电平 使用者=“led1” 
  3:“GLOBAL_RESET” 输出 
  4:“VDD_SD_IO_SEL” 输出 使用者=“vdd-sd-io” 
  5:“CAM_GPIO” 输出 使用者=“cam1_regulator” 
  6:“SD_PWR_ON” 输出 使用者=“sd_vcc_reg” 
  7:“SD_OC_N” 输入 
 
# 读取特定的信息。 
$ ./gpioinfo PWR_LED_OFF STATUS_LED_G_CLK GLOBAL_RESET 
gpiochip0 42 “STATUS_LED_G_CLK” 输出 使用者=“led0” 
gpiochip1 2 “PWR_LED_OFF” 输出低电平 使用者=“led1” 
gpiochip1 3 “GLOBAL_RESET” 输出 
 
# 按名称读取单个GPIO的值。 
$ gpioget RXD1 
“RXD1” = 激活 
 
# 按芯片和偏移量读取单个GPIO的值。 
$ gpioget -c 0 15 
“15” = 激活 
 
# 以数字值的形式读取单个GPIO的值。 
$ gpioget --numeric RXD1 
1 
 
# 同时读取两个值。将的活动状态设置为低电平,并且不使用带引号的名称。 
$ gpioget --active-low --unquoted GPIO23 GPIO24 
GPIO23 = 激活 GPIO24 = 激活 
 
# 设置的值,并保持该直到被终止。 
$ gpioset GPIO23=1 
 
# 设置两个的值,然后使其成为守护进程并保持。 
$ gpioset --daemonize GPIO23=1 GPIO24=0 
 
# 设置单个的值,保持20毫秒,然后退出。 
$ gpioset --hold-period 20ms -t0 GPIO23=1 
 
# 在GPIO22上以1Hz频率闪烁LED 
$ gpioset -t500ms GPIO22=1 
 
# 在GPIO22上以1Hz频率和20%的工作比闪烁LED 
$ gpioset -t200ms,800ms GPIO22=1 
 
# 以交互方式设置一些(需要--enable-gpioset-interative) 
$ gpioset --interactive --unquoted GPIO23=inactive GPIO24=active 
gpioset> get 
GPIO23 = inactive GPIO24 = active 
gpioset> toggle 
gpioset> get 
GPIO23 = 激活 GPIO24 = inactive 
gpioset> set GPIO24=1 
gpioset> get 
GPIO23 = 激活 GPIO24 = 激活 
gpioset> toggle 
gpioset> get 
GPIO23 = inactive GPIO24 = inactive 
gpioset> toggle GPIO23 
gpioset> get 
GPIO23 = 激活 GPIO24 = inactive 
gpioset> exit 
 
# 等待单个GPIO上的三个上升沿事件,然后退出。 
$ gpiomon --num-events=3 --edges=rising GPIO22 
10002.907638045 上升沿 “GPIO22” 
10037.132562259 上升沿 “GPIO22” 
10047.179790748 上升沿 “GPIO22” 
 
# 在单个GPIO上等待三个边缘事件,使用本地时间和不带引号的名称,然后退出。 
$ gpiomon --num-events=3 --edges=both --localtime --unquoted GPIO22 
2022-11-15T10:36:59.109615508 上升沿 GPIO22 
2022-11-15T10:36:59.129681898 下降沿 GPIO22 
2022-11-15T10:36:59.698971886 上升沿 GPIO22 
 
# 等待下降沿事件并使用自定义输出格式。 
$ gpiomon --format="%e %c %o %l %S" --edges=falling -c gpiochip0 22 
2 gpiochip0 22 GPIO22 10946.693481859 
2 gpiochip0 22 GPIO22 10947.025347604 
2 gpiochip0 22 GPIO22 10947.283716669 
2 gpiochip0 22 GPIO22 10947.570109430 
... 
 
# 阻塞直到发生边缘事件。不打印任何内容。 
$ gpiomon --num-events=1 --quiet GPIO22 
 
# 监视多个,在第一个边缘事件后退出。 
$ gpiomon --quiet --num-events=1 GPIO5 GPIO6 GPIO12 GPIO17 
 
# 监视的信息更改。 
$ gpionotify GPIO23 
11571.816473718 请求 “GPIO23” 
11571.816535124 释放 “GPIO23” 
11572.722894029 请求 “GPIO23” 
11572.722932843 释放 “GPIO23” 
11573.222998598 请求 “GPIO23” 
... 
 
# 监视的请求,报告UTC时间和不带引号的名称。 
$ gpionotify --utc --unquoted GPIO23 
2022-11-15T03:05:23.807090687Z 请求 GPIO23 
2022-11-15T03:05:23.807151390Z 释放 GPIO23 
2022-11-15T03:05:24.784984280Z 请求 GPIO23 
2022-11-15T03:05:24.785023873Z 释放 GPIO23 
... 
 
# 监视多个,在第一个请求后退出。 
$ gpionotify --quiet --num-events=1 --event=requested GPIO5 GPIO6 GPIO12 GPIO17 
 
# 阻塞直到被释放。 
$ gpionotify --quiet --num-events=1 --event=released GPIO6 

libgpiod库的交叉编译

1. 安装交叉编译工具链:根据目标平台的架构和操作系统,下载并安装相应的交叉编译工具链。例如,对于ARM架构的Linux系统,您可以使用arm-linux-gnueabi工具链。

2. 下载libgpiod源代码:从libgpiod的官方仓库或官方网站下载最新的源代码压缩包。

3. 解压源代码:将下载的压缩包解压到您选择的目录中。

4. 进入源代码目录:使用终端进入解压后的libgpiod源代码目录。

5. 设置环境变量:根据您的交叉编译工具链,设置以下环境变量:

   #export CROSS_COMPILE=<交叉编译工具链前缀>
   export CROSS_COMPILE=/opt/okt507/buildroot/host/bin/aarch64-linux-gnu-
   export CC=${CROSS_COMPILE}gcc
   export CXX=${CROSS_COMPILE}g++
   export AR=${CROSS_COMPILE}ar
   export AS=${CROSS_COMPILE}as
   export LD=${CROSS_COMPILE}ld
   export RANLIB=${CROSS_COMPILE}ranlib
   export STRIP=${CROSS_COMPILE}strip

单个设置麻烦,可以保存脚本文件,例如 setenv.sh ,然后在终端中运行以下命令来设置环境变量并构建libgpiod库: 

source setenv.sh

这将加载脚本中的环境变量,并使其在当前终端会话中生效。然后,您可以继续执行构建步骤来编译和安装libgpiod库。

遇到错误

yang@ubuntu:~/okt507/gpiod/libgpiod-1.6.4$ ./autogen.sh --enable-tools=yes
./autogen.sh: 17: ./autogen.sh: autoreconf: not found

error: possibly undefined macro: AC_CHECK_HEADERS

configure.ac:190: the top level
configure.ac:91: error: possibly undefined macro: AC_CHECK_HEADERS
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
configure.ac:183: error: possibly undefined macro: AC_LANG_PUSH
configure.ac:185: error: possibly undefined macro: AC_LANG_POP
autoreconf: error: /usr/bin/autoconf failed with exit status: 1

需要安装依赖:

sudo apt-get install -y autoconf automake libtool
sudo apt-get install autoconf-archive
sudo apt-get install m4

sudo apt install pkg-config

其中最后一个 pkg-config一定不能忘了,很重要的依赖,否则容易报以下错误:

configure.ac:91: error: possibly undefined macro: AC_CHECK_HEADERS
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.

具体原因,这里有解释:

Why 'Possibly Undefined Macro' Means Install pkg-config | AE1020: Lazy Notebook

 最后,开始交叉编译:

#加载环境变量
source setenv.sh
./autogen.sh --enable-tools=yes --host=arm-linux

#--prefix指定make install的安装目录
./configure --enable-tools=yes --host=arm-linux --prefix=/home/yang/okt507/gpiod/build

Ubuntu关闭后台更新解决重启时间过长问题

Ubuntu虚拟机重启发现用时过长,显示:A stop job is running for Unattended Upgrades Shutdown (10s / 30 min)

经过百度,发现是Ubuntu会自动更新,但这时间也太长了,于是果断禁用。

执行命令:

sudo dpkg-reconfigure unattended-upgrades

选择no并按ENTER以禁用无人参与的升级。
环境变量setenv.sh脚本

#!/bin/bash
 # 设置交叉编译工具链前缀
export CROSS_COMPILE=<交叉编译工具链前缀>
 # 设置交叉编译工具链
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export AS=${CROSS_COMPILE}as
export LD=${CROSS_COMPILE}ld
export RANLIB=${CROSS_COMPILE}ranlib
export STRIP=${CROSS_COMPILE}strip
 # 设置安装路径
#export INSTALL_PATH=<安装路径>

6. 配置构建:运行以下命令配置构建过程:

./autogen.sh --enable-tools=yes --prefix=<安装路径>

<安装路径> 替换为您希望安装libgpiod的路径。

7. 运行构建:运行以下命令开始构建libgpiod库:

8. 安装库:运行以下命令将构建好的库安装到指定的安装路径:

c API使用

#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>

#ifndef	CONSUMER
#define	CONSUMER	"Consumer"
#endif

int blend_led(struct gpiod_line *r, int r_val, struct gpiod_line *g, int g_val, struct gpiod_line *b, int b_val);

/**
* GPIO 16 <-> R
* GPIO 17 <-> B
* GPIO 18 <-> G
*/
int main(int argc, char **argv)
{
	char *chipname = "gpiochip0";
	unsigned int line_num_16 = 16;	// GPIO 16
	unsigned int line_num_17 = 17;	// GPIO 17
	unsigned int line_num_18 = 18;	// GPIO 18
	
	struct gpiod_chip *chip;
	struct gpiod_line *line16, *line17, *line18;
	int ret;

	chip = gpiod_chip_open_by_name(chipname);
	if (!chip) {
		printf("Open chip by name failed. name: %s\n", chipname);
		goto end;
	}
	
	line16 = gpiod_chip_get_line(chip, line_num_16);
	if (!line16) {
		printf("Get line failed. line_num: %u\n", line_num_16);
		goto close_chip;
	}

	line17 = gpiod_chip_get_line(chip, line_num_17);
	if (!line17) {
		printf("Get line failed. line_num: %u\n", line_num_17);
		goto release_line16;
	}

	line18 = gpiod_chip_get_line(chip, line_num_18);
	if (!line18) {
		printf("Get line failed. line_num: %u\n", line_num_18);
		goto release_line17;
	}
	
	ret = gpiod_line_request_output(line16, CONSUMER, 0);
	if (ret < 0) {
		printf("Request line16 as output failed\n");
		goto release_line18;
	}

	ret = gpiod_line_request_output(line17, CONSUMER, 0);
	if (ret < 0) {
		printf("Request line17 as output failed\n");
		goto release_line18;
	}

	ret = gpiod_line_request_output(line18, CONSUMER, 0);
	if (ret < 0) {
		printf("Request line18 as output failed\n");
		goto release_line18;
	}
	
	//R
	ret = blend_led(line16, 1, line17, 0, line18, 0);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	
	sleep(1);
	//G
	ret = blend_led(line16, 0, line17, 0, line18, 1);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	sleep(1);
	
	//B
	ret = blend_led(line16, 0, line17, 1, line18, 0);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	sleep(1);
	
	//yellow
	ret = blend_led(line16, 1, line17, 0, line18, 1);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	sleep(1);
	
	ret = blend_led(line16, 1, line17, 1, line18, 0);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	sleep(1);
	
	ret = blend_led(line16, 0, line17, 1, line18, 1);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}
	sleep(1);
	
	ret = blend_led(line16, 1, line17, 1, line18, 1);
	if (ret < 0) {
		printf("Set output failed.\n");
		goto release_line18;
	}

release_line18:
	gpiod_line_release(line18);
release_line17:
	gpiod_line_release(line17);
release_line16:
	gpiod_line_release(line16);
close_chip:
	gpiod_chip_close(chip);
end:
	return 0;
}

int blend_led(struct gpiod_line *r, int r_val, struct gpiod_line *g, int g_val, struct gpiod_line *b, int b_val){
	int ret = 0;
	ret = gpiod_line_set_value(r, r_val);
	if (ret < 0) {
		printf("Set r output failed. val: %u\n", r_val);
		return ret;
	}
	
	ret = gpiod_line_set_value(g, g_val);
	if (ret < 0) {
		printf("Set g output failed. val: %u\n", g_val);
		return ret;
	}
	
	ret = gpiod_line_set_value(b, b_val);
	if (ret < 0) {
		printf("Set b output failed. val: %u\n", b_val);
		return ret;
	}
	
	return 0;
}

其他资源

qlibgpiod/libgpiod.git - C library and tools for interacting with the linux GPIO character device

Libgpiod库的使用,点亮LED_猪突猛进进进的博客-CSDN博客

百度安全验证

autoreconf执行,出现undefined macro问题_linuxarmsummary的博客-CSDN博客

RaspberryPi 4B 使用 libgpiod 操作 gpio_树莓派4b引脚图_TYYJ-洪伟的博客-CSDN博客

Why 'Possibly Undefined Macro' Means Install pkg-config | AE1020: Lazy Notebook

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

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

相关文章

YashanDB获强制性国家标准GB 18030-2022最高级别认证

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB V23正式完成了强制性国家标准GB 18030-2022《信息技术 中文编码字符集》适配检测&#xff0c;通过该标准的最高实现级别&#xff08;级别3&#xff09;认证&#xff0c;成为数据库领域首批获得该证书的产品&#xff…

css-选择器、常见样式、标签分类

CSS CSS简介 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;或XML&#xff08;标准通用标记语言的一个子集&#xff09;等文件样式的计算机语言。CSS不仅可以静态地修饰网页&#xff0c;还可…

GO-vscode远程开发和调试

本文内容主要包括&#xff1a; 概述&#xff1a; 主要就是把代码放到服务器上然后远程去开发和调试 工具&#xff1a; vscode 远程端&#xff1a; linux 一.安装远程插件 vscode安装Remote - SSH&#xff0c;Remote Explorer&#xff0c;Remote Development&#xff0c…

Eclipse(STS):pom.xml 报错:Multiple markers at this line

pom.xml 报错&#xff1a;Multiple markers at this line STS中&#xff0c;项目能够正常运行&#xff0c;但是 pom.xml 报错&#xff1a;Multiple markers at this line 项目本身没有任何修改&#xff0c;之前不报错的&#xff0c;突然报错了。 Multiple markers at this li…

小程序运营方式有哪些?如何构建小程序运营框架?

​如今&#xff0c;每个企业基本都做过至少一个小程序&#xff0c;但由于小程序本身不具备流量、也很少有自然流量&#xff0c;因此并不是每个企业都懂如何运营小程序。想了解小程序运营方式方法有哪些&#xff1f; 在正式运营小程序前&#xff0c;了解小程序的功能与企业实际经…

36款影音娱乐-音乐、电台、直播类APP评测体验报告

为方便开发者更好地衡量APP在同类产品中的表现和竞争力&#xff0c;有针对性地进行产品优化&#xff0c;软件绿色联盟策划了垂类APP评测体验专题&#xff0c;目前已发布了天气、小说、教育和视频类APP评测体验报告。本期将对影音娱乐类中的音乐、电台、直播类APP围绕绿标五大标…

达标率81.14%,软件绿色联盟7月绿标评测报告发布

导 读 为帮助应用开发者提升APP质量&#xff0c;推动用户体验升级&#xff0c;软件绿色联盟持续基于《软件绿色联盟应用体验标准》&#xff0c;月度对国内主流TOP1000共计18类应用&#xff0c;从兼容性、稳定性、功耗、性能、安全五方面进行绿标评测&#xff0c;解读不同分类应…

Linux和其他类Unix系统的GNU coreutils 知多少

GNU coreutils是GNU项目的一部分&#xff0c;它是一组基本的命令行工具集&#xff0c;用于操作和管理Linux和其他类Unix系统中的文件和数据流。这些工具被广泛用于终端和脚本中&#xff0c;提供了许多常用的功能和实用程序。Linux和其他类Unix系统的GNU coreutils 知多少&#…

VR智慧校园资中控管理平台综合提升了课堂教学质量

随着越来越多高校在课堂中引进VR虚拟仿真实训系统&#xff0c;为了方便老师对全班同学进行高效率地管理&#xff0c;VR中控平台应运而生。下面为您详细介绍VR中控平台在课堂教学中的应用优势。 VR中控系统安装在教师总控端&#xff0c;融合了课件、视频、3D动画等丰富的教学资源…

Leetcode-每日一题【剑指 Offer 35. 复杂链表的复制】

题目 请实现 copyRandomList 函数&#xff0c;复制一个复杂链表。在复杂链表中&#xff0c;每个节点除了有一个 next 指针指向下一个节点&#xff0c;还有一个 random 指针指向链表中的任意节点或者 null。 示例 1&#xff1a; 输入&#xff1a;head [[7,null],[13,0],[11,4]…

【原理图专题】​​​​OrCAD Capture如何将连线加粗

在实际的工作中,特别是大公司里。原理图和PCB是两个不同的人进行的,是两个工种。原理图由硬件工程师绘制,而PCB则由专门的Layout工程师绘制。那么两个人之间的交互要是无法在一个频道上,就很容易在后期审查或是打样产出后才出现这样或那样的问题。 为了做到更好的传达原理…

RabbitMQ---work消息模型

1、work消息模型 工作队列或者竞争消费者模式 在第一篇教程中&#xff0c;我们编写了一个程序&#xff0c;从一个命名队列中发送并接受消息。在这里&#xff0c;我们将创建一个工作队列&#xff0c;在多个工作者之间分配耗时任务。 工作队列&#xff0c;又称任务队列。主要思…

STM32电源名词解释

STM32电源架构 常用名词 VCC Ccircuit 表示电路&#xff0c;即接入电路的电压。 VDD Ddevice 表示器件&#xff0c; 即器件内部的工作电压。 VSS Sseries 表示公共连接&#xff0c;通常指电路公共接地端电压。 VDDA Aanalog 表示模拟&#xff0c;是模拟电路部分的电源。主要为…

七大排序算法详解

1.概念 1.排序的稳定性 常见的稳定的排序有三种&#xff1a;直接插入排序&#xff0c;冒泡排序&#xff0c;归并排序 对于一组数据元素排列&#xff0c;使用某种排序算法对它进行排序&#xff0c;若相同数据之间的前后位置排序后和未排序之前是相同的&#xff0c;我们就成这种…

stm32之5.长按按键(使用时钟源)调整跑马灯速度

------------------------------ 源码 #include <stm32f4xx.h> #include "led.h" #include "delay.h" #include "my_str.h" #include "beep.h" #include "key.h" int main(void) { key_init(); Led_init();…

Java【手撕双指针】LeetCode 57. “两数之和“, 图文详解思路分析 + 代码

文章目录 前言一、两数之和1, 题目2, 思路分析3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1f4d7; Java数据结构: 顺序表, 链表…

M1使用android模拟器的办法

问题背景 在产品的某一期需求中&#xff0c;是关于对于模拟器使用app的用户进行一定的管控&#xff0c;比如说封禁。那么这时候测试就需要模拟器了。对于Windows平台&#xff0c;网上有很多的平台可供选择。使用M1的我&#xff0c;只能不断的找可以用的模拟器。 解决过程 首…

uniapp-form表单

<template><view class"ptb-20 plr-30 bg min100"><view class"bg-white radius-20 pd-30"><view class"bold mt-30 mb-50 size-32">选择方式&#xff1a;</view><u--form labelPosition"left" :mod…

Orchestrator自身高可用性方案

目录 获得 HA 的方法 一 没有高可用性 &#xff08;No high availability&#xff09; 使用场景 架构组成 架构图 二 半高可用性&#xff08;Semi HA&#xff09; 三 基于共享数据库后端高可用&#xff08;HA via shared backend&#xff09; 四 基于Raft协议高可用 五…

python中的matplotlib画折线图(数据分析与可视化)

先导包&#xff08;必须安装了numpy 、pandas 和matplotlib才能导包&#xff09;&#xff1a; import numpy as np import pandas as pd import matplotlib.pyplot as plt核心代码&#xff1a; import numpy as np import pandas as pd import matplotlib.pyplot as pltpd.se…