文档章节

boa阅读笔记5

开源中国精神科主任
 开源中国精神科主任
发布于 2014/11/10 09:52
字数 857
阅读 15
收藏 0
    create_common_env();
    build_needs_escape();

    if (max_connections < 1) {
        struct rlimit rl;

        /* has not been set explicitly */
        c = getrlimit(RLIMIT_NOFILE, &rl);    //获得系统的限制
        if (c < 0) {
            perror("getrlimit");
            exit(1);
        }
        max_connections = rl.rlim_cur;        //根据系统限制设置最大连接数
    }

    /* background ourself */
    if (do_fork) {                            //父进程退出,子进程转换为守护进程
        switch(fork()) {
        case -1:
            /* error */
            perror("fork");
            exit(1);
            break;
        case 0:
            /* child, success */
            break;
        default:
            /* parent, success */
            exit(0);
			//break?????
            break;
        }
    }

我们接着从create_common_env开始介绍。

void create_common_env()
{
    int index = 0, i;


    /* NOTE NOTE NOTE:
       If you (the reader) someday modify this chunk of code to
       handle more "common" CGI environment variables, then bump the
       value COMMON_CGI_COUNT in defines.h UP

       Also, in the case of document_root and server_admin, two variables
       that may or may not be defined depending on the way the server
       is configured, we check for null values and use an empty
       string to denote a NULL value to the environment, as per the
       specification. The quote for which follows:

       "In all cases, a missing environment variable is
       equivalent to a zero-length (NULL) value, and vice versa."
     */
    common_cgi_env[index++] = env_gen_extra("PATH",
                                            ((cgi_path != NULL) ? cgi_path : DEFAULT_PATH), 0);
    common_cgi_env[index++] = env_gen_extra("SERVER_SOFTWARE", SERVER_VERSION, 0);
    common_cgi_env[index++] = env_gen_extra("SERVER_NAME", server_name, 0);
    common_cgi_env[index++] = env_gen_extra("GATEWAY_INTERFACE", CGI_VERSION, 0);

    common_cgi_env[index++] =
        env_gen_extra("SERVER_PORT", simple_itoa(server_port), 0);

    /* NCSA and APACHE added -- not in CGI spec */
    /* common_cgi_env[index++] = env_gen_extra("DOCUMENT_ROOT", document_root); */

    /* NCSA added */
    /* common_cgi_env[index++] = env_gen_extra("SERVER_ROOT", server_root); */

    /* APACHE added */
    common_cgi_env[index++] = env_gen_extra("SERVER_ADMIN", server_admin, 0);
    common_cgi_env[index] = NULL;

    /* Sanity checking -- make *sure* the memory got allocated */
    if (index > COMMON_CGI_COUNT) {
        log_error_time();
        fprintf(stderr, "COMMON_CGI_COUNT not high enough.\n");
        exit(1);
    }

    for(i = 0;i < index;++i) {
        if (common_cgi_env[i] == NULL) {
            log_error_time();
            fprintf(stderr, "Unable to allocate a component of common_cgi_env - out of memory.\n");
            exit(1);
        }
    }
}

上面的代码应该是在设置cgi的环境变量,并最后进行一次环境变量检测。

void build_needs_escape(void)
{
    unsigned int a, b;
    const unsigned char special[] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789"
        "-_.!~*'():@&=+$,/?";
    /* 21 Mar 2002 - jnelson - confirm with Apache 1.3.23 that '?'
     * is safe to leave unescaped.
     */
    unsigned short i, j;

    b = 1;
    for (a=0; b!=0; a++) b=b<<1;
    /* I found $a bit positions available in an unsigned long. */
    if (a < NEEDS_ESCAPE_WORD_LENGTH) {
        fprintf(stderr,
                "NEEDS_ESCAPE_SHIFT configuration error -- "\
                "%d should be <= log2(%d)\n",
                NEEDS_ESCAPE_SHIFT, a);
        exit(1);
    } else if (a >= 2*NEEDS_ESCAPE_WORD_LENGTH) {
        /* needs_escape_shift configuration suboptimal */
    } else {
        /* Ahh, just right! */;
    }
    memset(_needs_escape, ~0, sizeof(_needs_escape));
    for(i = 0; i < sizeof(special) - 1; ++i) {
        j=special[i];
        if (j>=NEEDS_ESCAPE_BITS) {
            /* warning: character $j will be needlessly escaped. */
        } else {
            _needs_escape[NEEDS_ESCAPE_INDEX(j)]&=~NEEDS_ESCAPE_MASK(j);
        }
    }
}

看函数名应该跟编解码有关,浏览代码后初步确定是创建了程序需要的编码对照表,方便server快速编解码。

    /* main loop */
    timestamp();

    status.requests = 0;
    status.errors = 0;

    start_time = current_time;

    #if defined _kqueue
        kqueue_loop(server_s);

    #elif defined _epoll
        epoll_loop(server_s);

    #else
        select_loop(server_s);

    #endif

    return 0;
}

最后就是进入主循环了,先是记录当前时间,然后根据系统情况以先后次序选择kqueue、epoll、和select之一进行socket端口的监听循环。

