【安全】linux audit审计使用入门
文章目录
- 1 audit简介
- 2 auditctl的使用
- 2 audit配置和规则
- 3 工作原理
- 4 audit接口调用
- 4.1 获取和修改配置
- 4.2 获取和修改规则
- 4.3 获取审计日志
- 5 audit存在的问题
- 5.1 内核版本
- 5.2 审计日志过多造成的缓存队列和磁盘问题
- 5.2 容器环境下同一个命令的日志存在差异
- 6 参考文档
1 audit简介
audit是Linux内核提供的一种审计机制,由于audit是内核提供的,因此,在使用audit的过程中就包含内核空间和用户空间部分:
- rules:审计规则,其中配置了审计系统需要审计的操作
- auditctl:用户态程序,用于审计规则配置和配置变更
- kaudit:内核空间程序,根据配置好的审计规则记录发生的事件
- auditd:用户态程序,通过netlink获取审计日志
通常的使用流程:
- 用户通过auditctl配置审计规则
- 内核的kauditd程序获取到审计规则后,记录对应的审计日志
- 用户态的auditd获取审计日志并写入日志文件。
audit的主要应用场景是安全审计,通过对日志进行分析发现异常行为。
2 auditctl的使用
auditctl是用户态的控制程序,可以修改audit配置以及审计规则的操作。
auditctl的选项可以分成两类。
配置类:
- -b:配置buffer的大小
- -e:设置enabled标记
- -f:设置failure标记
- -s:返回整体的状态
- –backlog_wait_time:设置backlog_wait_time
审计规则类:
- -a & -A l,a:往某个规则表中增加需要记录的行为
- -d:从某个规则表中删除规则
- -D:删除所有规则
- -F f=v:设置更多监控条件
- -l:查看规则
- -p:在文件监控上设置权限过滤
- -i:当从文件中读取规则时忽略错误
- -c:出错时继续
- -r:设置rate_limit,每秒多少条消息
- -R:从文件中读取规则
- -S:设置要监控的系统调用名或者系统调用号
- -w:增加监控点
- -W:删除监控点
例如,假如我们想要获取调用execve系统调用的事件,可以增加下列的规则:
auditctl -a always,exit -S execve -F key=123456
然后就可以通过ausearch查找该日志:
ausearch -k 123456
如果想要获取执行tail命令的事件,可以增加规则:
auditctl -w /usr/bin/tail -p x -k 123456
然后使用tail命令查看通过ausearch命令查看日志:
time->Sun Apr 23 15:47:36 2023
type=PROCTITLE msg=audit(1682236056.128:4318964): proctitle=7461696C002D6E0032006C756F2E7368
type=PATH msg=audit(1682236056.128:4318964): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=36969 dev=08:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PATH msg=audit(1682236056.128:4318964): item=0 name="/usr/bin/tail" inode=100666597 dev=08:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:bin_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=CWD msg=audit(1682236056.128:4318964): cwd="/root"
type=EXECVE msg=audit(1682236056.128:4318964): argc=4 a0="tail" a1="-n" a2="2" a3="luo.sh"
type=SYSCALL msg=audit(1682236056.128:4318964): arch=c000003e syscall=59 success=yes exit=0 a0=20749e0 a1=218ecd0 a2=2179ee0 a3=7fffa4a99460 items=2 ppid=58219 pid=59519 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=956 comm="tail" exe="/usr/bin/tail" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="123456"
可以看到,开头一行是事件发生的事件,后面的若干行是执行tail命令产生的事件日志,有些日志很简单,例如CWD,表示操作的当前路径,而有些日志很复杂,例如SYSCALL,有接近30个字段。每行日志都有type字段和msg字段(冒号前面是时间戳,可以通过date命令转换,冒号后面是事件ID,同一条规则产生的事件的事件ID是一样的,因此,如果不使用ausearch查找某条规则产生的日志,就需要先用key进行查找,找到对应的事件ID,然后再通过事件ID查找产生的所有日志)。
这里的tail命令的监控,我们只关注上面的2个事件:
- EXECVE:这里给出了调用的参数,argc和argv
- SYSCALL:arch(架构),syscall(系统调用号,可以通过ausyscall --dump查看),success(调用是否成功),exit(返回码),a0~a3为系统调用前4个参数,ppid(父进程ID),pid(进程ID),comm(执行的命令),exe(执行execve的可执行文件)
2 audit配置和规则
通过auditctl -s命令可以看到当前audit的一些属性和配置:
- enabled:表明audit是否会记录事件,可以通过auditctl -e设置
- failure:表明audit是否会记录失败事件,设置为1,才会记录失败事件
- pid:占用audit的进程的pid
- rate_limit:内核每秒发送的最大消息数,如果是0,表示不限制
- backlog_limit:缓存队列长度限制
- lost:由于缓存队列超过限制而导致的丢失的记录数
- backlog:当前缓存队列中等待读取的记录数
- backlog_wait_time:缓存队列满时的等待时间
其中backlog_wait_time是后面的版本提供的。
3 工作原理
除了上述的使用外,audit还有一个特点:独占性。实际的审计操作是由内核中的kauditd完成的,auditd再通过netlink读取审计日志。而kauditd是只允许与一个用户态进程连接,因此,如果系统上已经有auditd进程与kauditd建立连接,后续其他进程进行了抢占,auditd则会断开。那么,如果判断当前是哪个进程与kautid建立了连接呢?可以通过auditctl -s中的pid进行判断。
另一个重要的地方是kaudit如何去应用配置的规则。在auditctl的-a <l,a>
选项中,给出的选项含义是:将规则和对应的action加入到list后面。list有4种:task、exit、user、exclude,action有2种:never、always。
task、exit、user分别表示审计事件的三种类型:user事件是指与用户相关的事件,例如用户登录、注销、切换等。task是指与进程相关的事件,例如进程创建、退出、切换等。exit是指与系统调用相关的事件。exclude只是一个关键字,用于排除不需要审计的文件或者目录。因此,这里面的事件类型与其他的某些选项有强相关:
- -a用于增加规则,-w用于监视文件,两者不能同时使用,说明在实现上,分别维护了以事件类型进行分类的4个列表,同时还维护了需要监视的文件列表
- -S指定系统调用号,因此,只能用于-a exit
配置和规则的变更:
当通过auditctl操作配置或者规则时,会通过netlink将规则发送到内核,内核接收到到配置后会对内部的配置或者规则进行更新
对于规则来说,内核(4.19.281)内部会维护7个链表:
- AUDIT_FILTER_USER:用户生成的日志
- AUDIT_FILTER_TASK:进程创建
- AUDIT_FILTER_ENTRY:系统调用入口
- AUDIT_FILTER_WATCH:文件系统监控
- AUDIT_FILTER_EXIT:系统调用退出
- AUDIT_FILTER_EXCLUDE:审计日志排除
- AUDIT_FILTER_FS
4 audit接口调用
auditctl使用netlink与内核进行交互,因此,要想实现audit的一些能力,就需要采用netlink实现一套交互接口,幸运的是,已经有库可以完成这项工作:yum install -y audit-libs-devel,然后编译时带上-laudit
。
安装完成后,可以查看头文件/usr/include/libaudit.h看下提供的方法。
4.1 获取和修改配置
#include <iostream>
#include <libaudit.h>using namespace std;int main() {int fd = audit_open();audit_request_status(fd);struct audit_reply reply;audit_get_reply(fd, &reply, GET_REPLY_BLOCKING, 0);struct audit_status *status;status = reply.status;cout <<"auditctl -s return:" <<endl;cout << "enabled=" << status->enabled << endl;cout << "failure=" << status->failure << endl;cout << "pid=" << status->pid << endl;cout << "rate_limit=" << status->rate_limit << endl;cout << "backlog_limit=" << status->backlog_limit << endl;cout << "lost=" << status->lost << endl;cout << "backlog=" << status->backlog << endl;return 0;
}
先试用audit_request_status()向内核发送请求,表明要获取配置信息,然后再通过audit_get_reply()接收数据,数据放在struct audit_reply的结构体:
// /usr/src/libaudit.h
struct audit_reply {int type;int len;struct nlmsghdr *nlh;struct audit_message msg;/* Using a union to compress this structure since only one of* the following should be valid for any packet. */union {struct audit_status *status;struct audit_rule_data *ruledata;struct audit_login *login;char *message;struct nlmsgerr *error;struct audit_sig_info *signal_info;struct daemon_conf *conf;
#ifdef AUDIT_FEATURE_BITMAP_ALLstruct audit_features *features;
#endif};
};
如果是获取配置信息,此时数据放在status中:
// include/uapi/linux/audit.h
struct audit_status {__u32 mask; /* Bit mask for valid entries */__u32 enabled; /* 1 = enabled, 0 = disabled */__u32 failure; /* Failure-to-log action */__u32 pid; /* pid of auditd process */__u32 rate_limit; /* messages rate limit (per second) */__u32 backlog_limit; /* waiting messages limit */__u32 lost; /* messages lost */__u32 backlog; /* messages waiting in queue */union {__u32 version; /* deprecated: audit api version num */__u32 feature_bitmap; /* bitmap of kernel audit features */};
};
因此,只要读取返回的audit_reply中的status中的上述字段即可。需要注意的是,如果audit_get_reply()中的第3个参数设置为GET_REPLY_NONBLOCKING,可能拿不到数据,因为fd可能还没有可读的数据,所以,这里要么设置为GET_REPLY_BLOCKING,要么使用select:
#include <iostream>
#include <libaudit.h>using namespace std;int main() {struct timeval t = {.tv_sec = 0, .tv_usec = 500000};int fd = audit_open();audit_request_status(fd);fd_set read_mask;FD_ZERO(&read_mask);FD_SET(fd, &read_mask);select(fd+1, &read_mask, NULL, NULL, &t);struct audit_reply reply;audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);struct audit_status *status;status = reply.status;cout <<"auditctl -s return:" <<endl;cout << "enabled=" << status->enabled << endl;cout << "failure=" << status->failure << endl;cout << "pid=" << status->pid << endl;cout << "rate_limit=" << status->rate_limit << endl;cout << "backlog_limit=" << status->backlog_limit << endl;cout << "lost=" << status->lost << endl;cout << "backlog=" << status->backlog << endl;return 0;
}
对于修改配置的操作,libaudit直接提供了对应的api函数,例如,设置backlog_limit,可以直接调用audit_set_backlog_limit()。
4.2 获取和修改规则
#include <iostream>
#include <libaudit.h>using namespace std;int main() {struct timeval t = {.tv_sec = 0, .tv_usec = 500000};int fd = audit_open();do {audit_request_rules_list_data(fd);fd_set read_mask;FD_ZERO(&read_mask);FD_SET(fd, &read_mask);select(fd+1, &read_mask, NULL, NULL, &t);struct audit_reply reply;audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);if(reply.type == NLMSG_DONE) {break;}struct audit_rule_data *rules;rules = reply.ruledata;cout <<"auditctl -l return:" <<endl;cout << audit_flag_to_name(rules->flags) << endl;cout << audit_action_to_name(rules->action) << endl;} while(true);return 0;
}
获取规则跟获取配置的区别只是发起操作的函数和数据解析不同,获取规则使用audit_request_rules_list_data()发起操作,解析数据时则需要解析struct audit_rule_data的数组。
#include <iostream>
#include <libaudit.h>
#include <linux/audit.h>using namespace std;int main() {int fd = audit_open();struct audit_rule_data *rule = new(struct audit_rule_data);audit_rule_syscall_data(rule, 57);audit_add_rule_data(fd, rule, AUDIT_FILTER_EXIT, AUDIT_NEVER);return 0;
}
上面的代码相当于auditctl -a exit,never -S execve
。
#include <iostream>
#include <libaudit.h>
#include <linux/audit.h>using namespace std;int main() {int fd = audit_open();struct audit_rule_data *rule = new(struct audit_rule_data);audit_add_watch(&rule, "/etc/passwd");audit_add_rule_data(fd, rule, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);return 0;
}
上面的代码相当于auditctl -w /etc/passwd -p rwxa
。
4.3 获取审计日志
获取升级日志还是使用netlink的方式读取:
#include <iostream>
#include <libaudit.h>
#include <string.h>
#include <unistd.h>using namespace std;int main() {int audit_fd = audit_open();if (audit_fd < 0) {cout << "open audit fail:" << strerror(errno) << endl;return -1;}audit_set_enabled(audit_fd, 1);struct audit_reply audit_rep;int ret;struct timeval t = {.tv_sec = 5, .tv_usec = 0};pid_t cur_pid = getpid();ret = audit_set_pid(audit_fd, static_cast<uint32_t>(cur_pid),WAIT_NO);if (ret <= 0) {cout << "audit_set_pid fail:" << strerror(errno) << endl;return -1;}do {fd_set read_mask;FD_ZERO(&read_mask);FD_SET(audit_fd, &read_mask);ret = select(audit_fd + 1, &read_mask, nullptr, nullptr, &t);if (ret <= 0) {cout << "select fail:" << strerror(errno) << endl;continue;}ret = audit_get_reply(audit_fd, &audit_rep,GET_REPLY_NONBLOCKING, 0);if (ret <= 0) {cout << "open audit fail:" << strerror(errno) << endl;}printf("%s %s", __FUNCTION__, audit_rep.msg.data);cout << audit_rep.msg.data << endl;} while(true);return 0;
}
5 audit存在的问题
如果只是正常使用audit:配置audit规则,查看审计日志,也没啥问题,但是,实际使用过程中,还是存在一些问题。
5.1 内核版本
不同版本的内核在实现机制上有所不同,因此,运行表现和参数控制上也有所不同:
- 小于3.14的内核没有提供设置backlog_wait_time的接口
5.2 审计日志过多造成的缓存队列和磁盘问题
audit_log_end将审计日志放到audit_queue的队尾,如果审计日志较多,可能会导致队列很长,占用的资源增多,因此,内核也提供了一些参数进行控制:
- backlog_limit:缓存队列长度限制
- backlog_wait_time:缓存队列满的等待时间
// audit_log_start(linux-4.19.281)// auditd_test_task:检查当前进程是否是audit daemon进程// audit_ctl_owner_current:检查当前进程是否持有audit_cmd_mutex锁// 因此,这里进入if的条件是:当前进程不是audit daemon进程,并且没有持有锁if (!(auditd_test_task(current) || audit_ctl_owner_current())) {// 获取audit_backlog_wait_time,就是auditctl -s中的backlog_wait_timelong stime = audit_backlog_wait_time;// audit_backlog_limit就是auditctl -s中的backlog_limit,默认值是64// 因此,这里进入while的条件是:设置了backlog_limit,并且当前缓存队列的长度大于backlog_limitwhile (audit_backlog_limit &&(skb_queue_len(&audit_queue) > audit_backlog_limit)) {// 唤醒kauditd处理队列中的日志wake_up_interruptible(&kauditd_wait);/* sleep if we are allowed and we haven't exhausted our* backlog wait limit */// 如果当前进程允许休眠,并且backlog_wait_time大于0,则进入if,backlog_wait_time默认是60sif (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) {// 创建等待队列的节点DECLARE_WAITQUEUE(wait, current);// 将刚才创建的等待队列的节点wait加入到队列audit_backlog_wait中add_wait_queue_exclusive(&audit_backlog_wait,&wait);set_current_state(TASK_UNINTERRUPTIBLE);// 让当前进程休眠一段时间stime = schedule_timeout(stime);// 将wait从audit_backlog_wait队列中移除remove_wait_queue(&audit_backlog_wait, &wait);} else {// 如果当前进程没有休眠,则先检查审计日志的生成速度是否超过rate_limitif (audit_rate_check() && printk_ratelimit())pr_warn("audit_backlog=%d > audit_backlog_limit=%d\n",skb_queue_len(&audit_queue),audit_backlog_limit);// lost自增1,并在审计日志中打印缓存队列超过限制audit_log_lost("backlog limit exceeded");return NULL;}}}
从上面的代码可以看出,当队列长度超过backlog_limit时,内核会休眠一段时间backlog_wait_time(默认60秒),如果backlog_limit为0,则不会休眠,而是会打印backlog limit exceeded日志。
因此,如果backlog_wait_time不为0,而日志太多时,可能导致内核频繁休眠,极端情况下,系统直接卡死。
如果要解决这个问题,可以从几个方面入手:
- 审计规则尽可能只配置必要的,防止生成大量无用的审计日志
- 根据机器配置增加backlog_limit,例如,将backlog_limit可以设置为8193或者更大
- backlog_wait_time设置为0,当日志过多时直接丢弃,防止影响日常的使用
- 审计日志的消费者尽可能快速消费日志,可能的情况下,可以增加丢弃策略,防止审计日志堆积
当审计日志过多,还会造成磁盘占用率的问题:当审计日志太多,可能会占用大量磁盘空间。
需要注意的是,即使没有配置审计规则,日志中也可能有审计日志,pam认证、服务启动等,在没有规则的情况下内核也会生成审计日志。
同时,从3.16.0开始,内核增加了多消费者,允许多个进程同时读取审计日志,那么,如果存在其他进程也读取审计然后写到日志文件的话,磁盘占用的问题又会放大,因此,对于磁盘占用的问题,可以从以下几个方面入手:
- 是否有其他进程也读取了审计日志
- 在没有配置审计规则的情况下是否也会产生大量日志
5.2 容器环境下同一个命令的日志存在差异
在容器环境下,同一个命令的日志可能存在差异,因为命令的实现有所不同,比较典型的是,有些镜像的vi是重定向到busybox,有些则是跟主机一样的二进制文件,那么他们产生的日志就不同,就会造成分析上的困难。
6 参考文档
- RHEL Audit System Reference
- 读懂audit日志
- Audit framework
相关文章:

