11.1Linux串口应用程序开发
UART简介
UART的全称是Universal Asynchronous Receiver and Transmitter,即异步发送和接收。
串口在嵌入式中用途非常的广泛,主要的用途有:
- 打印调试信息;
- 外接各种模块:GPS、蓝牙;
串口因为结构简单、稳定可靠(通过RXD 、TXD、GND三根线即可完成通信),广受欢迎。
串口的参数
- 波特率:常用的有9600、19200、115200、230400、921600等,其实意思就是每秒传输这么多个比特位数(bit)
- 起始位:先发出一位或两位逻辑”0”的信号,表示传输数据的开始。
- 数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。
- 校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。
- 停止位:它是一个字符数据的结束标志,通常一位或两位逻辑”1”。
串口传输数据
- 双方约定好波特率(每一位占据的时间)。
- 双方约定好传输电平,即高电平是多少v,低电平是但是v。
- 双方约定好起始位位数。
- 双方约定好奇偶校验。
- 双方约定好停止位位数。
tty 设备节点命名规则
- /dev/ttyS0 、 /dev/ttySTM0 :串口终端。
- /dev/tty1 、 /dev/tty2 、 …… :虚拟终端设备。
- /dev/tty0 :当前正在使用的虚拟终端的别名。
- /dev/tty :本进程自己的终端。
- /dev/console :控制台,由内核的命令行参数确定,可以认为是一个拥有更高权限的终端,不管当前正在使用哪个终端,系统信息都会发送到控制台上。
串口编程
头文件
编写串口应用程序时需要先包含如下头文件:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
打开串口
int open_port(void)
{int fd;/* 打开串口* "/dev/ttyf1" 串口文件名* O_RDWR 以读写方式打开* O_NOCTTY 不将此端口作为控制终端* O_NDELAY 表示不关心 DCD 信号线的状态,同时它还将串口设置为非阻塞模式,在没有数据时进行读取返回0,* 后面可以通过fcntl(fd, F_SETFL, 0)将其设置为阻塞式**/fd = open("/dev/ttyf1", O_RDWR | O_NOCTTY | O_NDELAY);if (fd == -1){/* 打开失败 */perror("open_port: Unable to open /dev/ttyf1 - ");}else{/* 设置为阻塞式读取 */fcntl(fd, F_SETFL, 0);}return (fd);
}
读写串口
通过write函数写数据(发送数据),通过read函数都数据(接收数据)
关闭串口
通过close函数关闭串口设备
配置串口
可以通过如下来读取或配置串口参数:
/* tcgetattr 获取串口配置参数, tcsetattr 设置串口配置参数- fd- optional_actions 配置模式:- TCSANOW 改变立即发生 - TCSADRAIN 改变在写入 fd 的数据都被传输后生效- TCSAFLUSH 改变在写入 fd 的数据都被传输后生效,且已接收但未读取的数据全部丢弃- termios_p 串口配置参数**/int tcgetattr(int fd, struct termios *termios_p)int tcsetattr(int fd, int optional_actions, const struct termios *termios_p)
串口的配置参数保存在struct termios 结构体中,此结构体至少包含以下成员:
/* 输入控制标志 */tcflag_t c_iflag;/* 输出控制标志 */tcflag_t c_oflag;/* 控制模式标志 */tcflag_t c_cflag;/* 本地模式标志 */tcflag_t c_lflag;/* 行规程 */cc_t c_cc[NCCS];/* 输入波特率 */int c_ispeed;/* 输出波特率 */int c_ospeed;
- 输入控制标志选项(c_iflag)
INPCK :启用输入奇偶校验
IGNPAR :忽略奇偶校验错误
PARMRK :标记奇偶校验错误
ISTRIP :去掉奇偶校验位
IXON :启用输出的 XON/XOFF 流控制
IXOFF :启用输入的 XON/XOFF 流控制
IXANY :允许任何字符来重新开始输出
IGNBRK :忽略输入中的 BREAK 状态
BRKINT :检测到中断条件时发送 SIGINT
INLCR :将换行映射到回车
IGNCR :忽略回车
ICRNL :将回车映射到换行
IUCLC :将大写映射到小写
启用输入奇偶校验并剥离奇偶校验位:
c_iflag |= (INPCK | ISTRIP)
启用软件流控制:
c_iflag |= (IXON | IXOFF | IXANY);
禁用软件流控:
c_iflag &= ~(IXON | IXOFF | IXANY);
- 输出控制标志选项(c_oflag)
OPOST :启用输出处理(未设置 = 原始输出)
OLCUC :将小写映射到大写
ONLCR :将换行映射到回车+换行
OCRNL :将回车映射到换行
NOCR :不在第 0 列输出回车
ONLRET :将换行映射到回车
OFILL :发送填充字符作为延时,而不是使用定时来延时
OFDEL :填充字符为 DEL
NLDLY :新行延时掩码
NL0 :新行没有延迟
NL1 :换行后延迟100ms
CRDLY :回车延时掩码
CR0 :回车没有延迟
CR1 :回车后的延迟取决于当前列位置
CR2 :回车后延迟 100 毫秒
CR3 :回车后延迟 150 毫秒
TABDLY :tab延时掩码
TAB0 :TAB 没有延迟
TAB1 :TAB 后的延迟取决于当前列位置
TAB2 :发送 TAB 后延迟 100 毫秒
TAB3 :将 TAB 字符扩展为空格
BSDLY :回退延时掩码
BS0 :回退没有延迟
BS1 :回退后延迟 50 毫秒
VTDLY :竖直跳格延时掩码
VT0 :竖直跳格无延迟
VT1 :竖直跳格后延迟 2 秒
FFDLY :进表延时掩码
FF0 :进表没有延迟
FF1 :进表后延迟 2 秒
选择原始输出:
/* 禁用OPOST选项时,将忽略 c_oflag中的所有其他选项位 */c_oflag &= ~OPOST;
- 控制模式标志(c_cflag)
CSIZE :字符长度掩码
CS5 :5 个数据位
CS6 :6 个数据位
CS7 :7 个数据位
CS8 :8 个数据位
CSTOPB :2 个停止位(否则为 1 个)
CREAD :启用接收器
PARENB :启用奇偶校验位
PARODD :使用奇校验而不是偶校验
HUPCL :关闭时挂断 moden
CLOCAL :忽略 modem 控制线
CRTSCTS :启用硬件流控制
设置字符大小:
c_cflag &= ~CSIZE; /* 屏蔽字符大小位 */ c_cflag |= CS8; /* 选择 8 个数据位 */
设置奇偶校验:
/*无奇偶校验 (8N1) */c_cflag &= ~PARENB;c_cflag &= ~CSTOPB;c_cflag &= ~CSIZE;c_cflag |= CS8;/* 偶校验(7E1) */c_cflag |= PARENB;c_cflag &= ~PARODD;c_cflag &= ~CSTOPB;c_cflag &= ~CSIZE;c_cflag |= CS7;/* 奇校验(7O1) */c_cflag |= PARENB;c_cflag |= PARODD;c_cflag &= ~CSTOPB;c_cflag &= ~CSIZE;c_cflag |= CS7;
设置硬件流控制:
c_cflag |= CRTSCTS;
禁用硬件流控制:
c_cflag &= ~CRTSCTS;
- 本地模式标志(c_lflag)
ISIG :启用 SIGINTR、SIGSUSP、SIGDSUSP 和 SIGQUIT 信号
ICANON :使能规范输入,这使 EOF 、 EOL 、 EOL2 、 ERASE 、 KILL 、 REPRINT 、 STATUS 、 WERASE 字符起作用,输入字符被装配成行
XCASE :如果同时设置了 ICANON ,则输入被转换为小写(除有前缀 / 的字符以外),输出一个大写字符也在其前加一个 /
ECHO :回显输入字符
ECHOE :如果同时设置了 ICANON ,字符 ERASE 擦除前一个输入字符, WERASE 擦除前一个词
ECHOK :如果同时设置了 ICANON,字符 KILL 删除当前行
ECHONL :如果同时设置了 ICANON,回显字符 NL,即使没有设置 ECHO
NOFLSH :禁止在产生 SIGINT, SIGQUIT 和 SIGSUSP 信号时刷新输入和输出队列
IEXTEN :启用扩展字符处理,这个标志必须与 ICANON 同时使用才能解释特殊字符 EOL2 、 LNEXT 、 REPRINT 、 WERASE, IUCLC 标志才有效
ECHOCTL :如果同时设置了 ECHO,除了 TAB, NL, START, 和 STOP 之外的 ASCII 控制字符被回显为 ^X (这里 X 是比控制字符加 0x40 的 ASCII 码)
ECHOPRT :如果同时设置了 ICANON 和 IECHO,字符在删除的同时被打印
ECHOKE :如果同时设置了 ICANON ,回显 KILL 时将删除一行中的每个字符
FLUSHO :输出被刷新,这个标志可以通过键入字符 DISCARD 来开关
PENDIN :在读入下一个字符时,输入队列中所有字符被重新输出
TOSTOP :向试图写控制终端的后台进程组发送 SIGTTOU 信号
选择规范输入:
c_lflag |= (ICANON | ECHO | ECHOE);
选择原始输入:
c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
- 控制字符(c_cc )
VINTR :中断字符。发出 SIGINT 信号,当设置 ISIG 时可被识别
VQUIT :退出字符。发出 SIGQUIT 信号,当设置 ISIG 时可被识别
VERAS :删除字符。删除上一个还没有删掉的字符,但不删除上一个 EOF 或行首,当设置 ICANON 时可被识别
VKILL :终止字符。删除自上一个 EOF 或行首以来的输入,当设置 ICANON 时可被识别
VEOF :文件尾字符。这个字符使得 tty 缓冲中的内容被送到等待输入的用户程序中,而不必等到 EOL,当设置ICANON 时可被识别
VEOL : 行结束字符,当设置 ICANON 时可被识别
VEOL2 :替换的行结束,当设置 ICANON 时可被识别
VMIN :要读取的最小字符数
VTIME :等待数据的时间(100毫秒)
MIN与TIME组合有以下四种:
//有数据立即读取,并返回读取的字节数,无数据立即返回0
MIN = 0 , TIME = 0;
//在 TIME 指定的时间内有数据则返回读取的字节数,无数据返回0
MIN = 0 , TIME > 0;
//在最少读取到 MIN 个字节数才返回
MIN > 0 , TIME = 0;
//读取到的一个字节时启动计时,此后每收到一个字符都会重新计时,在最少读取到 MIN 个字节数或超时返回读取的字节数
MIN > 0 , TIME > 0;
- 波特率(c_ispeed & c_ospeed)
波特率的设置和读取通过下列函数实现:
/* 获取输入波特率 */speed_t cfgetispeed(const struct termios *termios_p);/* 获取输出波特率 */speed_t cfgetospeed(const struct termios *termios_p);/* 设置输入波特率 */int cfsetispeed(struct termios *termios_p, speed_t speed);/* 设置输出波特率 */int cfsetospeed(struct termios *termios_p, speed_t speed);/* 设置输入输出波特率 */int cfsetspeed(struct termios *termios_p, speed_t speed);
串口应用程序编写
原理图
编写设备树
在设备树stm32mp157d-atk.dtsi中引用uart3和uart4节点,并加入如下内容:
&usart3 {pinctrl-names = "default", "sleep";pinctrl-0 = <&usart3_pins_mx>;pinctrl-1 = <&usart3_sleep_pins_mx>;/delete-property/dmas;/delete-property/dma-names;status = "okay";
};&uart5 {pinctrl-names = "default", "sleep";pinctrl-0 = <&uart5_pins_mx>;pinctrl-1 = <&uart5_sleep_pins_mx>;/delete-property/dmas;/delete-property/dma-names;status = "okay";
};
在设备树stm32mp15-pinctrl.dtsi中引用的&pinctrl节点中加入如下内容:
uart5_pins_mx: uart5_mx-0 {pins1 {pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX */bias-disable;};pins2 {pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */bias-disable;drive-push-pull;slew-rate = <0>;};};uart5_sleep_pins_mx: uart5_sleep_mx-0 {pins {pinmux = <STM32_PINMUX('B', 12, ANALOG)>, /* UART5_RX */<STM32_PINMUX('B', 13, ANALOG)>; /* UART5_TX */};};usart3_pins_mx: usart3_mx-0 {pins1 {pinmux = <STM32_PINMUX('D', 8, AF7)>; /* USART3_TX */bias-disable;drive-push-pull;slew-rate = <0>;};pins2 {pinmux = <STM32_PINMUX('D', 9, AF7)>; /* USART3_RX */bias-disable;};};usart3_sleep_pins_mx: usart3_sleep_mx-0 {pins {pinmux = <STM32_PINMUX('D', 8, ANALOG)>, /* USART3_TX */<STM32_PINMUX('D', 9, ANALOG)>; /* USART3_RX */};};
在设备树stm32mp157d-atk.dts的aliases节点中增加如下内容:
//usart3的设备文件名是ttySTM1//uart5的设备文件名是ttySTM2serial1 = &usart3;serial2 = &uart5;
用make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabihf- dtbs -j8编译设备树,然后用新的.dtb文件启动系统
编写应用程序
编写一个应用程序,从串口读取数据,然后显示读取到的字节数,并将读取的数据返回到PC,程序包含以下几个部分:
- 打开串口设备
- 配置串口设备
- 读写串口设备
完整的应用程序如下:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */int set_port(int fd, int baud_rate, int n_bits, char parity, int n_stop)
{struct termios options;/* 读取配置 */if(tcgetattr(fd, &options) < 0) { perror("SetupSerial 1");return -1;}options.c_iflag = 0x00;options.c_oflag = 0x00;options.c_cflag = 0x00;options.c_lflag = 0x00;/* 禁用软件流控 */options.c_iflag &= ~(IXON | IXOFF | IXANY);if((parity == 'O') || (parity == 'E')) {/* 启用输入奇偶校验并剥离奇偶校验位 */options.c_iflag |= (INPCK | ISTRIP);}/* 选择原始输出 */options.c_oflag &= ~OPOST;/* 设置字符大小 */options.c_cflag &= ~CSIZE;switch(n_bits){case 7:options.c_cflag |= CS7;break;case 8:default:options.c_cflag |= CS8;break;}/* 设置奇偶校验 */switch(parity){case 'O':options.c_cflag |= PARENB;options.c_cflag |= PARODD;break;case 'E':options.c_cflag |= PARENB;options.c_cflag &= ~PARODD;break;case 'N':default:options.c_cflag &= ~PARENB;break;}/* 禁用硬件流控制 */options.c_cflag &= ~CRTSCTS;/* 设置停止位 */switch(n_stop){case 2:options.c_cflag |= CSTOPB;break;case 1:default:options.c_cflag &= ~CSTOPB;break;}/* 启用接收器,并忽略 modem 控制线 */options.c_cflag |= CLOCAL | CREAD; /* 选择原始输入 */options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);/* 设置波特率 */switch(baud_rate){case 2400:cfsetispeed(&options, B2400);cfsetospeed(&options, B2400);break;case 4800:cfsetispeed(&options, B4800);cfsetospeed(&options, B4800);break;case 9600:cfsetispeed(&options, B9600);cfsetospeed(&options, B9600);break;case 115200:default:cfsetispeed(&options, B115200);cfsetospeed(&options, B115200);break;}/* 设置读取超时和每次读取的最小字节数 */options.c_cc[VMIN] = 1;options.c_cc[VTIME] = 1;/* 刷新缓冲区 */tcflush(fd, TCIFLUSH);/* 配置串口 */if((tcsetattr(fd, TCSANOW, &options))!=0){perror("com set error");return -1;}return 0;
}int open_port(const char *com)
{int fd;/* 打开串口 */fd = open(com, O_RDWR | O_NOCTTY | O_NDELAY);if (fd == -1){/* 打开失败 */perror("open_port");}else{/* 设置为阻塞式读取 */fcntl(fd, F_SETFL, 0);}return (fd);
}int main(int argc, char **argv)
{int fd;int result;char buffer[64];if (argc != 2){printf("Usage: \n");printf("%s </dev/ttySAC1 or other>\n", argv[0]);return -1;}/* 打开串口设备 */fd = open_port(argv[1]);if (fd < 0){printf("open %s err!\n", argv[1]);return -1;}/* 设置串口设备 */result = set_port(fd, 115200, 8, 'N', 1);if(result < 0){printf("set port err!\n");return -1;}while(1){/* 读取串口接收到的数据 */result = read(fd, &buffer, sizeof(buffer));if(result > 0){printf(" read %d bytes\r\n", result);/* 通过串口发送数据 */result = write(fd, &buffer, result);}elseperror(NULL);}return 0;
}
上机测试
- 根据原理图修改设备树,主要是使能需要用到的串口,然后编译设备树,用新的设备树启动串口
- 从这里下载代码,并进行编译,然后将编译得到的可执行程序拷贝到目标板的root目录中
- 连接串口线到电脑
- 在终端运行命令./uart_teat.out /dev/ttySTM2进行串口测试,其中/dev/ttySTM2是串口设备文件名,如下分别是串口测试软件输出和串口调试软件的截图
相关文章:

