123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
- <section id="ser_startup" xmlns:xi="http://www.w3.org/2001/XInclude">
- <sectioninfo>
- <revhistory>
- <revision>
- <revnumber>$Revision$</revnumber>
- <date>$Date$</date>
- </revision>
- </revhistory>
- </sectioninfo>
-
- <title>The Server Startup</title>
- <para>
- The <function>main</function> function in file
- <filename>main.c</filename> is the first function called upon server
- startup. It's purpose is to initialize the server and enter main
- loop. The server initialization will be described in the following
- sections.
- </para>
-
- <para>
- Particular initialization steps are described in order in which they
- appear in <function>main</function> function.
- </para>
-
- <section id="signal_handlers">
- <title>Installation Of New Signal Handlers</title>
- <para>
- The first step in the initialization process is the installation of
- new signal handlers. We need our own signal handlers to be able to
- do graceful shutdown, print server statistics and so on. There is
- only one signal handler function which is function
- <function>sig_usr</function> in file <filename>main.c</filename>.
- </para>
- <para>
- The following signals are handled by the function: SIGINT, SIGPIPE,
- SIGUSR1, SIGCHLD, SIGTERM, SIGHUP and SIGUSR2.
- </para>
- </section> <!-- signal-installation -->
-
- <section id="cmdline_parameters">
- <title>Processing Command Line Parameters</title>
- <para>
- SER utilizes the <function>getopt</function>function to parse
- command line parameters. The function is extensively described in
- the man pages.
- </para>
- </section> <!-- cmd-line-params -->
-
- <section id="parser-init">
- <title>Parser Initialization</title>
- <para>
- SER contains a fast 32-bit parser. The parser uses pre-calculated
- hash table that needs to be filled in upon startup. The
- initialization is done here, there are two functions that do the
- job. Function <function>init_hfname_parser</function> initializes
- hash table in header field name parser and function
- <function>init_digest_parser</function> initializes hash table in
- digest authentication parser. The parser's internals will be
- described later.
- </para>
- </section> <!-- parser-init -->
-
- <section id="malloc_init">
- <title>Malloc Initialization</title>
- <para>
- To make SER even faster we decided to re-implement memory
- allocation routines. The new <function>malloc</function> better
- fits our needs and speeds up the server a lot. The memory
- management subsystem needs to be initialized upon server
- startup. The initialization mainly creates internal data structures
- and allocates memory region to be partitioned.
- </para>
-
- <important>
- <para>
- The memory allocation code must be initialized
- <emphasis>BEFORE</emphasis> any of its function is called !
- </para>
- </important>
- </section> <!-- malloc-init -->
-
- <section id="timer_init">
- <title>Timer Initialization</title>
- <para>
- Various subsystems of the server must be called periodically
- regardless of the incoming requests. That's what timer is
- for. Function <function>init_timer</function> initializes the timer
- subsystem. The function is called from <filename>main.c</filename>
- and can be found in <filename>timer.c</filename> The timer
- subsystem will be described later.
- </para>
- <warning>
- <para>
- Timer subsystem must be initialized before config file is parsed !
- </para>
- </warning>
- </section> <!-- timer-init -->
- <section id="fifo_init">
- <title>FIFO Initialization</title>
- <para>
- SER has built-in support for FIFO control. It means that the
- running server can accept commands over a FIFO special file (a
- named pipe). Function <function>register_core_fifo</function>
- initializes FIFO subsystem and registers basic commands, that are
- processed by the core itself. The function can be found in file
- <filename>fifo_server.c</filename>.
- </para>
- <para>
- The FIFO server will be described in another chapter.
- </para>
- </section> <!-- fifo-init -->
-
- <section id="builtin_modules">
- <title>Built-in Module Initialization</title>
- <para>
- Modules can be either loaded dynamically at runtime or compiled in statically. When a module
- is loaded at runtime, it is registered
- <footnote id="regfoot">
- <para>
- Module registration is a process when the core tries to find what functions and
- parameters are offered by the module.
- </para>
- </footnote>
- immediately with the core. When the module is compiled in
- statically, the registration<footnoteref linkend="regfoot"/> must be
- performed during the server startup. Function
- <function>register_builtin_modules</function> does the job.
- </para>
- </section> <!-- builtin-mod-reg -->
-
- <section id="ser_configuration">
- <title>Server Configuration</title>
- <para>
- The server is configured through a configuration file. The
- configuration file is C-Shell like script which defines how
- incoming requests should be processed. The file cannot be
- interpreted directly because that would be very slow. Instead of
- that the file is translated into an internal binary
- representation. The process is called compilation and will be
- described in the following sections.
- </para>
- <note>
- <para>
- The following sections only describe how the internal binary
- representation is being constructed from the config file. The
- way how the binary representation is used upon a request
- arrival will be described later.
- </para>
- </note>
- <para>The compilation can be divided in several steps:</para>
-
- <section id="lexical_analysis">
- <title>Lexical Analysis</title>
- <para>
- Lexical analysis is process of converting the input (the
- configuration file in this case) into a stream of tokens. A
- token is a set of characters that 'belong' together. A program
- that can turn the input into stream of tokens is called
- scanner. For example, when scanner encounters a number in the
- config file, it will produce token NUMBER.
- </para>
- <para>
- There is no need to implement the scanner from scratch, it can
- be done automatically. There is a utility called flex. Flex
- accepts a configuration file and generates scanner according to
- the configuration file. The configuration file for flex
- consists of several lines - each line describing one token. The
- tokens are described using regular expressions. For more
- details, see flex manual page or info documentation.
- </para>
- <para>
- Flex input file for the SER config file is in file
- <filename>cfg.lex</filename>. The file is processed by flex
- when the server is being compiled and the result is written in
- file <filename>lex.yy.c</filename>. The output file contains
- the scanner implemented in the C language.
- </para>
- </section> <!-- lex-analysis -->
-
- <section id="syntax_analysis">
- <title>Syntactical Analysis</title>
- <para>
- The second stage of configuration file processing is called
- syntactical analysis. Purpose of syntactical analysis is to
- check if the configuration file has been well formed, doesn't
- contain syntactical errors and perform various actions at
- various stages of the analysis. Program performing syntactical
- analysis is called parser.
- </para>
- <para>
- Structure of the configuration file is described using
- grammar. Grammar is a set of rules describing valid 'order' or
- 'combination' of tokens. If the file isn't conformable with
- it's grammar, it is syntactically invalid and cannot be further
- processed. In that case an error will be issued and the server
- will be aborted.
- </para>
- <para>
- There is a utility called yacc. Input of the utility is a file
- containing the grammar of the configuration file, in addition
- to the grammar, you can describe what action the parser should
- do at various stages of parsing. For example, you can instruct
- the parser to create a structure describing an IP address every
- time it finds an IP address in the configuration file and
- convert the address to its binary representation.
- </para>
- <para>For more information see yacc documentation.</para>
- <para>
- yacc creates the parser when the server is being compiled from
- the sources. Input file for yacc is
- <filename>cfg.y</filename>. The file contains grammar of the
- config file along with actions that create the binary
- representation of the file. Yacc will write its result into
- file <filename>cfg.tab.c</filename>. The file contains function
- <function>yyparse</function> which will parse the whole
- configuration file and construct the binary representation. For
- more information about the bison input file syntax see bison
- documentation.
- </para>
- </section> <!-- syntax-analysis -->
-
- <section id="config_structure">
- <title>Config File Structure</title>
- <para>
- The configuration file consist of three sections, each of the
- sections will be described separately.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Route Statement</emphasis> - The statement
- describes how incoming requests will be processed.
- When a request is received, commands in one or more
- "route" sections will be executed step by step. The
- config file must always contain one main "route"
- statement and may contain several additional "route"
- statements. Request processing always starts at the
- beginning of the main "route" statement. Additional
- "route" statements can be called from the main one or
- another additional "route" statements (It it similar to
- function calling).
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Assign Statement</emphasis> - There are many
- configuration variables across the server and this
- statement makes it possible to change their
- value. Generally it is a list of assignments, each
- assignment on a separate line.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Module Statement</emphasis> - Additional
- functionality of the server is available through
- separate modules. Each module is a shared object that
- can be loaded at runtime. Modules can export functions,
- that can be called from the configuration file and
- variables, that can be configured from the config
- file. The module statement makes it possible to load
- modules and configure them. There are two commands in
- the statement - <function>loadmodule</function> and
- <function>modparam</function>. The first can load a
- module. The second one can configure module's internal
- variables.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- In the following sections we will describe in detail how the
- three sections are being processed upon server startup.
- </para>
- <section id="route_statement">
- <title>Route Statement</title>
- <para>The following grammar snippet describes how the route statement is constructed</para>
- <programlisting>
- route_stm = "route" "{" actions "}"
- {
- $$ = push($3, &rlist[DEFAULT_RT]);
- }
-
- actions = actions action { $$ = append_action($1, $2}; }
- | action { $$ = $1; }
- action = cmd SEMICOLON { $$ = $1; }
- | SEMICOLON { $$ = 0; }
- cmd = "forward" "(" host ")" { $$ = mk_action(FORWARD_T, STRING_ST, NUMBER_ST, $3, 0)
- | ...
- </programlisting>
- <para>
- A config file can contain one or more "route"
- statements. "route" statement without number will be
- executed first and is called the main route
- statement. There can be additional route statements
- identified by number, these additional route statements can
- be called from the main route statement or another
- additional route statements.
- </para>
- <para>
- Each route statement consists of a set of actions. Actions
- in the route statement are executed step by step in the
- same order in which they appear in the config file. Actions
- in the route statement are delimited by semicolon.
- </para>
- <para>
- Each action consists of one and only one command (cmd in
- the grammar). There are many types of commands defined. We
- don't list all of them here because the list would be too
- long and all the commands are processed in the same
- way. Therefore we show only one example (forward) and
- interested readers might look in <filename>cfg.y</filename>
- file for full list of available commands.
- </para>
- <para>
- Each rule in the grammar contains a section enclosed in
- curly braces. The section is the C code snippet that will
- be executed every time the parser recognizes that rule in
- the config file.
- </para>
- <para>
- For example, when the parser finds
- <function>forward</function> command,
- <function>mk_action</function> function (as specified in
- the grammar snippet above) will be called. The function
- creates a new structure with
- <structfield>type</structfield> field set to FORWARD_T
- representing the command. Pointer to the structure will be
- returned as the return value of the rule.
- </para>
- <para>
- The pointer propagates through <function>action</function>
- rule to <function>actions</function>
- rule. <function>Actions</function> rule will create linked
- list of all commands. The linked list will be then inserted
- into <structfield>rlist</structfield> table. (Function
- <function>push</function> in rule
- <function>route_stm</function>). Each element of the table
- represents one "route" statement of the config file.
- </para>
- <para>
- Each route statement of the configuration file will be
- represented by a linked list of all actions in the
- statement. Pointers to all the lists will be stored in
- rlist array. Additional route statements are identified by
- number. The number also serves as index to the array.
- </para>
- <para>
- When the core is about to execute route statement with
- number n, it will look in the array at position n. If the
- element at position n is not null then there is a linked
- list of commands and the commands will be executed step by
- step.
- </para>
- <para>
- Reply-Route statement is compiled in the same way. Main differences are:
- <itemizedlist>
- <listitem>
- <para>
- Reply-Route statement is executed when a SIP
- <emphasis>REPLY</emphasis> comes (not ,SIP
- <emphasis>REQUEST</emphasis>).
- </para>
- </listitem>
- <listitem>
- <para>
- Only subset of commands is allowed in the
- reply-route statement. (See file
- <filename>cfg.y</filename> for more details).
- </para>
- </listitem>
- <listitem>
- <para>Reply-route statement has it's own array of linked-lists.</para>
- </listitem>
- </itemizedlist>
- </para>
- </section> <!-- route-stm -->
-
- <section id="assign_statement">
- <title>Assign Statement</title>
- <para>
- The server contains many configuration variables. There is
- a section of the config file in which the variables can be
- assigned new value. The section is called The Assign
- Statement. The following grammar snippet describes how the
- section is constructed (only one example will be shown):
- </para>
- <programlisting>
- assign_stm = "children" '=' NUMBER { children_no=$3; }
- | "children" '=' error { yyerror("number expected"); }
- ...
- </programlisting>
- <para>
- The number in the config file is assigned to
- <varname>children_no</varname> variable. The second
- statement will be executed if the parameter is not number
- or is in invalid format and will issue an error and abort
- the server.
- </para>
- </section> <!-- assign-stm -->
-
- <section id="module_statement">
- <title>Module Statement</title>
- <para>
- The module statement allows module loading and
- configuration. There are two commands:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>loadmodule</emphasis> - Load the
- specified module in form of a shared object. The
- shared object will be loaded using
- <function>dlopen</function>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>modparam</emphasis> - It is possible to
- configure a module using this command. The command
- accepts 3 parameters: <emphasis>module
- name</emphasis>, <emphasis>variable name</emphasis>
- and <emphasis>variable value</emphasis>.
- </para>
- </listitem>
- </itemizedlist>
- <para>The following grammar snippet describes the module statement:</para>
- <programlisting>
- module_stm = "loadmodule" STRING
- {
- DBG("loading module %s\n", $2);
- if (load_module($2)!=0) {
- yyerror("failed to load module");
- }
- }
- | "loadmodule" error { yyerror("string expected"); }
- | "modparam" "(" STRING "," STRING "," STRING ")"
- {
- if (set_mod_param($3, $5, PARAM_STR|PARAM_STRING, $7) != 0) {
- yyerror("Can't set module parameter");
- }
- }
- | "modparam" "(" STRING "," STRING "," NUMBER ")"
- {
- if (set_mod_param($3, $5, PARAM_INT, (void*)$7) != 0) {
- yyerror("Can't set module parameter");
- }
- }
- | MODPARAM error { yyerror("Invalid arguments"); }
- </programlisting>
- <para>
- When the parser finds <function>loadmodule</function>
- command, it will execute statement in curly braces. The
- statement will call <function>load_module</function>
- function. The function will load the specified filename
- using <function>dlopen</function>. If
- <function>dlopen</function> was successful, the server will
- look for <structname>exports</structname> structure
- describing the module's interface and register the
- module. For more details see <link
- linkend="module_interface">module section</link>.
- </para>
- <para>
- If the parser finds <function>modparam</function> command,
- it will try to configure the specified variable in the
- specified module. The module must be loaded using
- <function>loadmodule</function> before
- <function>modparam</function> for the module can be used !
- Function <function>set_mod_param</function> will be called
- and will configure the variable in the specified module.
- </para>
- </section> <!-- module-stm -->
- </section> <!-- config-file-struct -->
- </section> <!-- ser-config -->
-
- <section id="iface_config">
- <title>Interface Configuration</title>
- <para>
- The server will try to obtain list of all configured interfaces of
- the host it is running on. If it fails the server tries to convert
- hostname to IP address and will use interface with the IP address
- only.
- </para>
- <para>
- Function <function>add_interfaces</function> will add all
- configured interfaces to the array.
- </para>
- <para>
- Try to convert all interface names to IP addresses, remove duplicates...
- </para>
- </section> <!-- iface-config -->
-
- <section id="daemon">
- <title>Turning into a Daemon</title>
- <para>
- When configured so, SER becomes a daemon during startup. A process
- is called daemon when it hasn't associated controlling
- terminal. See function <function>daemonize</function> in file
- <filename>main.c</filename> for more details. The function does
- the following:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>chroot</emphasis> is performed if necessary. That
- ensures that the server will have access to a particular
- directory and its subdirectories only.
- </para>
- </listitem>
- <listitem>
- <para>
- Server's working directory is changed if the new working
- directory was specified (usually it is /).
- </para>
- </listitem>
- <listitem>
- <para>
- If command line parameter -g was used, the server's group
- ID is changed to that value.
- </para>
- </listitem>
- <listitem>
- <para>
- If command line parameter -u was used, the server's user ID
- is changed to that value.
- </para>
- </listitem>
- <listitem>
- <para>
- Perform <emphasis>fork</emphasis>, let the parent process
- exit. This ensures that we are not a group leader.
- </para>
- </listitem>
- <listitem>
- <para>
- Perform <emphasis>setsid</emphasis> to become a session
- leader and drop the controlling terminal.
- </para>
- </listitem>
- <listitem>
- <para>
- Fork again to drop group leadership.
- </para>
- </listitem>
- <listitem>
- <para>Create a pid file.</para>
- </listitem>
- <listitem>
- <para>Close all opened file descriptors.</para>
- </listitem>
- </itemizedlist>
- </section> <!-- daemon -->
-
- <section id="module_init">
- <title>Module Initialization</title>
- <para>
- The whole config file was parsed, all modules were loaded already
- and can be initialized now. A module can tell the core that it
- needs to be initialized by exporting <function>mod_init</function>
- function. <function>mod_init</function> function of all loaded
- modules will be called now.
- </para>
- </section> <!-- module-init -->
-
- <section id="routing_list_fixing">
- <title>Routing List Fixing</title>
- <para>
- After the whole routing list was parsed, there might be still
- places that can be further processed to speed-up the server. For
- example, several commands accept regular expression as one of their
- parameters. The regular expression can be compiled too and
- processing of compiled expression will be much faster.
- </para>
- <para>
- Another example might be string as parameter of a function. For
- example if you call <function>append_hf("Server: SIP Express
- Router\r\n")</function> from the routing script, the function will
- append a new header field after the last one. In this case, the
- function needs to know length of the string parameter. It could
- call <function>strlen</function> every time it is called, but that
- is not a very good idea because <function>strlen</function> would
- be called every time a message is processed and that is not
- necessary.
- </para>
- <para>
- Instead of that the length of the string parameter could be
- pre-calculated upon server startup, saved and reused later. The
- processing of the request will be faster because
- <function>append_hf</function> doesn't need to call
- <function>strlen</function> every time, I can just reuse the saved
- value.
- </para>
- <para>
- This can be used also for string to int conversions, hostname
- lookups, expression evaluation and so on.
- </para>
- <para>
- This process is called Routing List Fixing and will be done as one
- of last steps of the server startup.
- </para>
- <para>
- Every loaded module can export one or more functions. Each such
- function can have associated a fixup function, which should do
- fixing as described in this section. All such fixups of all loaded
- modules will be called here. That makes it possible for module
- functions to fix their parameters too if necessary.
- </para>
- </section> <!-- rt-list-fix -->
- <section id="stat-init">
- <title>Statistics Initialization</title>
- <para>
- If compiled-in, the core can produce some statistics about itself
- and traffic processed. The statistics subsystem gets initialized
- here, see function <function>init_stats</function>.
- </para>
- </section> <!-- stat-init -->
- <section id="socket_init">
- <title>Socket Initialization</title>
- <para>
- UDP socket initialization depends on <varname>dont_fork</varname>
- variable. If this variable is set (only one process will be
- processing incoming requests) and there are multiple listen
- interfaces, only the first one will be used. This mode is mainly
- for debugging.
- </para>
- <para>
- If the variable is not set, then sockets for all configured
- interfaces will be created and initialized. See function
- <function>udp_init</function> in file
- <filename>udp_server.c</filename> for more details.
- </para>
- </section> <!-- socke-init -->
-
- <section id="forking">
- <title>Forking</title>
- <para>
- The rest of the initialization process depends on value of
- <varname>dont_fork</varname> variable.
- <varname>dont_fork</varname> is a global variable defined in
- <filename>main.c</filename>. We will describe both variants
- separately.
- </para>
- <section id="dont_fork">
- <title><varname>dont_fork</varname> variable is set (not zero)</title>
- <para>
- If <varname>dont_fork</varname> variable is set, the server
- will be operating in special mode. There will be only one
- process processing incoming requests. This is very slow and was
- intended mainly for debugging purposes. The main process will
- be processing all incoming requests itself.
- </para>
- <para>
- The server still needs additional children:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- One child is for the timer subsystem, the child will be
- processing timers independently of the main process.
- </para>
- </listitem>
- <listitem>
- <para>
- FIFO server will spawn another child if enabled. The
- child will be processing all commands coming through
- the fifo interface.
- </para>
- </listitem>
- <listitem>
- <para>If SNMP support was enabled, another child will be created.</para>
- </listitem>
- </itemizedlist>
-
- <para>
- The following initialization will be performed in dont fork
- mode. (look into function <function>main_loop</function> in
- file <filename>main.c</filename>.
- </para>
- <itemizedlist>
- <listitem>
- <para>Another child will be forked for the timer subsystem.</para>
- </listitem>
- <listitem>
- <para>
- Initialize the FIFO server if enabled, this will fork
- another child. For more info about the FIFO server,
- see section The FIFO server.
- </para>
- </listitem>
- <listitem>
- <para>
- Call <function>init_child(0).</function> The function
- performs per-child specific initialization of all
- loaded modules. A module can be initialized though
- <function>mod_init</function> function. The function
- is called <emphasis>BEFORE</emphasis> the server forks
- and thus is common for all children.
- </para>
- <para>
- If there is anything, that needs to be initialized in
- every child separately (for example if each child needs
- to open its own file descriptor), it cannot be done in
- <function>mod_init</function>. To make such
- initialization possible, a module can export another
- initialization function called
- <function>init_child</function>. The function will be
- called in all children <emphasis>AFTER</emphasis> fork
- of the server.
- </para>
- <para>
- And since we are in "dont fork" mode and there will no
- children processing requests (remember the main process
- will be processing all requests), the
- <function>init_child</function> wouldn't be called.
- </para>
- <para>
- That would be bad, because
- <function>child_init</function> might do some
- initialization that must be done otherwise modules
- might not work properly.
- </para>
- <para>
- To make sure that module initialization is complete we
- will call <function>init_child</function> here for the
- main process even if we are not going to fork.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- That's it. Everything has been initialized properly and as the
- last step we will call <function>udp_rcv_loop</function> which
- is the main loop function. The function will be described
- later.
- </para>
- </section> <!-- dont-fork-set -->
- <section id="dont_fork_not_set">
- <title><varname>dont_fork</varname> is not set (zero)</title>
- <para>
- <varname>dont_fork</varname> is not set. That means that the
- server will fork children and the children will be processing
- incoming requests. How many children will be created depends on
- the configuration (<varname>children</varname> variable). The
- main process will be sleeping and handling signals only.
- </para>
- <para>
- The main process will then initialize the FIFO server. The FIFO
- server needs another child to handle communication over FIFO
- and thus another child will be created. The FIFO server will be
- described in more detail later.
- </para>
- <para>
- Then the main process will perform another fork for the timer
- attendant. The child will take care of timer lists and execute
- specified function when a timer hits.
- </para>
- <para>
- The main process is now completely initialized, it will sleep
- in <function>pause</function> function until a signal comes and
- call <function>handle_sigs</function> when such condition
- occurs.
- </para>
-
- <para>
- The following initialization will be performed by each child
- separately:
- </para>
- <para>
- Each child executes <function>init_child</function>
- function. The function will sequentially call
- <function>child_init</function> functions of all loaded
- modules.
- </para>
- <para>
- Because the function is called in each child separately, it can
- initialize per-child specific data. For example if a module
- needs to communicate with database, it must open a database
- connection. If the connection would be opened in
- <function>mod_init</function> function, all the children would
- share the same connection and locking would be necessary to
- avoid conflicts. On the other hand if the connection was opened
- in <function>child_init</function> function, each child will
- have its own connection and concurrency conflicts will be
- handled by the database server.
- </para>
- <para>
- And last, but not least, each child executes
- <function>udp_rcv_loop</function> function which contains the
- main loop logic.
- </para>
-
- </section> <!-- dont-fork-not-set -->
- </section> <!-- forking -->
- </section>
|