【安全】linux audit审计使用入门
文章目录 1 audit简介2 auditctl的使用2 audit配置和规则3 工作原理4 audit接口调用4.1 获取和修改配置4.2 获取和修改规则4.3 获取审计日志 5 audit存在的问题5.1 内核版本5.2 审计日志过多造成的缓存队列和磁盘问题5.2 容器环境下同一个命令的日志存在差异 6 参考文档 1 audi…...

如何优雅的终止 Docker 容器
init 系统有以下几个特点: 它是系统的第一个进程,负责产生其他所有用户进程。 init 以守护进程方式存在,是所有其他进程的祖先。 它主要负责: 启动守护进程 回收孤儿进程 将操作系统信号转发给子进程 1. Docker 容器停止过程…...

SXSSFWorkbook-MinIo-大数据-流式导出
文章目录 前言业务现状架构思路技术细节生成摘要IDSXSSFWorkbookMinIomybatis 流查询PipedInputStream 保存到minio 总结 前言 由于业务涉及到数据比较大,用户对导出功能使用频繁,每次导出数据两10万以上。 为了减少数据库压力,及应用服务器…...

使用PyQt5创建图片查看器应用程序
使用PyQt5创建图片查看器应用程序 作者:安静到无声 个人主页 在本教程中,我们将使用PyQt5库创建一个简单的图片查看器应用程序。这个应用程序可以显示一系列图片,并允许用户通过按钮切换、跳转到不同的图片。 1. 准备工作 首先࿰…...

