Linux下进程的创建使用fork系统调用,fork在哪里呢?答案是在ngx_spawn_process函数中。我们先不忙着看ngx_spawn_process函数,先看调用ngx_spawn_process的ngx_start_worker_processes函数。该函数在主线程循环中需要创建工作进程的地方被调用。
void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
ngx_int_t i, s;
ngx_channel_t ch;
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start worker processes");
ch.command = NGX_CMD_OPEN_CHANNEL;
for (i = 0; i < n; i++) {
cpu_affinity = ngx_get_cpu_affinity(i);
ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
"worker process", type);
ch.pid = ngx_processes[ngx_process_slot].pid;
ch.slot = ngx_process_slot;
ch.fd = ngx_processes[ngx_process_slot].channel[0];
for (s = 0; s < ngx_last_process; s++) {
if (s == ngx_process_slot
|| ngx_processes[s].pid == -1
|| ngx_processes[s].channel[0] == -1)
{
continue;
}
ngx_log_debug6(NGX_LOG_DEBUG_CORE, cycle->log, 0,
"pass channel s:%d pid:%P fd:%d to s:%i pid:%P fd:%d",
ch.slot, ch.pid, ch.fd,
s, ngx_processes[s].pid,
ngx_processes[s].channel[0]);
ngx_write_channel(ngx_processes[s].channel[0],
&ch, sizeof(ngx_channel_t), cycle->log);
}
}
}
ngx_start_worker_process函数还是很简单的,基本就是调用ngx_spawn_process函数创建工作进程,然后通知所有进程。下面我们就具体看看主进程是如何创建工作进程的。
ngx_spawn_process函数首先需要为即将创建的工作进程分配一个进程信息结构体。如果是重启某个工作进程,直接使用respawn参数作为工作进程索引,否则需要从ngx_process数组中找到一个空闲的元素。如果ngx_process数组全部用光了,就返回错误。函数在fork之前会将新进程在ngx_process中的索引保存在ngx_process_slot中。
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
char *name, ngx_int_t respawn)
{
u_long on;
ngx_pid_t pid;
ngx_int_t s;
if (respawn >= 0) {
s = respawn;
} else {
for (s = 0; s < ngx_last_process; s++) {
if (ngx_processes[s].pid == -1) {
break;
}
}
if (s ==