nginx线程池浅析

本文详细剖析了Nginx线程池的实现原理,从任务结构、队列管理、线程池初始化、任务调度、主线程交互等方面进行深入探讨。线程池简化流程为:A线程准备任务->post任务->线程池处理任务->回调通知A线程。关键数据结构包括任务结构体和队列,线程池结构体包含任务队列、等待任务计数和条件变量等。线程运行函数负责处理任务并使用回调通知主线程。此外,还展示了线程池的使用示例,主要用于文件I/O操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nginx线程池

源代码在ngx_thread_pool.c中

nginx线程池简化流程

A线程准备任务—>post任务—>线程池唤醒一个线程处理–>通过回调函数通知A线程处理完毕

数据结构分析

任务

struct ngx_thread_task_s {
   
   
    ngx_thread_task_t   *next;		//指向下一个任务
    ngx_uint_t           id;		//任务ID
    void                *ctx;		//任务的上下文
    void               (*handler)(void *data, ngx_log_t *log);		//处理任务的函数句柄
    ngx_event_t          event;			//跟任务关联的事件对象(当线程池处理成任务之后将会由主线程调用event对象的handler回调函数)
};

队列

typedef struct {
   
   
    ngx_thread_task_t        *first;
    ngx_thread_task_t       **last;
} ngx_thread_pool_queue_t;

线程池

struct ngx_thread_pool_s {
   
   
    ngx_thread_mutex_t        mtx;		//互斥锁,用于锁定任务队列,避免竞争状态。
    ngx_thread_pool_queue_t   queue;	//任务队列
    ngx_int_t                 waiting;	//有多少个任务正在等待处理
    ngx_thread_cond_t         cond;		//用于通知线程池有任务需要处理

    ngx_log_t                *log;		

    ngx_str_t                 name;		//线程池名称
    ngx_uint_t                threads;	//线程池由多少个线程组成(线程数)
    ngx_int_t                 max_queue;	//线程池最大能处理的任务数

    u_char                   *file;		//配置文件名
    ngx_uint_t                line;		//thread_pool配置在配置文件中的行号
};

代码分析

入口函数ngx_thread_pool_init_worker

此函数会调用线程池初始化函数

static ngx_int_t
ngx_thread_pool_init_worker(ngx_cycle_t *cycle)
{
   
   
    ngx_uint_t                i;
    ngx_thread_pool_t       **tpp;
    ngx_thread_pool_conf_t   *tcf;

	//如果不是worker或者只有一个worker就不起用线程池
    if (ngx_process != NGX_PROCESS_WORKER
        && ngx_process != NGX_PROCESS_SINGLE)
    {
   
   
        return NGX_OK;
    }

    tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                  ngx_thread_pool_module);

    if (tcf == NULL) {
   
   
        return NGX_OK;
    }

    ngx_thread_pool_queue_init(&ngx_thread_pool_done);		//初始化任务完成队列

    tpp = tcf->pools.elts;

    for (i = 0; i < tcf->pools.nelts; i++) {
   
   
        if (ngx_thread_pool_init(tpp[i], cycle->log, cycle->pool) != NGX_OK) {
   
   
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}

线程池初始化ngx_thread_pool_init

static ngx_int_t
ngx_thread_pool_init(ngx_thread_pool_t *tp, ngx_log_t *log, ngx_pool_t *pool)
{
   
   
    int             err;
    pthread_t       tid;
    ngx_uint_t      n;
    pthread_attr_t  attr;

    if (ngx_notify == NULL) {
   
   
        ngx_log_error(NGX_LOG_ALERT, log, 0,
               "the configured event method cannot be used with thread pools");
        return NGX_ERROR;
    }
	
	/*
		#define ngx_thread_pool_queue_init(q)                                         \
		    (q)->first = NULL;                                                        \
		    (q)->last = &(q)->first
		
		first指针赋值NULL,**last执行first的地址
	*/
    ngx_thread_pool_queue_init(&tp->queue);		//初始化线程池队列

    if (ngx_thread_mutex_create(&tp->mtx, log) != NGX_OK) {
   
   
        return NGX_ERROR;
    }

    if (ngx_thread_cond_create(&tp->cond, log) != NGX_OK) {
   
   
        (void) ngx_thread_mutex_destroy(&tp->mtx, log);
        return NGX_ERROR;
    }

    tp->log = log;

    err = pthread_attr_init(&attr);
    if (err) {
   
   
        ngx_log_error(NGX_LOG_ALERT, log, err
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值