void select_loop(int server_s)
{
    FD_ZERO(&block_read_fdset);
    FD_ZERO(&block_write_fdset);
    /* set server_s and req_timeout */
    req_timeout.tv_sec = (ka_timeout ? ka_timeout : REQUEST_TIMEOUT);
    req_timeout.tv_usec = 0l;   /* reset timeout */

    /* preset max_fd */
    max_fd = -1;

    while (1) {
        if (sighup_flag)
            sighup_run();
        if (sigchld_flag)
            sigchld_run();
        if (sigalrm_flag)
            sigalrm_run();

        if (sigterm_flag) {
            if (sigterm_flag == 1)
                sigterm_stage1_run(server_s);
            if (sigterm_flag == 2 && !request_ready && !request_block) {
                sigterm_stage2_run();
            }
        }

        /* reset max_fd */
        max_fd = -1;

        if (request_block)
            /* move selected req's from request_block to request_ready */
            fdset_update();

        /* any blocked req's move from request_ready to request_block */
        process_requests(server_s);

        if (!sigterm_flag && total_connections < (max_connections - 10)) {
            BOA_FD_SET(server_s, &block_read_fdset); /* server always set */
        }

        req_timeout.tv_sec = (request_ready ? 0 :
                              (ka_timeout ? ka_timeout : REQUEST_TIMEOUT));
        req_timeout.tv_usec = 0l;   /* reset timeout */

        if (select(max_fd + 1, &block_read_fdset,
                   &block_write_fdset, NULL,
                   (request_ready || request_block ? &req_timeout : NULL)) == -1) {
            /* what is the appropriate thing to do here on EBADF */
            if (errno == EINTR)
                continue;   /* while(1) */
            else if (errno != EBADF) {
                DIE("select");
            }
        }

        time(&current_time);
        if (FD_ISSET(server_s, &block_read_fdset))
            pending_requests = 1;
    }
}

因为对select比较熟悉,因此拿select_loop来分析。在主循环中先对状态标志进行了分析和处理,如果有请求阻塞,则把请求移到就绪队列进行处理,然后对请求进行超时处理,最后再次进行select监听读写请求。

对boa的解读就先到这里了,由于对http服务的了解还不多,因此也无法进行更细致的业务分析,只能讲解个大概,以后研究http协议时再来做详细的分析。

© 著作权归作者所有

共有 人打赏支持
开源中国精神科主任
粉丝 1
博文 18
码字总数 26787
作品 0
杭州
私信 提问
SylixOS移植Boa服务器

1. Boa简介 Boa是一种非常小巧的Web服务器,其可执行代码只有大约60KB左右。作为一种单任务Web服务器,Boa只能依次完成用户的请求,而不会fork出新的进程来处理并发连接请求。但Boa支持CGI,...

遗忘丶彻底
2017/07/10
0
0
boa与cgic库写cgi简介

嵌入式 WEB 服务器 BOA 和 CGI 一、嵌入式 WEB 服务器 BOA 简介 嵌入式 WEB 服务器常见的有: boa lighttpd shttpd thttpd mathopd minihttpd appweb goahead 随着 Internet 技术的兴起,在嵌...

唧唧帝
2014/01/15
0
0
嵌入式Web服务器移植

第一步 Boa程序的移植 1、下载Boa源码 下载地址: http://www.boa.org/, 或者 http://sourceforge.net 最新发行版本: 0.94.13 下载 boa-0.94.13.tar.gz,注意:从boa上下载的是boa-0.94.13...

晨曦之光
2012/03/09
52
0
Python学习札记(2)——搭建Boa-constructor

一、Boa-constructor是什么 看看来自己百度的解释:Boa Constructor是一个跨平台的Python集成开发环境和wxPython图形用户界面构建器。它提供了可视化方式的框架(窗口) 的创建 和处理、对象...

东方卯
2014/03/04
0
2
Python集成开发环境--Boa Constructor

boa-constructor是一个跨平台的Python集成开发环境和wxPython图形用户界面构建器。它提供了可视化方式的框架(窗口) 的创建 和处理、对象检视器(object inspector)、编辑器、继承的等级、h...

匿名
2008/09/14
22.9K
2

没有更多内容

加载失败,请刷新页面

加载更多

Java生成二维码图片

maven配置jar包 <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>com.google.z......

骑羊放狼灬
6分钟前
2
0
oracle 修改字段类型

1.varchar2 类型修改 例子:alter table T_Node modify (NODE_CONTEXT varchar2(4000)); 2.varchar2 修改为clob 例子: alter table T_Node add hehe clob; update T_Node set hehe=NODE_CO......

qimh
9分钟前
2
0
别再写 bug 了,避免空指针的 5 个案例!

空指针是我们 Java 开发人员经常遇到的一个基本异常,这是一个极其普遍但似乎又无法根治的问题。 本文,栈长将带你了解什么是空指针,还有如何有效的避免空指针。 什么是空指针? 当一个变量...

Java技术栈
13分钟前
5
0
FastJson对BigDecimal保留两位小数(valueFilter)

实现ValueFilter public class BigDecimalValueFilter implements ValueFilter { @Override public Object process(Object o, String name, Object value) {//o是待转换的对象,n......

石日天
15分钟前
1
0
android 颜色透明度参照比

##透明度参照表: 00%=FF(不透明) 5%=F2 10%=E5 15%=D8 20%=CC 25%=BF 30%=B2 35%=A5 40%=99 45%=8c 50%=7F 55%=72 60%=66 65%=59 70%=4c 75%=3F 80%=33 85%=21 90%=19 95%=0c 100%=00(全透......

东街小霸王
16分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部