Nginx源码分析 - 主流程篇 - Nginx的启动流程(09)

深入理解Nginx线程池【内附原理讲解以及源码分析】 本篇博客将从什么是并发编程、为什么要使用线程池、线程池的组成以及线程池的使用这4个方面对Nginx线程池进行刨析,相信耐心看完会对您有所帮助。 阅读详情
AI摘要

本文详细解析了Nginx的启动过程,包括ngx_get_options参数解析、init_cycle全局变量初始化、ngx_save_argv和ngx_process_options变量保存方法、ngx_preinit_modules模块初始化以及ngx_create_pidfile PID文件创建等关键步骤。

 

目录

一、Nginx的启动过程

二、重要流程分析

1. ngx_get_options 解析外部参数

2. init_cycle 初始化全局变量

3. 变量保存方法ngx_save_argv和ngx_process_options

4. 给模块打标ngx_preinit_modules

5. 创建PID文件ngx_create_pidfile


前几篇主要介绍了Nginx比较常用的一些基础数据结构,例如pool,buf,array,list等。通过对Nginx基础数据结构的理解,能更好的帮助我们读懂整个Nginx的源代码。

这一章节开始主要分析Nginx的主流程。

Nginx的主流程的实现函数在./src/core/nginx.c文件中。通过main()函数,我们可以窥探整个Nginx启动的流程。

一、Nginx的启动过程


main()函数的启动过程如下:

  1. 调用ngx_get_options方法,主要用于解析命令行中的参数,例如:./nginx -s stop|start|restart
  2. 调用ngx_time_init方法,初始化并更新时间,如全局变量ngx_cached_time
  3. 调用ngx_getpid方法,获取当前进程的pid。一般pid会放在/usr/local/nginx-1.4.7/nginx.pid的文件中,用于发送重启,关闭等信号命令。
  4. 调用ngx_log_init方法,初始化日志,并得到日志的文件句柄ngx_log_file.fd
  5. 初始化init_cycle Nginx的全局变量。在内存池上创建一个默认大小1024的全局变量。这里只是最简单的初始化一个变量。
  6. 调用ngx_save_argv方法,保存Nginx命令行中的参数和变量,放到全局变量ngx_argv
  7. 调用ngx_process_options方法,将ngx_get_options中获得这些参数取值赋值到ngx_cycle中。prefix, conf_prefix, conf_file, conf_param等字段。
  8. 调用ngx_os_init()初始化系统相关变量,如内存页面大小ngx_pagesize,ngx_cacheline_size,最大连接数ngx_max_sockets等
  9. 调用ngx_crc32_table_init方法,初始化一致性hash表,主要作用是加快查询
  10. 调用ngx_add_inherited_sockets方法,ngx_add_inherited_sockets主要是继承了socket的套接字。主要作用是热启动的时候需要平滑过渡
  11. 调用ngx_preinit_modules方法,主要是前置的初始化模块,对模块进行编号处理
  12. 调用ngx_init_cycle方法,完成全局变量cycle的初始化
  13. 调用ngx_signal_process方法,如果有信号,则进入ngx_signal_process方法。例如:例如./nginx -s stop,则处理Nginx的停止信号
  14. 调用ngx_get_conf方法,得到核心模块ngx_core_conf_t的配置文件指针
  15. 调用ngx_create_pidfile方法,创建pid文件。例如:/usr/local/nginx-1.4.7/nginx.pid
  16. 调用ngx_master_process_cycle方法,这函数里面开始真正创建多个Nginx的子进程。这个方法包括子进程创建、事件监听、各种模块运行等都会包含进去

 

二、重要流程分析


1. ngx_get_options 解析外部参数


ngx_get_options方法主要用于解析命令行外部参数。例如:./nginx -s stop|start|restart

    /* 解析外部参数 */
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

 

/**
 * 解析启动命令行中的参数
 * ./nginx -s stop|start|restart
 */
