boa阅读笔记3

void open_logs(void)
{
    int error_log;

    /* if error_log_name is set, dup2 stderr to it */
    /* otherwise, leave stderr alone */
    /* we don't want to tie stderr to /dev/null */
    if (error_log_name) {
        /* open the log file */
        if (!(error_log = open_gen_fd(error_log_name))) {
            DIE("unable to open error log");
        }

        /* redirect stderr to error_log */
        if (dup2(error_log, STDERR_FILENO) == -1) {
            DIE("unable to dup2 the error log");
        }
        close(error_log);
    }

    /* set the close-on-exec to true */
    //当使用exec时关闭stderr,防止其他程序写stderr
    if (fcntl(STDERR_FILENO, F_SETFD, 1) == -1) {
        DIE("unable to fcntl the error log");
    }

    if (access_log_name) {//权限日志
        /* Used the "a" flag with fopen, but fopen_gen_fd builds that in
         * implicitly when used as a file, and "a" is incompatible with
         * pipes and network sockets. */
        if (!(access_log = fopen_gen_fd(access_log_name, "w"))) {
            int errno_save = errno;
            fprintf(stderr, "Cannot open %s for logging: ",
                    access_log_name);
            errno = errno_save;
            perror("logfile open");
            exit(errno);
        }
        /* line buffer the access log */
#ifdef SETVBUF_REVERSED
        setvbuf(access_log, _IOLBF, (char *) NULL, 0);
#else
        setvbuf(access_log, (char *) NULL, _IOLBF, 0);
#endif
    } else
        access_log = NULL;

    if (cgi_log_name) {//cgi日志
        cgi_log_fd = open_gen_fd(cgi_log_name);
        if (cgi_log_fd == -1) {
            WARN("open cgi_log");
            free(cgi_log_name);
            cgi_log_name = NULL;
            cgi_log_fd = 0;
        } else {
            if (fcntl(cgi_log_fd, F_SETFD, 1) == -1) {//当exec时关闭cgi_log
                WARN("unable to set close-on-exec flag for cgi_log");
                close(cgi_log_fd);
                cgi_log_fd = 0;
                free(cgi_log_name);
                cgi_log_name = NULL;
            }
        }
    }
}

open_logs完成了程序所需日志的打开、重定向和设置,并防止新建进程对日志的干扰。

完成 一系列的环境初始化后,接下来就是创建监听socket了。

    server_s = create_server_socket();

static int create_server_socket(void)
{
    int server_s;
    
    server_s = socket(SERVER_AF, SOCK_STREAM, IPPROTO_TCP); //创建TCP协议的socket
    if (server_s == -1) {
        DIE("unable to create socket");
    }

    /* server socket is nonblocking */
    if (set_nonblock_fd(server_s) == -1) {//设置文件描述符为无阻塞模式
        DIE("fcntl: unable to set server socket to nonblocking");
    }

    /* close server socket on exec so cgi's can't write to it */
    if (fcntl(server_s, F_SETFD, 1) == -1) {      //FD_CLOEXEC
        DIE("can't set close-on-exec on server socket!");
    }

    /* reuse socket addr */
    if ((setsockopt(server_s, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
                    sizeof (sock_opt))) == -1) {
        DIE("setsockopt");
    }

    /* internet family-specific code encapsulated in bind_server()  */
    if (bind_server(server_s, server_ip) == -1) {//实现了ipv4和ipv6的定制绑定
        DIE("unable to bind");
    }

    /* listen: large number just in case your kernel is nicely tweaked */
    if (listen(server_s, backlog) == -1) {//监听
        DIE("unable to listen");
    }
    return server_s;
}

一个标准的socket创建流程后,服务端口已经成功被程序监听。

接下来是对信号处理函数进行设置。

    init_signals();
void init_signals(void)
{
    struct sigaction sa;

    sa.sa_flags = 0;
    //设置在信号处理函数中需要屏蔽的信号
    sigemptyset(&sa.sa_mask); //清空sa_mask
    sigaddset(&sa.sa_mask, SIGSEGV);
    sigaddset(&sa.sa_mask, SIGBUS);
    sigaddset(&sa.sa_mask, SIGTERM);
    sigaddset(&sa.sa_mask, SIGHUP);
    sigaddset(&sa.sa_mask, SIGINT);
    sigaddset(&sa.sa_mask, SIGPIPE);
    sigaddset(&sa.sa_mask, SIGCHLD);
    sigaddset(&sa.sa_mask, SIGALRM);
    sigaddset(&sa.sa_mask, SIGUSR1);
    sigaddset(&sa.sa_mask, SIGUSR2);
    //设置信号处理函数
    sa.sa_handler = sigsegv;
    sigaction(SIGSEGV, &sa, NULL);

    sa.sa_handler = sigbus;
    sigaction(SIGBUS, &sa, NULL);

    sa.sa_handler = sigterm;
    sigaction(SIGTERM, &sa, NULL);

    sa.sa_handler = sighup;
    sigaction(SIGHUP, &sa, NULL);

    sa.sa_handler = sigint;
    sigaction(SIGINT, &sa, NULL);

    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, NULL);

    sa.sa_handler = sigchld;
    sigaction(SIGCHLD, &sa, NULL);

    sa.sa_handler = sigalrm;
    sigaction(SIGALRM, &sa, NULL);

    sa.sa_handler = SIG_IGN;
    sigaction(SIGUSR1, &sa, NULL);

    sa.sa_handler = SIG_IGN;
    sigaction(SIGUSR2, &sa, NULL);
}

完成了信号的设置,离程序真正开始工作又近了一步,下次再接着分析下面几步。


你可能感兴趣的:(boa阅读笔记3)