怎样制作一个展会场馆预约小程序
随着互联网的发展,展会行业也逐渐向数字化转型。展会场馆预约小程序作为展会线下向线上的延伸,能够让参展商和观众随时随地进行预约,大大提升了客户的体验。那么,如何制作一个展会场馆预约小程序呢?下面就以乔拓云平台…...

呼叫中心系统信息发送功能的应用
通常情况下功能比较齐全的呼叫中心系统都会有短信功能,那么短信功能在呼叫中心职场中有哪些应用呢? 呼叫中心系统中短信功能主要分为三部分:短信发送、待发送短信、短信发件箱,先来简单了解一下这三个功能在工作中如何使用。 短信…...

Android笔记(三)多Activity活动的切换中的简化处理
多Activity实现的跳转简单实现 Activity定义移动的界面。在本例中,介绍多个活动之间的切换的简化通用的实现。在本例中,定义三个活动MainActivity、FirstActivity和SecondActivity.要求能从MainActivity分别切换到FirstActivity和SecondActivity&#x…...

vue打包压缩
参考 https://www.cnblogs.com/lafitewu/p/8309305.html 注意:方法1和方法2不能同时用 取消打包的map config/index.js的productionSourceMap设置为false 抽取js 将部分常用又比较大的组件直接抽取为一个单独的js 打开webpack.base.conf.js,在module.exports.entry中添加想…...

