Lighttpd 1.5的多线程实现

lighttpd 1.4.x是一个典型的多进程linux程序,在单个进程内部没有使用多线程,同一时刻只有一个线程在运行。

而到了lighttpd 1.5版本,也使用了多线程来完成某些工作。lighttpd通过GAsyncQueue(GLIB异步队列)的方式实现了一个线程池,从而完成了多线程的运作(需要安装glibc-dev库)。

GAsyncQueue类型的异步消息队列的定义在base.h中

GAsyncQueue *stat_queue; /* send a stat_job into this queue and joblist_queue will get a wakeup when the stat is finished */ 

GAsyncQueue *joblist_queue; 

GAsyncQueue *aio_write_queue; 

在sever.c文件中,对其进行初始化:

srv->stat_queue = g_async_queue_new(); 

srv->joblist_queue = g_async_queue_new(); 

srv->aio_write_queue = g_async_queue_new(); 

同时,在server.c中,也定义了线程:

#ifdef USE_GTHREAD  

    GThread **stat_cache_threads;   //定义了一个指针的指针,也就是一个数组。GThread由g_thread-2.0库提供,需要安装这个库  

    GThread **aio_write_threads = NULL; 

#ifdef USE_LINUX_AIO_SENDFILE  

    GThread *linux_aio_read_thread_id = NULL; 

#endif  

    GError *gerr = NULL; 

#endif 

下面以stat_cache_threads为例,说明GAsyncQueue实现线程池的方式,这个线程的功能是处理页面的stat_cache信息:

首先在lighttpd的main函数中,为线程申请空间、创建线程,其中srv->srvconf.max_stat_threads即stat_cache线程数量,是从配置文件中读取到的:

stat_cache_threads = calloc(srv->srvconf.max_stat_threads, sizeof(*stat_cache_threads)); 

 

for (i = 0; i < srv->srvconf.max_stat_threads; i++) { 

        stat_cache_threads[i] = g_thread_create(stat_cache_thread, srv, 1, &gerr); 

        if (gerr) { 

            ERROR("g_thread_create failed: %s", gerr->message); 

            return -1; 

        } 

于是stat_cache_thread函数(注意,结尾没有“s”)就被作为线程,执行起来了,其句柄保存在stat_cache_threads数组中。

stat_cache_thread函数在stat_cache.c文件中,为:

gpointer stat_cache_thread(gpointer _srv) { 

    server *srv = (server *)_srv; 

    stat_job *sj = NULL;     

    /* take the stat-job-queue */ 

    GAsyncQueue * inq; 

    g_async_queue_ref(srv->stat_queue); 

    inq = srv->stat_queue; 

    /* */ 

    while (!srv->is_shutdown) { 

        /* let's see what we have to stat */ 

        struct stat st; 

        if ((sj = g_async_queue_pop(inq))) { 

            if(sj == (stat_job *) 1) 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwzsgw.html