static ngx_int_t
ngx_get_options(int argc, char *const *argv)
{
    u_char     *p;
    ngx_int_t   i;

    for (i = 1; i < argc; i++) {

        p = (u_char *) argv[i];

        if (*p++ != '-') {
            ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
            return NGX_ERROR;
        }

        while (*p) {

            switch (*p++) {

            case '?':
            case 'h':
                ngx_show_version = 1;
                ngx_show_help = 1;
                break;

            case 'v':
                ngx_show_version = 1;
                break;

            case 'V':
                ngx_show_version = 1;
                ngx_show_configure = 1;
                break;

            case 't':
                ngx_test_config = 1;
                break;

            case 'T':
                ngx_test_config = 1;
                ngx_dump_config = 1;
                break;

            case 'q':
                ngx_quiet_mode = 1;
                break;

            case 'p':
                if (*p) {
                    ngx_prefix = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_prefix = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-p\" requires directory name");
                return NGX_ERROR;

            case 'c':
                if (*p) {
                    ngx_conf_file = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_file = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-c\" requires file name");
                return NGX_ERROR;

            case 'g':
                if (*p) {
                    ngx_conf_params = p;
                    goto next;
                }

                if (argv[++i]) {
                    ngx_conf_params = (u_char *) argv[i];
                    goto next;
                }

                ngx_log_stderr(0, "option \"-g\" requires parameter");
                return NGX_ERROR;

            case 's':
                if (*p) {
                    ngx_signal = (char *) p;

                } else if (argv[++i]) {
                    ngx_signal = argv[i];

                } else {
                    ngx_log_stderr(0, "option \"-s\" requires parameter");
                    return NGX_ERROR;
                }

                if (ngx_strcmp(ngx_signal, "stop") == 0
                    || ngx_strcmp(ngx_signal, "quit") == 0
                    || ngx_strcmp(ngx_signal, "reopen") == 0
                    || ngx_strcmp(ngx_signal, "reload") == 0)
                {
                    ngx_process = NGX_PROCESS_SIGNALLER;
                    goto next;
                }

                ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
                return NGX_ERROR;

            default:
                ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
                return NGX_ERROR;
            }
        }

    next:

        continue;
    }

    return NGX_OK;
}

2. init_cycle 初始化全局变量


初始化init_cycle Nginx的全局变量。在内存池上创建一个默认大小1024的全局变量。这里只是最简单的初始化一个变量。

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */
    /* 初始化Nginx的init_cycle */
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    /* 创建内存池 默认大小1024*/
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

真正的初始化在ngx_init_cycle这个函数中。ngx_init_cycle包含了Nginx的全局变量的全部初始化过程,后面会单独开一篇文章讲解。

    /* 完成cycle的初始化工作 */
    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

3. 变量保存方法ngx_save_argv和ngx_process_options


  • ngx_save_argv:保存Nginx命令行中的参数和变量,放到全局变量ngx_argv
  • ngx_process_options:将ngx_get_options中获得这些参数取值赋值到ngx_cycle中。prefix, conf_prefix, conf_file, conf_param等字段。
    /* 保存Nginx命令行中的参数和变量,放到全局变量ngx_argv */
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    /* 将ngx_get_options中获得这些参数取值赋值到ngx_cycle中 */
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

头部的全局变量定义

/**
 * 定义全局变量参数
 */
static ngx_uint_t   ngx_show_help; //是否显示帮助信息
static ngx_uint_t   ngx_show_version; //是否显示版本号
static ngx_uint_t   ngx_show_configure; //是否显示配置信息
static u_char      *ngx_prefix; //Nginx的工作目录
static u_char      *ngx_conf_file; //全局配置文件目录地址
static u_char      *ngx_conf_params; //配置参数
static char        *ngx_signal; //信号
int              ngx_argc; //命令行参数个数
char           **ngx_argv; //命令行参数
char           **ngx_os_argv;
/**
 * 保存Nginx命令行中的参数和变量
 * 放到全局变量ngx_argv
 */