Mysql5.7大限将至升级Mysql 8.0过程记录(未完)
一、前言 时间很快,到2023年10月底,MySQL 5.7就到了它的EOL(End of Life),届时将不会提供任何补丁,无法应对潜在的安全风险;是时候和 MySQL 5.7 说再见了!!!&…...

多架构环境下docker-compose部署rocketmq单机模式—— 筑梦之路
接上篇linux上构建任意版本的rocketmq多架构x86 arm镜像——筑梦之路-CSDN博客,本文适用于x86、arm等多架构环境。 话不多说,直接上代码。 准备broker配置文件 #broker配置文件示例 cat data/broker/conf/broker.conf brokerClusterName DefaultClus…...

[Unity][VR]Passthrough2-创建一个基本的Passthrough应用
上一期我们对PassthroughXR项目做好了基本的项目设置,今天我们就开始构建一个基本的Passthrough应用。 我们还是从基本场景开始。先把默认的main camera删除。因为后续我们会引入OVR Rig对象,这个对象自带Camera用来实现VR视角。 在Project面板我们搜索OVR camera rig。看见…...

【Unity3D赛车游戏制作】设置面板搭建——UGUI复合控件
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:Uni…...

如何让 Source Insight 识别 AUTOSAR 宏定义 FUNC
有很多从事汽车电子行业的软件工程师在使用Source Insight阅览Classic AUTOSAR协议栈源码的时候, 发现函数名无法解析,基本上都变成了FUNC。 先说原因: AUTOSAR的协议栈为了实现多平台和编译器兼容,大量使用宏定义来代替关键字。…...