11.1Linux串口应用程序开发
UART简介 UART的全称是Universal Asynchronous Receiver and Transmitter,即异步发送和接收。 串口在嵌入式中用途非常的广泛,主要的用途有: 打印调试信息;外接各种模块:GPS、蓝牙; 串口因为结构简单、稳…...
log4j学习
依赖 <!--log4j依赖--> <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> </dependency><!--测试--> <dependency><groupId>org.junit.jupiter</g…...

【Vue2+3入门到实战】(4)Vue基础之指令修饰符 、v-bind对样式增强的操作、v-model应用于其他表单元素 详细示例
目录 一、今日学习目标1.指令补充 二、指令修饰符1.什么是指令修饰符?2.按键修饰符3.v-model修饰符4.事件修饰符 三、v-bind对样式控制的增强-操作class1.语法:2.对象语法3.数组语法4.代码练习 四、京东秒杀-tab栏切换导航高亮1.需求:2.准备代…...

【数据结构和算法】找到最高海拔
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 前缀和的解题模板 2.1.1 最长递增子序列长度 2.1.2 寻找数组中第 k 大的元素 2.1.3 最长公共子序列…...
redis相关问题
1、概述: 1. 非关系型数据库 2. 是分布式缓存数据库 3. 使用 key -value结构存储 2、作用: 用作缓存降低数据库压力,提高性能;可以用作消息队列(削峰、解耦、异步调用) 3、基础语法: 基础命令…...
第41节: Vue3 watch函数
在UniApp中使用Vue3框架时,你可以使用watch函数来观察和响应Vue实例上的数据变化。以下是一个示例,演示了如何在UniApp中使用Vue3框架使用watch函数: <template> <view> <input v-model"message" type"text…...