static ngx_int_t
ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
{
#if (NGX_FREEBSD)

    ngx_os_argv = (char **) argv;
    ngx_argc = argc;
    ngx_argv = (char **) argv;

#else
    size_t     len;
    ngx_int_t  i;

    ngx_os_argv = (char **) argv;
    ngx_argc = argc;

    ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
    if (ngx_argv == NULL) {
        return NGX_ERROR;
    }

    for (i = 0; i < argc; i++) {
        len = ngx_strlen(argv[i]) + 1;

        ngx_argv[i] = ngx_alloc(len, cycle->log);
        if (ngx_argv[i] == NULL) {
            return NGX_ERROR;
        }

        (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
    }

    ngx_argv[i] = NULL;

#endif

    ngx_os_environ = environ;

    return NGX_OK;
}
/**
 * 将ngx_get_options中获得这些参数取值赋值到ngx_cycle中
 */
static ngx_int_t
ngx_process_options(ngx_cycle_t *cycle)
{
    u_char  *p;
    size_t   len;

    /* Nginx工作目录 */
    if (ngx_prefix) {
        len = ngx_strlen(ngx_prefix);
        p = ngx_prefix;

        if (len && !ngx_path_separator(p[len - 1])) {
            p = ngx_pnalloc(cycle->pool, len + 1);
            if (p == NULL) {
                return NGX_ERROR;
            }

            ngx_memcpy(p, ngx_prefix, len);
            p[len++] = '/';
        }

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;
        cycle->prefix.len = len;
        cycle->prefix.data = p;

    } else {

#ifndef NGX_PREFIX

        p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
        if (p == NULL) {
            return NGX_ERROR;
        }

        if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
            ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
            return NGX_ERROR;
        }

        len = ngx_strlen(p);

        p[len++] = '/';

        cycle->conf_prefix.len = len;
        cycle->conf_prefix.data = p;
        cycle->prefix.len = len;
        cycle->prefix.data = p;

#else

#ifdef NGX_CONF_PREFIX
        ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
#else
        ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
#endif
        ngx_str_set(&cycle->prefix, NGX_PREFIX);

#endif
    }

    /* 配置文件目录 */
    if (ngx_conf_file) {
        cycle->conf_file.len = ngx_strlen(ngx_conf_file);
        cycle->conf_file.data = ngx_conf_file;

    } else {
        ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
    }

    if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
        return NGX_ERROR;
    }

    for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
         p > cycle->conf_file.data;
         p--)
    {
        if (ngx_path_separator(*p)) {
            cycle->conf_prefix.len = p - ngx_cycle->conf_file.data + 1;
            cycle->conf_prefix.data = ngx_cycle->conf_file.data;
            break;
        }
    }

    /* 配置参数 */
    if (ngx_conf_params) {
        cycle->conf_param.len = ngx_strlen(ngx_conf_params);
        cycle->conf_param.data = ngx_conf_params;
    }

    if (ngx_test_config) {
        cycle->log->log_level = NGX_LOG_INFO;
    }

    return NGX_OK;
}

4. 给模块打标ngx_preinit_modules


ngx_preinit_modules方法主要初始化所有模块;并对所有模块进行编号处理;

    /* 初始化所有模块;并对所有模块进行编号处理;
     * ngx_modules数却是在自动编译的时候生成的,位于objs/ngx_modules.c文件中   */
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

ngx_module.c

/**
 * 初始化所有模块;并对所有模块进行编号处理;
 */
ngx_int_t
ngx_preinit_modules(void)
{
    ngx_uint_t  i;

    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = i;
        ngx_modules[i]->name = ngx_module_names[i];
    }

    ngx_modules_n = i;
    ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;

    return NGX_OK;
}

5. 创建PID文件ngx_create_pidfile


ngx_create_pidfile创建PID文件

    /* 创建PID文件 */
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

ngx_cycle.c

/**
 * 创建PID的文件
 */
ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{
    size_t      len;
    ngx_uint_t  create;
    ngx_file_t  file;
    u_char      pid[NGX_INT64_LEN + 2];

    if (ngx_process > NGX_PROCESS_MASTER) {
        return NGX_OK;
    }

    ngx_memzero(&file, sizeof(ngx_file_t));

    file.name = *name;
    file.log = log;

    create = ngx_test_config ? NGX_FILE_CREATE_OR_OPEN : NGX_FILE_TRUNCATE;

    file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR,
                            create, NGX_FILE_DEFAULT_ACCESS);

    if (file.fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", file.name.data);
        return NGX_ERROR;
    }

    if (!ngx_test_config) {
        len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;

        if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
            return NGX_ERROR;
        }
    }

    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", file.name.data);
    }

    return NGX_OK;
}

其它重要模块

下面的模块都会新开文章具体详细解析:

  • ngx_add_inherited_sockets 继承Socket文件句柄
  • ngx_init_cycle 全局配置文件cycle详解
  • ngx_signal_process 信号的处理机制
  • ngx_master_process_cycle 多进程循环机制
Nginx底层设计与源码分析(未完) Nginx(发音为“engine-x”)是一个免费、开源、高性能的Web服务器和反向代理软件。它被开发用于处理高流量网站并作为负载均衡器、内容缓存和Web服务器。Nginx旨在轻巧高效,专注于可伸缩性和性能。它采用事件驱动、异步、非阻塞的架构,能高效地同时处理多个连接。这使它成为高流量网站和应用程序的热门选择。Nginx可用于提供静态文件,也可将请求代理到其他Web服务器,如Apache或Tomcat。它还可以用作负载均衡器,将传入流量分布到多个服务器上。 阅读详情

相关推荐