sts搭建springboot
sts搭建springboot 需要的软件 Apache-maven-3.3.9.rar 链接:百度网盘 请输入提取码 提取码:1xgj Spring-tool-suite-4-4.20.0.RELEASE-e4.29.0-win32.win32.x86_64.self-extracting.jar 链接:百度网盘 请输入提取码 提取码:p…...

解决react使用css module无法重写bootstrap样式的问题
react使用css module虽然能够解决样式污染,但是同时也失去了写css样式的灵活性,特别是:在.module.css文件中当子元素是非变量的静态class类(比如bootstrap), 此时使用css选择器对该子元素的样式不会起作用的 比如下面…...

自动驾驶软件和人工智能
自动驾驶汽车的核心在于其软件系统,而其中的机器学习和深度学习技术是使车辆能够感知、理解、决策和行动的关键。本文将深入探讨这些技术在自动驾驶中的应用,包括感知、定位、路径规划以及道路标志和交通信号的识别。 1. 机器学习和深度学习在自动驾驶中…...

堆叠、集群技术
1.堆叠、集群技术的概述 堆叠、集群简介 堆叠(iStack),将多台支持堆叠特性的交换机通过堆叠线缆连接在一起,从逻辑上虚拟成一台交换设备,作为一个整体参与数据转发。 集群(Cluster Switch System…...

SpringCould微服务保护01——Sentinel组件下载并使用
1.初识Sentinel 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 微服务中,服务间调用关系错综复杂,一个微服务往往依赖于多个其它微服务。 如图,如果服务提供者I发生了故障,当前的应用的部分业务因为依赖于服务I,因此也会被…...

可扩展性对物联网管理系统有哪些影响?
可扩展性对于物联网管理系统的设计和开发非常重要,它直接影响着系统的性能、可靠性和能耗等方面,是评估一个系统优劣的重要因素之一。可扩展性对物联网管理系统的影响主要体现在以下几个方面: 设备兼容性:物联网管理系统的可扩展性…...

洗地机哪个品牌最耐用质量好?2023年最好用的洗地机
随着科技的发展,人们的生活越来越便利,就拿打扫卫生来说,现在越来越多人抛弃扫把、地拖,转而选择让清洁更加轻松的清洁家电,而洗地机就是这样一种让打扫卫生变得简单轻松的家电。近年来洗地机销量剧增,是目…...

计算机视觉(Computer Vision, CV)是什么?
什么是计算机视觉 近年来,计算机视觉 (Computer Vision,简称CV) 不断普及,已成为人工智能 (AI) 增长最快的领域之一。计算机视觉致力于使计算机能够识别和理解图像和视频中的物体和人。 计算机视觉应用程序使用来自传感设备、人工智能、机器…...

【【萌新的SOC学习之自定义IP核 AXI4接口】】
萌新的SOC学习之自定义IP核 AXI4接口 自定义IP核-AXI4接口 AXI接口时序 对于一个读数据信号 AXI突发读 不要忘记 最后还有拉高RLAST 表示信号的中止 实验任务 : 通过自定义一个AXI4接口的IP核 ,通过AXI_HP接口对PS端 DDR3 进行读写测试 。 S_AXI…...

设计模式-创建型模式
文章目录 一、单例模式1.饿汉式(1) 静态变量(2) 静态代码块(3) 枚举方式 2.懒汉式(1) 双检锁(2) 静态内部类 3.破坏单例模式(1) 序列化(2) 反射 4.解决单例模式被破坏(1) 序列化、反序列化破坏单例模式的解决方法(2) 反射破坏单例解决 二、工厂方法模式1.简单工厂模式2.工厂方法…...

golang中的RSA算法,加密解密,签名校验,导出公钥密钥,导入公钥密钥
RSA算法广泛应用与数据加密(比如 SSL 传输层加密),数字签名(比如支付宝的支付签名)。 1、加密解密 // encrypts the given message with RSA-OAEP func f1() {// random 用来生成随机的素数rsaPriviteKey, err : rsa…...

修炼k8s+flink+hdfs+dlink(四:k8s(二)组件)
一:控制平面组件。 控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的 replicas 字段时, 要启动新的 pod)。 1. kube-apiserver。 该组件负责公开了 Kubernetes API&a…...
Android约束布局ConstraintLayout流式Flow
Android约束布局ConstraintLayout流式Flow <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.…...

