Multi-threaded usage in fastcgi

Source: Internet
Author: User
Tags goto printf thread

http://wdhdmx.iteye.com/blog/1477218

Official information: http://www.fastcgi.com/devkit/doc/overview.html

Http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/ap_guide.htm

Http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm
0. Background

Content waiting to be communicated is added to the project, so the single request processing time has increased. Single-threaded processing of fcgi wastes CPU and user time, so multiple threads are required to process, reducing user queuing time.

Changing the part of the processing user request from a single thread to multi-threading requires a general understanding of whether the change will affect performance.

The

concludes that multithreading and threading are executed in almost the same way as a single thread, so multithreading does not pose an additional burden. 1. Single Thread processing steps 1.1 A simple single-threaded fcgi request C code   #include  <fcgi_stdio.h>      void  main (void)    {       int count = 0;       while (Fcgi_accept ()  >= 0)  {            printf ("content-type: text/html\r\n");            printf ("\ r \ n");           printf ("Hello  world!<br>\r\n ");           printf (" Request  number %d. ",  count++);       }       exit ( 0);  }   1.2 enters fcgi_accept.

Enter this fcgi_accept () method inside, in the file FCGI_STDIO.C. C code   int fcgi_accept (void)    {       //variable Indicates whether the request is received. Default is Fasle, do not receive requests        if (!acceptcalled)  {            //judge whether it is CGI, the variable is global static, next time will be used.            iscgi = fcgx_iscgi ();     The        //status changes to receive requests.            acceptCalled = TRUE;            //the end of the request, the value is emptied to assign the initial values.            atexit (&fcgi_finish);        } else if (iscgi)  {           // Not the first request, and it's a CGI program.            return (EOF);       }    &NBsp;   if (iscgi)  {           //cgi Initial assignment operation , do not care.            ...       } else  {           fcgx_stream *in, *out, * error;           //char**  string array.            FCGX_ParamArray envp;            //accept the request, this method is described below             int acceptresult = fcgx_accept (&AMP;IN,&NBSP;&AMP;OUT,&NBSP;&AMP;ERROR,&NBSP;&AMP;ENVP);            //receive failed, return <0, which is why the judgment on the loop is  while (fcgi_ Accept ()  >= 0)            if (acceptresult  < 0)  {               return acceptresult;           }           / /Assign the resulting data to the corresponding output, input, data.            FCGI_stdin->stdio_stream = NULL;            FCGI_stdin->fcgx_stream = in;            FCGI_stdout->stdio_stream = NULL;            FCGI_stdout->fcgx_stream = out;           FCGI_stderr->stdio_stream = NULL;           FCGI_stderr->fcgx_stream = error;           environ = envp;       }       //End        return 0;  }   1.3 fcgx_acceptWait for the method to receive the request, in FCGIAOO.C.

C code   static fcgx_request the_request;      int fcgx_accept (fcgx_stream &NBSP;**IN,FCGX_STREAM&NBSP;**OUT,FCGX_STREAM&NBSP;**ERR,FCGX_PARAMARRAY&NBSP;*ENVP)    {       int rc;//defines the variables that are returned.    whether     //has been initialized.        if  (! libinitialized)  {            rc = fcgx_init ();            if  (RC)  {                return rc;           }        }       //receive data, the following introduction        rc = fcgx_ Accept_r (&the_request);       //assigns a value to the corresponding stream and data.        *in = the_request.in;       *out = the_request.out;        *err = the_request.err;       *envp = the_request.envp;           return rc;  }   1.4 fcgx_accept_r ()

With the fcgiapp.c inside; C code  /*   *----------------------------------------------------------------------   *    * FCGX_Accept_r --   *   *       from http  server  receive a new request    * Results:   *       correct return of 0, Error return -1.   * Side effects:   *   *       The request is completed via fcgx_accept, the Input,output stream is created, and each is assigned to in   *      ,out, Err. Create parameter data is removed from Fcgx_getparam and given to ENVP.    *       do not save pointers and strings, they will be released in Fcgx_finish in the next request.    *----------------------------------------------------------------------   */   Int fcgx_accept_r (fcgx_request *reqdataptr)    {       if  (!libinitialized)  {           return -9998;       }          //The current reqdata to complete the request. Releases the content, initializes it.        fcgx_finish_r (reqdataptr);       //while        for  (;;)  {           //ipcFd  is the conduit of communication between the two sides, in the above Fcgx_finish_ R is assigned a value of-1.            if  (reqdataptr->ipcfd < 0)  {               int fail_on_ intr = reqdataptr->flags & fcgi_fail_accept_on_intr;                //receive a request, incoming socket, no request will wait here. That's the point, but I can't read it.                reqDataPtr->ipcFd  = os_accept (Reqdataptr->listen_sock, fail_on_intr, webserveraddresslist);               if   (reqdataptr->ipcfd < 0)  {                    return  (errno > 0)  ?  (0  - errno)  : -9999;                }           }            reqDataPtr->isBeginProcessed = FALSE;            reqdataptr->in = newreader (reqdataptr, 8192, 0);           fillbuffproc (reqdataptr->in);            if (!reqdataptr->isbeginprocessed)  {                goto tryagain;           }            {                //view the request type.                char *roleStr;                switch (ReqDataPtr->role)  {                    case FCGI_RESPONDER:                        roleStr =  "Fcgi_role=responder";                        break;   &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&Nbsp;       case fcgi_authorizer:                        rolestr =   "Fcgi_role=authorizer";                        break;                    case FCGI_FILTER:                         rolestr =  "Fcgi_role=filter";                        break;                    default:                        goto tryagain;               }                //creates a space for storing parameter querystring.                reqdataptr->paramsptr  = newparams (;  )              //the request type as a key-value join parameter.                putparam (reqDataPtr-> Paramsptr, stringcopy (ROLESTR));           }           //reads the input stream in a developed manner (where it stops, whether it needs to skip requests)             setreadertype (reqdataptr->in, fcgi_params);            //writes the parameter read to the Key=value.            if (Readparams (reqdataptr->paramsptr,  reqdataptr->in)  >= 0)  {                //jumps out of the loop, or waits for the next request.                break;            }               //releases these intermediate-generated things. Place IPCFD as -1.   tryagain:           fcgx_free ( reqdataptr, 1);          } /* for  (;;)  */       //assigns the remaining information to the value. Complete the start part of a request.        setreadertype (Reqdataptr->in, fcgi_stdin);        reqdataptr->out = newwriter (reqdataptr, 8192, fcgi_stdout);        reqdataptr->err = newwriter (Reqdataptr, 512, fcgi_stderr );       reqDataPtr->nWriters = 2;        reqDataPtr->envp = reqDataPtr->paramsPtr->vec;        return 0;  }   1.5 Fcgx_finish_r executed before closing the request

in the fcgiapp.c; C Code   VOID&NBSP;FCGX_FINISH_R (fcgx_request *reqdataptr)    {        int close;          if  (reqdataptr == null)  {           return;        }          close = !reqDataPtr->keepConnection;          if  (reqdataptr->in)  {            close |= fcgx_fclose (reqdataptr->err);            close |= fcgx_fclose (reqdataptr->out);        close |= fcgx_geterror (reqdataptr->in);       }           fcgx_free (reqdataptr, close);  }  

The basic end, can only understand the process. two multi-threaded requests 2.1 Multi-threaded Request Example

Official website multi-threading example, (HTTP://WWW.FASTCGI.COM/DEVKIT/EXAMPLES/THREADED.C)

Remove the excess output.

  C code   #define  THREAD_COUNT 20      Static int counts[thread_ count];      Static void *doit (void *a)    {        int rc;       FCGX_Request request;        fcgx_initrequest (&request, 0, 0);       for  (;;)        {           rc =  fcgx_accept_r (&request);              if   (rc < 0)                 break;           fcgx_fprintf (request.out,                "content-type: text/html\r\n"                "\ r \ n"                  "<title>FastCGI Hello! ");              sleep (2);            fcgx_finish_r (&request);       }        return NULL;  }      int main (void)    {        int i;       pthread_t id[THREAD_COUNT];           fcgx_init ();           for  (i = 1; i < thread_count; i++)             pthread_create (&id[i], NULL, doit,  (void*) i);           doit (0);       return 0;  }   2.2 Methods related to fcgi

In the Main method C code fcgx_init ();  Initilize the FCGX library. This was called by fcgx_accept () but must was called by the user when using Fcgx_accept_r ().

In multi-line thread: C code fcgx_request Request;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.