Centos7:升级gcc、g++到版本5.2.0
背景 Centos7.9版本默认的g版本是4.8.5,在实践golang项目中,用到C14,编译时会报错:gcc: error: unrecognized command line option ‘-stdc14’ 因此,gcc需要升级到更高版本,我这里使用源码编译形式升级到g…...
Pytohn data mode plt
文章目录 文件的读写创建.csv类型的文件,并读取文件创建.xlsx文件 使用Python做图生成数据集切片取值操作修改张量中指定位置的数据 知识点torch.arange(x)torch.tensor(2)Atorch.randn(36).reshape(6,6)shapenumel()reshape(x,y,z)torch.zeros(3,3,4)torch.ones(2,…...
内网离线搭建之----kafka集群
1.系统版本 虚拟机192.168.9.184 虚拟机192.168.9.185 虚拟机192.168.9.186系统 centos7 7.6.1810 2.依赖下载 ps:置顶资源里已经下载好了,直接用!!!!!!!!…...
5.1 显示窗口的内容(一)
一,如何显示窗口的内容? 显示器用于在物理硬件(如计算机显示器或触摸屏显示器)上显示窗口的内容。 屏幕API提供的功能允许我们创建同时写入多个窗口和显示的应用程序。屏幕支持多个显示器,但创建和管理使用多个显示器…...

基于包围盒算法的三维点云数据压缩和曲面重建matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 包围盒构建 4.2 点云压缩 4.3 曲面重建 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...........................................…...

关于Python里xlwings库对Excel表格的操作(十八)
这篇小笔记主要记录如何【设置单元格数据的对齐方式】。前面的小笔记已整理成目录,可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 (1)如何安装导入xlwings库; (2)如何在Wps下…...

VScode远程连接服务器,Pycharm专业版下载及远程连接(深度学习远程篇)
Visual Code、PyCharm专业版,本地和远程交互。 远程连接需要用到SSH协议的技术,常用的代码编辑器vscode 和 pycharm都有此类功能。社区版的pycharm是免费的,但是社区版不支持ssh连接服务器,只有专业版才可以,需要破解…...
Vue2和Vue3组件间通信方式汇总(3)------$bus
组件间通信方式是前端必不可少的知识点,前端开发经常会遇到组件间通信的情况,而且也是前端开发面试常问的知识点之一。接下来开始组件间通信方式第三弹------$bus,并讲讲分别在Vue2、Vue3中的表现。 Vue2Vue3组件间通信方式汇总(1)…...

PyTorch加载数据以及Tensorboard的使用
一、PyTorch加载数据初认识 Dataset:提供一种方式去获取数据及其label 如何获取每一个数据及其label 总共有多少的数据 Dataloader:为后面的网络提供不同的数据形式 数据集 在编译器中导入Dataset from torch.utils.data import Dataset 可以在jupyter中查看Dataset官方文档&…...
TensorFlow是什么
TensorFlow是什么 Tensorflow是一个Google开发的第二代机器学习系统,克服了第一代系统DistBelief仅能开发神经网络算法、难以配置、依赖Google内部硬件等局限性,应用更加广泛,并且提高了灵活性和可移植性,速度和扩展性也有了大幅…...

docker-compose 安装Sonar并集成gitlab
文章目录 1. 前置条件2. 编写docker-compose-sonar.yml文件3. 集成 gitlab4. Sonar Login with GitLab 1. 前置条件 安装docker-compose 安装docker 创建容器运行的特有网络 创建挂载目录 2. 编写docker-compose-sonar.yml文件 version: "3" services:sonar-postgre…...
支付平台在选择服务器租用时要注意什么?
如果要建设一个支付平台的话要进行服务器租用,一旦涉及到钱的方面就必须要顾虑到多方面,这样才能保证安全性,今天小编就给大家讲一讲要注意什么呢? 1、带宽:带宽是业务稳定性的直接因素,只有带宽充足,这样…...
IDEA2018升级2023,lombok插件不兼容导致get/set方法无法使用
1、问题 最近了解到一款叫CodeGeeX 的智能编程助手,想要试用一下,但是IDEA2018版本太低了,没有CodeGeeX插件,于是打算将IDEA升级到2023.2.5版本,具体升级过程略过,升级完成后,启动项目…...
企业微信服务商代开发模式获取授权企业的客户信息
服务商代开发素材: 服务商可信ip 企业微信认证 测试时不用再次创建一个企业微信,可以用当前的企业微信作为授权企业使用一、创建代开发应用模板 1,代开发模板回调URL配置 参考 注意:保存代开发应用模板时的corpId是服务商的企业…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...