nginx源码分析 (信号机制)

这篇文章讲解nginx的信号机制,因为是信号,所以其他方面的没有深究,放在后面分享出来,欢迎有兴趣的朋友留言交流 nginx运行的进程模式为master-worker的话,那master和worker进程间是通过信号来通信,关于信号相关的知识可以参考下面的链接Linux信号(signal) 机制分析 下面讲解代码执行流程都是以quit命令来执行的 一、信号的安装 nginx启动的过程中,m...

pythonluo的专栏 732

Nginx源码分析(25篇)

Nginx源码分析 - 初探Nginx的架构 Nginx源码分析 - 基础数据结构篇 - 内存池 ngx_palloc.c Nginx源码分析 - 基础数据结构篇 - 数组结构 ngx_array.c Nginx源码分析 - 基础数据结构篇 - 缓冲区结构 ngx_buf.c Nginx源码分析 - 基础数据结构篇 - 双向链表结构 ngx_queue.c Nginx源码分析 ......

奇华资料的博客 9万+

nginx源码分析—启动流程

作者:阿波 本文链接:http://blog.youkuaiyun.com/livelylittlefish/article/details/7243718 Content 0. 序 1. main()分析 2. 注意问题 2.1 几个初值 2.2 nginx工作模式 2.3 一些配置 2.4 其他开关 3. 小结 0. 序 本文主要分析nginx主程序。 nginx主程序mai

学习,思考,记录,分享。 3万+

Nginx学习(5)—— 基本结构(源码)

可以看到,Nginx自定义了一个带有长度的字符串结构。这意味着,data所指向的字符串并不是以 “\0” 结束的。:对src按照type方式编码,结果放到dst中。如果dst传NULL可获得结果的空间大小。:将src的前n个字符转换成小写存放到dst字符串中。:将结果放到dst中,需要保证dst有足够的空间存放结果。:log为后续在该pool上进行操作时输出日志的对象。:dst传NULL返回结果占用空间大小。:dst传NULL返回结果占用空间大小。

Stars____的博客 1424

Nginx源码分析 - Nginx启动以及IOCP模型

Nginx 源码分析 - Nginx启动以及IOCP模型版本及平台信息本文档针对Nginx1.11.7版本,分析Windows下的相关代码,虽然服务器可能用linux更多,但是windows平台下的代码也基本相似 ,另外windows的IOCP完成端口,异步IO模型非常优秀,很值得一看。Nginx启动曾经有朋友问我,面对一个大项目的源代码,应该从何读起呢?我给他举了一个例子,我们学校大一大二是在紫

InsZVA的专栏 7640

【Nginx 源码学习】Nginx 架构设计与主流程分析

Java架构进阶面试及知识点文档笔记这份文档共498页,其中包括Java集合,并发编程,JVM,Dubbo,Redis,Spring全家桶,MySQL,Kafka等面试解析及知识点整理Java分布式高级面试问题解析文档其中都是包括分布式的面试问题解析,内容有分布式消息队列,Redis缓存,分库分表,微服务架构,分布式高可用,读写分离等等!互联网Java程序员面试必备问题解析及文档学习笔记Java架构进阶视频解析合集《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》

2301_82242204的博客 612

nginx启动流程详解

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> ...

爱宝贝丶的博客 585

Anolis OS 23实战:5分钟搞定AI环境配置(含NVIDIA驱动一键安装)

本文详细介绍了如何在Anolis OS 23上快速配置AI开发环境,包括NVIDIA驱动的一键安装和TensorFlow、PyTorch等AI框架的部署。通过智能硬件适配引擎和优化后的二进制包,用户可在5分钟内完成传统需要数小时的配置工作,显著提升AI项目开发效率。

weixin_30335575的博客 535

Nginx源码分析:启动流程

nginx源码分析 nginx-1.11.1 参考书籍《深入理解nginx模块开发与架构解析》 nginx简介 Nginx的作为服务端软件,表现的主要特点是更快、高扩展、高可靠性、低内存消耗、单机支持10万以上的并发连接和热部署等优点。Nginx是一般运行模型master-worker,启动多个worker来处理请求,一般master进程不会对用户提供服务,只用于管理真正提供服务的wroker进...

qq_33339479的博客 483

FreeRTOS:卡在configASSERT( ( pxQueue ) )问题的解决

FreeRTOS卡在configASSERT( ( pxQueue ) )问题的解决

qq_42007164的博客 9564

Aurix TC3XX Cache memory分析

Aurix Cache memory 分析

