Android 12 S 系统开机流程分析 - SetupSelinux(二)
Android 12 S 系统开机流程分析-FirstStageMain(一)
本文接着上文开始讲解,上文中最后一步执行后会执行init启动过程中的第二步SetupSelinux(Selinux配置阶段),这样又会走到main.cpp中的main方法。
目录
1. SetupSelinux
1.1 初始化kernel log系统
1.2 ReadPolicy
1.3 加载策略
1.4 使能/关闭Selinux并写入节点
1.5 selinux_android_restorecon
1.6 重新执行init进程并携带参数second_stage
1. SetupSelinux
由于上一篇中最后一步在重新执行init的时候携带了参数selinux_setup,所以此处会走入SetupSelinux方法,加载selinux的策略。
SetupSelinux主要功能:
1)open sepolicy
2)load sepolicy
3)使能/关闭selinux
int main(int argc, char** argv) {
...if (!strcmp(argv[1], "selinux_setup")) {
//执行此处return SetupSelinux(argv);}if (!strcmp(argv[1], "second_stage")) {return SecondStageMain(argc, argv);}}return FirstStageMain(argc, argv);
}
1.1 初始化kernel log系统
1)初始化kernel log
2)若系统发生了panic,则走InstallRebootSignalHandlers
InstallRebootSignalHandlers中主要做了以下几件事:
1. 初始化了一个自定义信号集,将其所有信号都填充满,即将信号集中的所有的标志位都置为1,使得这个集合包含所有可接受的信号,也就是阻塞所有信号。这个函数可以用于快速创建一个包含所有信号的信号集,然后可以根据需要删除其中的某些信号。
2. init创建出来的子进程不做处理,直接exit;如果不是子进程,则代表是init进程,则执行InitFatalReboot
3. 通过syscall向内核发送重启命令
4. 捕获一些信号
int SetupSelinux(char** argv) {SetStdioToDevNull(argv);InitKernelLogging(argv);if (REBOOT_BOOTLOADER_ON_PANIC) {InstallRebootSignalHandlers();}boot_clock::time_point start_time = boot_clock::now();
//这是R上为了R system.img/system_ext.img作为system_ext.img工作在old vendor.img上。
//我们在init第二阶段挂载system_ext,因为在system-only OTA场景中boot.img的init第一阶段是不会被更新的。MountMissingSystemPartitions();SelinuxSetupKernelLogging();LOG(INFO) << "Opening SELinux policy";
SelinuxGetVendorAndroidVersion主要作用是读/vendor/etc/selinux/plat_sepolicy_vers.txt中的第一行,获取Selinux vendor version。
int SelinuxGetVendorAndroidVersion() {static int vendor_android_version = [] {if (!IsSplitPolicyDevice()) {
//如果这个设备不拆分sepolicy文件,它就不是一个Treble设备return __ANDROID_API_FUTURE__;}std::string version;
//获取vendor Selinux version
//读/vendor/etc/selinux/plat_sepolicy_vers.txt中的第一行
//可以adb看下vendor版本:
//adb shell cat /vendor/etc/selinux/plat_sepolicy_vers.txt
//32.0if (!GetVendorMappingVersion(&version)) {LOG(FATAL) << "Could not read vendor SELinux version";}
//解析version值,version一般是带小数点的,比如32.0。int major_version;std::string major_version_str(version, 0, version.find('.'));if (!ParseInt(major_version_str, &major_version)) {PLOG(FATAL) << "Failed to parse the vendor sepolicy major version "<< major_version_str;}
//返回version中整数return major_version;}();return vendor_android_version;
}
1.2 ReadPolicy
ReadPolicy主要做了两件事
1)open split policy
2)读sepolicy
这个是SetupSelinux的主要功能之一。
// Read the policy before potentially killing snapuserd.std::string policy;ReadPolicy(&policy);auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();if (snapuserd_helper) {// Kill the old snapused to avoid audit messages. After this we cannot// read from /system (or other dynamic partitions) until we call// FinishTransition().snapuserd_helper->StartTransition();}
ReadPolicy的主要功能是:
如果设备中存在/system/etc/selinux/plat_sepolicy.cil文件,并可以访问,则IsSplitPolicyDevice为true,会走OpenSplitPolicy流程,这个设备中默认都有这个文件的。
void ReadPolicy(std::string* policy) {PolicyFile policy_file;
//constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";//bool IsSplitPolicyDevice() {
// return access(plat_policy_cil_file, R_OK) != -1;
//}
//IsSplitPolicyDevice如上,如果能访问设备中的/system/etc/selinux/plat_sepolicy.cil文件,
//则IsSplitPolicyDevice为true,会走OpenSplitPolicybool ok = IsSplitPolicyDevice() ? OpenSplitPolicy(&policy_file): OpenMonolithicPolicy(&policy_file);if (!ok) {LOG(FATAL) << "Unable to open SELinux policy";}if (!android::base::ReadFdToString(policy_file.fd, policy)) {PLOG(FATAL) << "Failed to read policy file: " << policy_file.path;}
}
OpenSplitPolicy的主要功能是:
1)如果设备是userdebug版本+设备unlock+存在/debug_ramdisk/adb_debug.prop并且可以访问,则加载userdebug system sepolicy
2)从代码看是access system,vendor,system_ext和vendor下etc/selinux/mapping/下的.cil文件
3)再查看对应目录下的.cil文件内容是否为空,不为空则将对应目录下的.cil文件内容push进compile_args
4)执行compile_args并等待,决定include哪个mapping下的.cil文件5)将临时文件/dev/sepolicy.XXXXXX的fd和path保存进policy_file->fd和 policy_file->path。
bool OpenSplitPolicy(PolicyFile* policy_file) {
//若存在/force_debuggable,则在init启动第一阶段,force_debuggable_env 环境变量已经设置好了
//setenv("INIT_FORCE_DEBUGGABLE", "true", 1);const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
//是userdebug版本+设备unlock+存在/debug_ramdisk/adb_debug.prop并且可以访问,
//则加载userdebug system sepolicybool use_userdebug_policy =((force_debuggable_env && "true"s == force_debuggable_env) &&AvbHandle::IsDeviceUnlocked() && access(kDebugRamdiskSEPolicy, F_OK) == 0);if (use_userdebug_policy) {LOG(WARNING) << "Using userdebug system sepolicy";}if (!use_userdebug_policy) {if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));if (fd != -1) {policy_file->fd = std::move(fd);policy_file->path = std::move(*res);return true;}} else {LOG(INFO) << res.error();}}// No suitable precompiled policy could be loaded
//没有合适的策略可以加载LOG(INFO) << "Compiling SELinux policy";// We store the output of the compilation on /dev because this is the most convenient tmpfs// storage mount available this early in the boot sequence.char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
//mkostemp:创建临时文件
//创建临时文件/dev/sepolicy.XXXXXX,其fd为compiled_sepolicy_fdunique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));if (compiled_sepolicy_fd < 0) {PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;return false;}
...
//从代码看是access system,vendor,system_ext和vendor下etc/selinux/mapping/下的.cil文件
//再查看对应目录下的.cil文件内容是否为空,不为空则将对应目录下的.cil文件内容push进compile_args
//执行compile_args并等待
//将临时文件/dev/sepolicy.XXXXXX的fd和path保存进policy_file->fd和 policy_file->path。
//决定include哪个mapping下的.cil文件std::string vend_plat_vers;if (!GetVendorMappingVersion(&vend_plat_vers)) {return false;}std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");std::string plat_compat_cil_file("/system/etc/selinux/mapping/" + vend_plat_vers +".compat.cil");if (access(plat_compat_cil_file.c_str(), F_OK) == -1) {plat_compat_cil_file.clear();}std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {system_ext_policy_cil_file.clear();}std::string system_ext_mapping_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +".cil");if (access(system_ext_mapping_file.c_str(), F_OK) == -1) {system_ext_mapping_file.clear();}std::string system_ext_compat_cil_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +".compat.cil");if (access(system_ext_compat_cil_file.c_str(), F_OK) == -1) {system_ext_compat_cil_file.clear();}std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");if (access(product_policy_cil_file.c_str(), F_OK) == -1) {product_policy_cil_file.clear();}std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");if (access(product_mapping_file.c_str(), F_OK) == -1) {product_mapping_file.clear();}// vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace// nonplat_sepolicy.cil.std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {// For backward compatibility.// TODO: remove this after no device is using nonplat_sepolicy.cil.vendor_policy_cil_file = "/vendor/etc/selinux/nonplat_sepolicy.cil";plat_pub_versioned_cil_file.clear();} else if (access(plat_pub_versioned_cil_file.c_str(), F_OK) == -1) {LOG(ERROR) << "Missing " << plat_pub_versioned_cil_file;return false;}// odm_sepolicy.cil is default but optional.std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {odm_policy_cil_file.clear();}const std::string version_as_string = std::to_string(SEPOLICY_VERSION);//有一些代码,我们并不想让clang-format调整格式,这时可以使用注释临时禁用clang-format// clang-format offstd::vector<const char*> compile_args {"/system/bin/secilc",use_userdebug_policy ? kDebugRamdiskSEPolicy: plat_policy_cil_file,"-m", "-M", "true", "-G", "-N","-c", version_as_string.c_str(),plat_mapping_file.c_str(),"-o", compiled_sepolicy,// We don't care about file_contexts output by the compiler"-f", "/sys/fs/selinux/null", // /dev/null is not yet available};// clang-format on//将对应目录下的.cil文件内容push进compile_argsif (!plat_compat_cil_file.empty()) {compile_args.push_back(plat_compat_cil_file.c_str());}if (!system_ext_policy_cil_file.empty()) {compile_args.push_back(system_ext_policy_cil_file.c_str());}if (!system_ext_mapping_file.empty()) {compile_args.push_back(system_ext_mapping_file.c_str());}if (!system_ext_compat_cil_file.empty()) {compile_args.push_back(system_ext_compat_cil_file.c_str());}if (!product_policy_cil_file.empty()) {compile_args.push_back(product_policy_cil_file.c_str());}if (!product_mapping_file.empty()) {compile_args.push_back(product_mapping_file.c_str());}if (!plat_pub_versioned_cil_file.empty()) {compile_args.push_back(plat_pub_versioned_cil_file.c_str());}if (!vendor_policy_cil_file.empty()) {compile_args.push_back(vendor_policy_cil_file.c_str());}if (!odm_policy_cil_file.empty()) {compile_args.push_back(odm_policy_cil_file.c_str());}compile_args.push_back(nullptr);
//执行compile_args并等待if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {unlink(compiled_sepolicy);return false;}unlink(compiled_sepolicy);
//将临时文件/dev/sepolicy.XXXXXX的fd和path保存进policy_file->fd和 policy_file->path。policy_file->fd = std::move(compiled_sepolicy_fd);policy_file->path = compiled_sepolicy;return true;
}
1.3 加载策略
这也是SetupSelinux中最重要的功能之一。
LoadSelinuxPolicy(policy);
上一节中对policy进行了赋值。
static void LoadSelinuxPolicy(std::string& policy) {LOG(INFO) << "Loading SELinux policy";set_selinuxmnt("/sys/fs/selinux");if (security_load_policy(policy.data(), policy.size()) < 0) {PLOG(FATAL) << "SELinux: Could not load policy";}
}
security_load_policy主要功能是:
1)open $selinux_mnt/load,获取其对应fd
2)根据fd将/dev/sepolicy.XXXXXX中的内容写入$selinux_mnt/load中。selinux_mnt如下#define SELINUXMNT "/sys/fs/selinux"
external/selinux/libselinux/src/load_policy.c
int security_load_policy(void *data, size_t len)
{char path[PATH_MAX];int fd, ret;if (!selinux_mnt) {errno = ENOENT;return -1;}snprintf(path, sizeof path, "%s/load", selinux_mnt);fd = open(path, O_RDWR | O_CLOEXEC);if (fd < 0)return -1;ret = write(fd, data, len);close(fd);if (ret < 0)return -1;return 0;
}
1.4 使能/关闭Selinux并写入节点
获取selinux状态是否是enforce,然后将selinux状态is_enforcing写入 $selinux_mnt/enforce中。selinux_mnt如下
#define SELINUXMNT "/sys/fs/selinux"
if (snapuserd_helper) {// Before enforcing, finish the pending snapuserd transition.snapuserd_helper->FinishTransition();snapuserd_helper = nullptr;}SelinuxSetEnforcement();
void SelinuxSetEnforcement() {bool kernel_enforcing = (security_getenforce() == 1);
//check selinux是否是enforce状态(开启selinux)bool is_enforcing = IsEnforcing();if (kernel_enforcing != is_enforcing) {if (security_setenforce(is_enforcing)) {PLOG(FATAL) << "security_setenforce(" << (is_enforcing ? "true" : "false")<< ") failed";}}if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result.ok()) {LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();}
}
bool IsEnforcing() {
//如果关闭系统的selinux,即将selinux置为permissive,此处直接返回false即可
//return false;if (ALLOW_PERMISSIVE_SELINUX) {return StatusFromProperty() == SELINUX_ENFORCING;}return true;
}
/external/selinux/libselinux/src/setenforce.c
int security_setenforce(int value)
{int fd, ret;char path[PATH_MAX];char buf[20];if (!selinux_mnt) {errno = ENOENT;return -1;}snprintf(path, sizeof path, "%s/enforce", selinux_mnt);fd = open(path, O_RDWR | O_CLOEXEC);if (fd < 0)return -1;snprintf(buf, sizeof buf, "%d", value);ret = write(fd, buf, strlen(buf));close(fd);if (ret < 0)return -1;return 0;
}
1.5 selinux_android_restorecon
从kernel domain域过渡到init domain域
文件系统在xattrs中存储了SELabels,比如ext4不需要restorecon,但其他文件系统需要
//从kernel domain域过渡到init domain域
//文件系统在xattrs中存储了SELabels,比如ext4不需要restorecon,但其他文件系统需要if (selinux_android_restorecon("/system/bin/init", 0) == -1) {PLOG(FATAL) << "restorecon failed of /system/bin/init failed";}
1.6 重新执行init进程并携带参数second_stage
setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);const char* path = "/system/bin/init";const char* args[] = {path, "second_stage", nullptr};execv(path, const_cast<char**>(args));// execv() only returns if an error happened, in which case we// panic and never return from this function.PLOG(FATAL) << "execv(\"" << path << "\") failed";return 1;
}
到了SetupSelinux的最后一步,这一步还是重新执行/system/bin/init,这样就会再次走init bin程序的main函数,由代码可以看到,此次携带了参数second_stage。
后面接着讲启动流程
相关文章:
Android 12 S 系统开机流程分析 - SetupSelinux(二)
Android 12 S 系统开机流程分析-FirstStageMain(一) 本文接着上文开始讲解,上文中最后一步执行后会执行init启动过程中的第二步SetupSelinux(Selinux配置阶段),这样又会走到main.cpp中的main方法。 目录 1. SetupSelinux 1.1 …...
高速信号PCB布局怎么布?(电子硬件)
对于高速信号,pcb的设计要求会更多,因为高速信号很容易收到其他外在因素的干扰,导致实际设计出来的东西和原本预期的效果相差很多。 所以在高速信号pcb设计中,需要提前考虑好整体的布局布线,良好的布局可以很好的决定布…...
vue 子页面通过暴露属性,实现主页面的某事件的触发
目录 1.前言2.代码2-1 子页面2-2 主页面 1.前言 需求:当我在子页面定义了一个定时器,点击获取验证码,计时器开始倒计时,在这个定时器没有走完,退出关闭子页面,再次进入子页面,定时器此时会被刷…...
计算机丢失mfc140.dll是什么意思?附送修复教程
mfc140.dll是Microsoft Foundation Classes(MFC)库的一部分,是一种动态链接库(DLL)文件。MFC库是Microsoft提供的一种C编程框架,它为开发者提供了许多方便的工具和类,以简化Windows应用程序的开…...
R语言将向量横向转换为单行数据框,随后整合数量不确定的数据框
vector1 c(1, “karthik”, “IT”) names(vector1) c(“id”, “name”, “branch”) df data.frame(as.list(vector1)) print(df) 先给向量的元素命名,然后转换为列表,最后转换为数据框。 我的需求大概是这个样子:数量不确定的仅有单行…...
怎么测试websocket接口
在部分业务中,我们需要使用长连接,我们可以使用http长连接或者websocket,开发结束后难免会遇到测试问题,这里推荐2个,一个是postman,一个是网站 postman 测试网站 测这边推荐测试网站,支持ws/w…...
21 移动网络的前世今生
1、移动网络的发展历程 发展过程就是:2G,3G,4G,5G的过程,用2G看txt,用3G看jpg,用4G看avi。 2、2G网络 手机本来是用来打电话的,不是用来上网的,所以原来在2G时代,上网使用的不是IP网络&#…...
里氏替换原则
定义:子类对象能够替换程序中父类对象出现的任何地方,并且*保证原来程序的逻辑行为不变及正确性不被破坏*。 public class Transporter {private HttpClient httpClient;public Transporter(HttpClient httpClient) {this.httpClient httpClient;}public Response…...
【JS】Chapter11-正则阶段案例
站在巨人的肩膀上 黑马程序员前端JavaScript入门到精通全套视频教程,javascript核心进阶ES6语法、API、js高级等基础知识和实战教程 (十一)正则&阶段案例 1. 正则表达式 1.1 介绍 正则表达式(Regular Expression࿰…...
跨时钟域(Clock Domain Crossing,CDC)
本文参考:http://t.csdnimg.cn/VHga2 【数字IC基础】跨时钟域(CDC,Clock Domain Crossing)_ReRrain的博客-CSDN博客 同步设计:所有设计使用同一时钟源,频率相位可预知。 异步设计:设计中有两…...
PTA古风排版
中国的古人写文字,是从右向左竖向排版的。本题就请你编写程序,把一段文字按古风排版。 输入格式: 输入在第一行给出一个正整数N(<100),是每一列的字符数。第二行给出一个长度不超过1000的非空字符串&a…...
SQL 注入漏洞详解
SQL 注入漏洞详解 漏洞描述 sql注入漏洞是指恶意用户在应用与数据库交互的地方利用非法的操作获取数据库内容从以下两点分析: 没有对用户输入的数据进行充分的过滤和验证,导致一些用户利用此漏洞向数据库插入恶意sql语句非法请求数据库从而获得一些敏感数据在与数…...
关于阿里云 ACK ingress部分补充
强调: 本文只是作为记录,过一段时间会删除 跟唐老师学习网络 一 Nginx Ingress管理 ① 流量走向 需求: 应用绑定LoadBalance,会自动创建或使用SLBeip:port --> nodeport_ip:port --> service_ip:port --> pod_ip:port 支持的注解 通过…...
轻量封装WebGPU渲染系统示例<22>- 渲染到纹理(RTT)(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/RTTTest.ts 当前示例运行效果: 此示例基于此渲染系统实现,当前示例TypeScript源码如下: export class RTTTest {private mRscene new RendererScene()…...
官方Redis视图化工具Redisinsight
一、下载最新版本的 docker pull redislabs/redisinsight mkdir /data/redisinsight docker run -d -u root -p 8001:8001 -v /etc/localtime:/etc/localtime -v /data/redisinsight:/db --restartunless-stopped redislabs/redisinsight:latest 二、浏览器打开 http://192…...
Vue+Django REST framework 打造生鲜电商项目课程下载树大根深
VueDjango REST framework 打造生鲜电商项目 链接:https://pan.baidu.com/s/1kEDxPsoTYSVWPYB2H0jbBw?pwd6666 提取码:6666Django是高水准的Python编程语言驱动的一个开源模型.视图,控制器风格的Web应用程序框架,它…...
react中遇到的分页问题
问题: 1.使用useState时不能够进行当前页码的改变,数据不会随着页码变化 2.删除当前页的最后一条数据时,页码返回上一页但是数据为空 解决: 1.由于useState和useRef的区别那我们就不考虑使用useState 2.再删除的逻辑当中添加判断条…...
变电站自动化系统中的安全措施分析及应用-安科瑞
安科瑞电气股份有限公司 上海嘉定 201801 摘要:阐述变电运行中的问题,电气自动化系统与安全运行措施,包括自动控制设备的投入,电气自动 化与计算机技术相、设备数据的采集与处理、自动化系统的升级、人工智能技术的应用。 关键…...
【MongoDB】索引 – 文本索引
一、准备工作 这里准备一些数据 db.books.insertMany([{_id: 1, name: "Java", description: "java 入门图书", translation: [{ language: "english", description: "java basic book" }]},{_id: 2, name: "C", descript…...
【广州华锐互动】影视制作VR在线学习:身临其境,提高学习效率
随着科技的不断发展,影视后期制作技术也在日新月异。然而,传统的教学方式往往难以满足学员的学习需求,无法充分展现影视后期制作的魅力和潜力。近年来,虚拟现实(VR)技术的崛起为教学领域带来了新的机遇。通过VR教学课件࿰…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
