cgi的核心机制:
1.从环境变量读取http request参数
2.如果是get模式,那么全部请求参数可以从环境变量中获取
3.如果是post模式,那么从stdin中读取content_length长度的数据,可解析为请求参数
这其中包括两块,首先当收到request后,起进程,配置父子进程的stdin和stdout,具体如下:
if ((pid = fork()) < 0) {
save_errno = errno;
if (pipe_in) {
close(in_fds[0]);
close(in_fds[1]);
}
if (pipe_out) {
close(out_fds[0]);
close(out_fds[1]);
}
if (pipe_err) {
close(err_fds[0]);
close(err_fds[1]);
}
errno = save_errno;
return 0;
}
if (!pid) {
/* Child process */
RAISE_SIGSTOP(SPAWN_CHILD);
if (pipe_out) {
close(out_fds[0]);
dup2(out_fds[1], STDOUT_FILENO);
close(out_fds[1]);
}
if (pipe_in) {
close(in_fds[1]);
dup2(in_fds[0], STDIN_FILENO);
close(in_fds[0]);
}
if (pipe_err) {
close(err_fds[0]);
dup2(err_fds[1], STDERR_FILENO);
close(err_fds[1]);
}
/* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
signal(SIGCHLD, SIG_DFL); /* Was that it? */
func(data, NULL);
exit(1); /* Should only get here if the exec in func() failed */
}
/* Parent process */
ap_note_subprocess(p, pid, kill_how);
if (pipe_out) {
close(out_fds[1]);
*pipe_out = out_fds[0];
}
if (pipe_in) {
close(in_fds[0]);
*pipe_in = in_fds[1];
}
if (pipe_err) {
close(err_fds[1]);
*pipe_err = err_fds[0];
}
第二,解析url,获取要执行的指令,子进程中执行,具体如下:
child_pid = ap_call_exec(r, pinfo, s, ap_create_environment(r->pool, env),1); //执行脚本程序
child_pid = ap_call_exec(r, pinfo, argv0, env, 0); //执行非脚本程序
这里的env就是解析请求得到的参数,作为环境变量传给指令程序。