qwe0405080615的博客 4346

Nginx 源码分析

nginx.caspect:constants:nginx.hfilter:fixture:lang:runtime:tools:

zjw12221的专栏 1136

京东商品多维特征提取:基于时空大模型的实时库存预测接口设计

在电商行业,库存管理是供应链的核心环节之一。库存水平过高会导致资金占用、仓储成本增加,而库存水平过低则可能引发缺货风险,影响客户满意度和平台声誉。京东作为中国领先的电商平台,拥有海量的商品数据和复杂的业务场景,传统的库存预测方法难以应对市场动态变化和业务需求。时空大模型作为一种融合时间序列分析和空间特征提取的前沿技术,能够捕捉商品多维特征在时空维度上的变化规律,为实时库存预测提供更精准的决策依据。

FB13713612741的博客 954

nginx 源码分析:启动流程

nginx 启动流程 启动流程假设 nginx 以一个 master 多个 worker 进程的方式工作。 main nginx 进程启动时先执行 main 函数(src/core/nginx.c 中),main 函数先做一些基本的工作,比如处理命令行参数,初始化系统时间,初始化 error 日志等。然后它初始化一个 ngx_cycle_t 结构的局部变量 init_cycle ,接着以init_...

alenliu's blog 1550

Mid-360激光雷达与IMU标定实战:从环境配置到参数优化

本文详细介绍了Mid-360激光雷达与IMU标定的完整流程,涵盖环境配置、驱动适配、参数优化及实战操作。重点解析了标定参数设置技巧与常见问题解决方案,帮助开发者提升机器人感知系统的定位与建图精度,确保LiDAR-IMU数据融合的最佳效果。

a1b2c3d的博客 914

在 SAP BTP 上为应用开启多租户能力:基于 SaaS Provisioning 和 XSUAA 的完整实践指南

本文介绍了在SAP BTP上配置多租户应用的实战指南。主要内容包括: 多租户架构概述:解释provider子账户、consumer子账户和tenant的概念,以及数据隔离机制。 安全配置:在xs-security.json中设置tenant-mode为shared,并为SaaS Provisioning服务添加回调scope授权。 路由配置:通过manifest.yml设置TENANT_HOST_PATTERN来定义多租户访问模式,确保不同租户通过不同子域名访问同一应用。 服务绑定:将XSUAA和SaaS

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 145

nginx源码分析(一) 启动篇nginx.c

一、Nginx的启动过程 Nginx的主流程的实现函数在./src/core/nginx.c文件中,以下是流程图,减少一切非必要的代码说明 二、主要命令 命令 -v 版本号; -?,-h 帮助 ; -t -T 测试配置; -q 退出; -s 发送信号; -p 设置编译后的路径; -c 配指文件名称; -g 设置全局 信号 nginx -s reload nginx -s reopen nginx -s stop nginx -s quit ...

yudaichenydc的博客 2854

大模型选型实战:为OpenClaw匹配最优“大脑”的全维度考量

大模型不是越贵越好,也不是参数越高越好,适合自己的使用场景才是最好的。按照我的方法,先明确自己的需求,再选对应的模型,配置多模型自动路由,既能保证体验,又能最大限度降低成本。我自己用这套配置用了半年多,不管是写文章、写代码还是处理复杂问题,都完全够用,成本也很低,大家可以参考一下。如果不知道选什么模型,可以在评论区说一下你的使用场景。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 343

Nginx源码分析(25篇),【设计思想解读开源框架】

加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2401_84265751的博客 809

损失函数大汇总(四十三)(Boundary Loss附公式推导与代码)

摘要 Boundary Loss是一种针对图像分割任务的边界优化损失函数,特别适用于小目标、细长结构和类别不平衡场景。它通过引入真实边界的有符号距离场(SDF),将边界距离优化问题转化为区域积分形式。与Dice Loss等区域重叠损失不同,Boundary Loss更关注预测边界与真实边界的精确对齐,而非整体区域重叠。其核心公式为像素级SDF值与预测概率的乘积求和,通过梯度调整使预测概率在真实边界内部升高、外部降低。该损失通常与区域型损失(如CE或Dice)联合使用,形成"区域分割+边界修正&qu

悦学共鸣,温柔以待,汇聚光芒,共同成长 354

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

上一篇: Linux c 开发 - 内存管理器ptmalloc
下一篇: Nginx源码分析 - 主流程篇 - 平滑重启和信号控制(10)
老码农zhuli
老码农zhuli 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄14年 2456粉丝 312原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值