source: trunk/user/init/init.c @ 676

Last change on this file since 676 was 676, checked in by alain, 3 years ago

Introduce chat application to test the named pipes.

File size: 6.3 KB
RevLine 
[427]1///////////////////////////////////////////////////////////////////////////////////////
2// File   :  init.c
3// Date   :  January 2018
4// Author :  Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// This single thread application implement the "init" process for ALMOS-MKH.
[434]7// It uses the fork/exec syscalls to create N KSH child processes
[659]8// (one child process per user TXT terminal).
9// Then calls the wait() function to block, and recreate any child KSH process
[434]10// that has been deleted, using a new fork/exec.
[427]11///////////////////////////////////////////////////////////////////////////////////////
12
[444]13#include <unistd.h>
[427]14#include <stdlib.h>
15#include <stdio.h>
16#include <pthread.h>
[445]17#include <almosmkh.h>
[574]18#include <hal_macros.h>
[444]19#include <sys/wait.h>
[659]20#include <shared_syscalls.h>
[427]21
[676]22#define DEBUG_PROCESS_INIT    0
[440]23
[574]24////////////////
[475]25int main( void )
[427]26{
[659]27    unsigned int  i;
[438]28    int           ret_fork;      // fork return value 
29    int           ret_exec;      // exec return value 
30    int           rcv_pid;       // pid received from the wait syscall
31    int           status;        // used by the wait syscall
32    char          string[64];    // log messages on kernel TXT0
[427]33
[574]34#if DEBUG_PROCESS_INIT
[623]35display_string("[init] process enters");
[574]36#endif
37
[676]38    // get number of TXT channels from hard configuration
[659]39    hard_config_t config;     
[676]40
[659]41    get_config( &config );
42
43    unsigned int  txt_channels = config.txt_channels;
44
[427]45    // check number of TXT channels
[659]46    if( txt_channels < 2 )
[445]47    {
[659]48        snprintf( string , 64 ,
[676]49        "\n[init ERROR] number of TXT channels must be larger than 1");
[659]50        display_string( string );
[445]51        exit( EXIT_FAILURE );
52    }
[427]53
54    // create the KSH processes (one per user terminal)
[659]55    for( i = 1 ; i <  txt_channels ; i++ )
[427]56    {
[434]57        // INIT process fork process CHILD[i]
58        ret_fork = fork();
59
[436]60        if( ret_fork < 0 )   // error in fork
[427]61        {
[437]62            // INIT display error message 
[659]63            snprintf( string , 64 , 
[676]64            "\n[init ERROR] cannot fork child[%d] => suicide" , i );
[427]65            display_string( string );
66
[436]67            // INIT suicide
[659]68            exit( EXIT_FAILURE );
[427]69        }
[434]70        else if( ret_fork == 0 )                    // we are in CHILD[i] process
[427]71        {
[676]72
73#if DEBUG_PROCESS_INIT
74            snprintf( string , 64 ,
75            "\n[init] CHILD[%d] process forked / call execve", i );
76            display_string( string );
77#endif
[434]78            // CHILD[i] process exec process KSH[i]
[444]79            ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
[434]80
81            if ( ret_exec )   // error in exec             
[427]82            {
[437]83                // CHILD[i] display error message
[435]84                snprintf( string , 64 , 
[676]85                "\n[init ERROR] CHILD[%d] cannot exec KSH" , i );
[434]86                display_string( string );
[659]87
88                // CHILD[i] suicide
89                exit( EXIT_FAILURE );
[427]90            }
91        }
[434]92        else                                      // we are in INIT process
93        {
[457]94            // INIT display CHILD[i] process PID
[659]95            snprintf( string , 64 ,
[676]96            "\n[init] (pid 0x1) create ksh[%d] (pid %x)", i , ret_fork ); 
[457]97            display_string( string );
[588]98
[659]99            // wait signal from KSH[i] before creating KSH[i+1]
[588]100            pause();
[434]101        }
102    } 
[440]103 
[442]104#if DEBUG_PROCESS_INIT
[528]105{
106    unsigned int  x;             // cluster x coordinate
107    unsigned int  y;             // cluster y coordinate
108    unsigned int  cxy;           // cluster identifier
109    unsigned int  lid;           // core local index
[434]110
[676]111    unsigned int  x_size       = config.x_size;
112    unsigned int  y_size       = config.y_size;
113    unsigned int  ncores       = config.ncores;
114
[528]115    // INIT displays processes and threads in all clusters
116    for( x = 0 ; x < x_size ; x++ )
[440]117    {
[588]118        for( y = 0 ; y < y_size ; y++ )
[581]119        {
120            cxy = HAL_CXY_FROM_XY( x , y );
[635]121            display_cluster_processes( cxy , 0 );
[581]122            for( lid = 0 ; lid < ncores ; lid++ )
123            { 
124                display_sched( cxy , lid );
125            }
[440]126        }
127    }
[457]128}
[440]129#endif
130
[435]131    // This loop detects the termination of the KSH[i] processes,
[436]132    // and recreate a new KSH[i] process when required.
[427]133    while( 1 )
134    {
[435]135        // block on child processes termination
[436]136        rcv_pid = wait( &status );
[427]137
[435]138        if( WIFSTOPPED( status ) )                         // stopped => unblock it
139        {
140            // display string to report unexpected KSH process block
[623]141            snprintf( string , 64 , "[init] KSH process %x stopped => unblock it" , rcv_pid );
[435]142            display_string( string ); 
143
[440]144            // TODO : unblock KSH [AG]
[435]145
[436]146        }  // end KSH stopped handling
147
[435]148        if( WIFSIGNALED( status ) || WIFEXITED( status ) )  // killed => recreate it
149        {
[437]150            // display string to report KSH process termination
[623]151            snprintf( string , 64 , "[init] KSH process %x terminated => recreate", rcv_pid );
[435]152            display_string( string ); 
[436]153
154            // INIT process fork a new CHILD process
155            ret_fork = fork();
156
157            if( ret_fork < 0 )                          // error in fork
158            {
[437]159                // INIT display error message
[623]160                snprintf( string , 64 , "[init ERROR] cannot fork child => suicide");
[436]161                display_string( string );
162
163                // INIT suicide
164                exit( 0 );
165            }
166            else if( ret_fork == 0 )                    // we are in CHILD process
167            {
168                // CHILD process exec process KSH
[444]169                ret_exec = execve( "/bin/user/ksh.elf" , NULL , NULL ); 
[436]170
171                if ( ret_exec )   // error in exec             
172                {
173                    // CHILD display error message on TXT0 terminal
[623]174                    snprintf( string , 64 , "[init ERROR] CHILD cannot exec KSH" );
[436]175                    display_string( string );
176                }
177            }
178            else                                       // we are in INIT process
179            {
[442]180                // INIT display new KSH process PID
[623]181                snprintf( string , 64 , "[init] re-created KSH / pid = %x", ret_fork ); 
[436]182                display_string( string );
183            }
[438]184        } // end KSH kill handling
[427]185
[438]186    }  // end while waiting KSH[i] termination
187
[427]188} // end main()
189
Note: See TracBrowser for help on using the repository browser.