Android JNI代码语法解释
文章目录 JNI中的JNIEXPORT、JNIIMPORT和JNICALLJVM如何查找native方法①按照JNI规范的命名规则②调用JNI提供的RegsterNatives函数,将本地函数注册到JVM中示例代码 JNI数据类型JNI字符串的处理①获取字符串②释放字符串③创建字符串④其他字符串处理API JNI中的JNI…...

小程序和前台开发软件定制的相关信息|APP网站搭建
小程序和前台开发软件定制的相关信息 在如今数字化时代,软件、小程序和前台开发软件定制已经成为了企业必备的工具之一。那么,这些工具到底有什么作用呢?接下来,我将为大家详细介绍。 首先,让我们来了解一下软件。软件…...

JVM监控及诊断工具-GUI篇
文章目录 JVM监控及诊断工具-GUI篇工具概述JConsoleVisual VM再谈内存泄漏Java中内存泄漏的8种情况Arthas(阿尔萨斯)康师傅使用阿尔萨斯的例子help指令 JVM监控及诊断工具-GUI篇 工具概述 使用上一章命令行工具或组合能获取目标Java应用性能相关的基础…...

【C++STL基础入门】list基本使用
文章目录 前言一、list简介1.1 list是什么1.2 list的头文件 二、list2.1 定义对象2.2 list构造函数2.3 list的属性函数 总结 前言 STL(Standard Template Library)是C标准库的一个重要组成部分,提供了一套丰富的数据结构和算法,可…...