首页 > 其他 > 详细

spawn-fcgi源码解读

时间:2020-07-01 13:32:03      阅读:54      评论:0      收藏:0      [点我收藏+]

版本:spawn-fcgi-1.6.4

文件:spawn-fcgi-1.6.4/src/spawn-fcgi.c

一、入口 main():

1. 获取执行spawn-fcgi的时候传递的参数:getopt(argc, argv, "c:d:f:g:?hna:p:b:u:vC:F:s:P:U:G:M:S");

while循环,每次获取一个参数,将获取到的参数值(每次获取的时候保存在optarg这个全局变量中)进行初始化处理;

Options:
 -f <path>      filename of the fcgi-application (deprecated; ignored if
                <fcgiapp> is given; needs /bin/sh)
 -d <directory> chdir to directory before spawning
 -a <address>   bind to IPv4/IPv6 address (defaults to 0.0.0.0)
 -p <port>      bind to TCP-port
 -s <path>      bind to Unix domain socket
 -M <mode>      change Unix domain socket mode (octal integer, default: allow
                read+write for user and group as far as umask allows it)
 -C <children>  (PHP only) numbers of childs to spawn (default: not setting
                the PHP_FCGI_CHILDREN environment variable - PHP defaults to 0)
 -F <children>  number of children to fork (default 1)
 -b <backlog>   backlog to allow on the socket (default 1024)
 -P <path>      name of PID-file for spawned process (ignored in no-fork mode)
 -n             no fork (for daemontools)
 -v             show version
 -?, -h         show this help
(root only)
 -c <directory> chroot to directory
 -S             create socket before chroot() (default is to create the socket
                in the chroot)
 -u <user>      change to user-id
 -g <group>     change to group-id (default: primary group of user if -u
                is given)
 -U <user>      change Unix domain socket owner to user-id
 -G <group>     change Unix domain socket group to group-id

2. 两种fork模式:

1) 传参-n, 即nofork模式, 则pid_file = NULL;

2)不传参-n,即非nofork模式,则pid_file = 参数-P指定的文件。

如果指定了pid_file文件,则pid_fd = open(pid_file, ...);

3. 判断指定的username, groupname,sockusername, sockgroupname是否在系统中: find_user_group()

相关函数:读取/etc/passwd文件到struct passwd结构中:

getpwnam()

getpwuid()

getgrnam()

4.root用户执行的时候getuid()==0,可以执行执行的chroot目录,也可以指定sock的用户和组;

5.socket的bind()操作:fcgi_fd = bind_socket();

 

二、生成fcgi应用程序进程: fcgi_spawn_connection(fcgi_app, fcgi_app_argv, fcgi_fd, fork_count, child_count, pid_fd, nofork);

fcgi_app:fcgi应用程序bin文件;

fcgi_app_argv,:通过getopt()读取完后剩下的参数;

fcgi_fd:socket client fd;

fork_count:需要fork的子进程数,默认为1;

child_count:仅仅PHP有效;

pid_fd:pid文件;

nofork:是否是fork模式.

1.通信sock统一到fd=0上面:

关键点:
      if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
        close(FCGI_LISTENSOCK_FILENO);
        dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
        close(fcgi_fd);
      }

使用dup2将指向sock的文件描述符fcgi_fd复制到FCGI_LISTENSOCK_FILENO。

也就是使fcgi_fd和FCGI_LISTENSOCK_FILENO都指向sock,然后关闭fcgi_fd,改用FCGI_LISTENSOCK_FILENO来作为通信sock的文件描述符.

2.如果是fork模式,则用setsid()脱离主进程,自己独立出来。

3.用新的程序替换掉当前进程:

如果传了新的执行程序:execv(appArgv[0], appArgv);

否则:execl("/bin/sh", "sh", "-c", b, (char *)NULL);  //参数b是-f指定的程序.

spawn-fcgi源码解读

原文:https://www.cnblogs.com/thinksasa/p/13218519.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!