10.Nginx启动流程之ngx_os_init

来源:互联网 发布:原理电路仿真软件 编辑:程序博客网 时间:2024/06/09 13:18

Nginx在启动流程中会调用ngx_os_init来初始化一些与操作系统有关的全局变量,不同操作系统下ngx_os_init的实现不同,在os/unix下我们看到Nginx为linux、freebsd、solaris等操作系统实现了对应的ngx_os_init函数。下面以linux操作系统进行讲解:


/* os/unix/ngx_posix.c */ngx_int_t  ngx_ncpu;ngx_int_t  ngx_max_sockets;   // 用于记录可持有的最大套接字描述符数量ngx_int_t  ngx_inherited_nonblocking;struct rlimit  rlmt;void ngx_signal_handler(int signo);typedef struct {     int     signo;     char   *signame;     void  (*handler)(int signo);} ngx_signal_t;ngx_signal_t  signals[] = {    { ngx_signal_value(NGX_RECONFIGURE_SIGNAL),      "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL),      ngx_signal_handler },    { ngx_signal_value(NGX_REOPEN_SIGNAL),      "SIG" ngx_value(NGX_REOPEN_SIGNAL),      ngx_signal_handler },    { ngx_signal_value(NGX_NOACCEPT_SIGNAL),      "SIG" ngx_value(NGX_NOACCEPT_SIGNAL),      ngx_signal_handler },    { ngx_signal_value(NGX_TERMINATE_SIGNAL),      "SIG" ngx_value(NGX_TERMINATE_SIGNAL),      ngx_signal_handler },    { ngx_signal_value(NGX_SHUTDOWN_SIGNAL),      "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL),      ngx_signal_handler },    { ngx_signal_value(NGX_CHANGEBIN_SIGNAL),      "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL),      ngx_signal_handler },    { SIGALRM, "SIGALRM", ngx_signal_handler },    { SIGINT, "SIGINT", ngx_signal_handler },    { SIGIO, "SIGIO", ngx_signal_handler },    { SIGCHLD, "SIGCHLD", ngx_signal_handler },    { SIGPIPE, "SIGPIPE, SIG_IGN", SIG_IGN },    { 0, NULL, NULL }};/* Posix下进行系统相关初始化工作 */ngx_int_t ngx_posix_init(ngx_log_t *log){    ngx_signal_t      *sig;    struct sigaction   sa;    // 调用unistd.h中getpagesize函数来获取内存分页大小, 单位为Byte    ngx_pagesize = getpagesize();    // ngx_ncpu简单置为1    if (ngx_ncpu == 0) {        ngx_ncpu = 1;    }    for (sig = signals; sig->signo != 0; sig++) {        // 遍历感兴趣的信号列表, 然后依次调用sigaction来为它们设置信号处理函数,        // 从上面可见大部分的信号都使用的ngx_signal_handler处理函数, 只有SIGPIPE是SIG_IGN, 也就是忽略此信号        ngx_memzero(&sa, sizeof(struct sigaction));        sa.sa_handler = sig->handler;        sigemptyset(&sa.sa_mask);        if (sigaction(sig->signo, &sa, NULL) == -1) {            ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,                          "sigaction(%s) failed", sig->signame);            return NGX_ERROR;        }    }    // 调用getrlimit来获取进程可以打开的最大文件数    // 我们可以使用ulimit -n命令来获取内核的默认值    if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {        ngx_log_error(NGX_LOG_ALERT, log, errno,                      "getrlimit(RLIMIT_NOFILE) failed)");        return NGX_ERROR;    }    ngx_max_sockets = rlmt.rlim_cur;#if (HAVE_INHERITED_NONBLOCK)    ngx_inherited_nonblocking = 1;#else    ngx_inherited_nonblocking = 0;#endif    return NGX_OK;}/* os/unix/ngx_linux_init.c */char ngx_linux_kern_ostype[50];         // 用于存放操作系统类型的字符数组全局变量char ngx_linux_kern_osrelease[20];      // 用于存放内核版本的字符数组全局变量int ngx_linux_rtsig_max;                // /* Linux下进行系统相关初始化工作 */ngx_int_t ngx_os_init(ngx_log_t *log){    int  name[2], len;    // 调用sysctl来获取操作系统类型    // 我在进行测试时, 如果ngx_linux_kern_ostype作为函数的局部变量, 那么调用会返回-1,    // 出错代码errno:14, 也就是"bad address"; 但是全局变量就不会, 很奇怪, 下面的获取内核版本也是这样    name[0] = CTL_KERN;    name[1] = KERN_OSTYPE;    len = sizeof(ngx_linux_kern_ostype);    if (sysctl(name, sizeof(name), ngx_linux_kern_ostype, &len, NULL, 0)                                                                       == -1) {        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,                      "sysctl(KERN_OSTYPE) failed");        return NGX_ERROR;    }    // 调用sysctl来获取内核版本    name[0] = CTL_KERN;    name[1] = KERN_OSRELEASE;    len = sizeof(ngx_linux_kern_osrelease);    if (sysctl(name, sizeof(name), ngx_linux_kern_osrelease, &len, NULL, 0)                                                                       == -1) {        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,                      "sysctl(KERN_OSRELEASE) failed");        return NGX_ERROR;    }    // 调用sysctl来获取最大可排队的实时信号数量    // 在Linux下测试时会报错errno:20, "Not a directory",    // 不过这里出错后, 不像上面2个会返回NGX_ERROR, 而是直接置ngx_linux_rtsig_max为0    name[0] = CTL_KERN;    name[1] = KERN_RTSIGMAX;    len = sizeof(ngx_linux_rtsig_max);    if (sysctl(name, sizeof(name), &ngx_linux_rtsig_max, &len, NULL, 0) == -1) {        ngx_log_error(NGX_LOG_INFO, log, ngx_errno,                      "sysctl(KERN_RTSIGMAX) failed");        ngx_linux_rtsig_max = 0;    }    // 调用Posix下系统相关初始化函数    return ngx_posix_init(log);}


原创粉丝点击