Changeset 457 for trunk/user/ksh


Ignore:
Timestamp:
Aug 2, 2018, 11:47:13 AM (6 years ago)
Author:
alain
Message:

This version modifies the exec syscall and fixes a large number of small bugs.
The version number has been updated (0.1)

Location:
trunk/user/ksh
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/user/ksh/Makefile

    r445 r457  
    1111OBJS = build/ksh.o
    1212
    13 INCLUDES = -I.                      \
    14            -I$(LIBC_INCLUDE)        \
    15            -I$(LIBPTHREAD_INCLUDE)  \
    16            -I$(LIBALMOSMKH_INCLUDE) \
     13INCLUDES = -I.                       \
     14           -I$(LIBC_INCLUDE)         \
     15           -I$(LIBPTHREAD_INCLUDE)   \
     16           -I$(LIBALMOSMKH_INCLUDE)  \
     17           -I$(LIBSEMAPHORE_INCLUDE) \
    1718           -I$(SHARED_INCLUDE)
    1819
     
    2021
    2122build/ksh.elf : $(OBJS) ksh.ld
    22         $(LD) -o $@ -T ksh.ld $(OBJS) -L$(LIBC) -L$(LIBPTHREAD) -L$(LIBALMOSMKH) -lc -lpthread -lalmosmkh -lpthread -lc
     23        $(LD) -o $@ -T ksh.ld $(OBJS) -L$(LIBC) -L$(LIBPTHREAD) -L$(LIBALMOSMKH) -L$(LIBSEMAPHORE) \
     24    -lc -lpthread -lalmosmkh -lpthread -lsemaphore -lc
    2325        $(DU) -D $@ > $@.txt
    2426
  • trunk/user/ksh/ksh.c

    r446 r457  
    44// Author :  Alain Greiner
    55///////////////////////////////////////////////////////////////////////////////
    6 // This applications implement a minimal shell for ALMOS-MKH.
    7 // This user process contains two POSIX threads:
     6// This application implements a minimal shell for ALMOS-MKH.
     7//
     8// This user KSH process contains two POSIX threads:
    89// - the "main" thread contains the infinite loop implementing
    9 //   the children processes termination monitoring (children processes
    10 //   are created by the <load> command and attached to the KSH TXT terminal).
     10//   the children processes termination monitoring using the wait syscall.
    1111// - the "interactive" thread contains the infinite loop implementing
    1212//   the command interpreter attached to the TXT terminal.
     13//   This "interactive" thread block and deschedules when the KSH process
     14//   loses the TXT terminal ownership. It is reactivated when the KSH
     15//   process returns in background.
     16//
     17// Note: the children processes are created by the <load> command, and are
     18// attached to the same TXT terminal as the KSH process itself.
     19// . A child process can be lauched in foreground: the KSH process loses
     20//   the TXT terminal ownership, that is transfered to the new process.
     21// . A child process can be lauched in background: the KSH process keeps
     22//   the TXT terminal ownership. that is transfered to the new process.
    1323///////////////////////////////////////////////////////////////////////////////
    1424
     
    2030#include <unistd.h>
    2131#include <almosmkh.h>
     32#include <semaphore.h>
    2233
    2334#define CMD_MAX_SIZE   (256)    // max number of characters in one command
     
    2536#define MAX_ARGS           (32)     // max number of arguments in a command
    2637#define FIFO_SIZE      (1024)   // FIFO depth for recursive ls
     38
     39#define KSH_DEBUG      0
    2740
    2841////////////////////////////////////////////////////////////////////////////////
     
    5972unsigned int    ptr;                      // read pointer in log_entries[]
    6073
    61 pthread_attr_t  attr;                     // monitor thread attributes
     74pthread_attr_t  attr;                     // interactive thread attributes
     75
     76sem_t           semaphore;                // block interactive thread when zero
    6277
    6378////////////////////////////////////////////////////////////////////////////////
     
    119134*/
    120135
     136    // release semaphore to get next command
     137    sem_post( &semaphore );
     138
    121139}   // end cmd_cat()
    122140
     
    135153
    136154    printf("  error: not implemented yet\n");
    137 /*
    138         path = argv[1];
    139 
    140         if (chdir(path) == -1)
    141     {
    142                 printf("  error: cannot cd to %s\n", path);
    143         }
    144 */
     155
     156    // release semaphore to get next command
     157    sem_post( &semaphore );
    145158
    146159}   // end cmd_cd()
     
    237250*/
    238251
     252    // release semaphore to get next command
     253    sem_post( &semaphore );
     254
    239255}   // end cmd_cp()
    240256
     
    343359        printf("  usage: display (vmm/sched/process/vfs/chdev/txt) [arg2] [arg3]\n");
    344360    }
     361
     362    // release semaphore to get next command
     363    sem_post( &semaphore );
     364
    345365} // end cmd_display()
    346366
     
    367387                printf("  error: cannot find process %x\n", pid );
    368388        }
     389
     390    // release semaphore to get next command
     391    sem_post( &semaphore );
     392
    369393}  // end cmd_fg()
    370394
     
    385409                printf("\t%s\t : %s\n", cmd[i].name , cmd[i].desc);
    386410        }
     411
     412    // release semaphore to get next command
     413    sem_post( &semaphore );
     414
    387415}   // end cmd_help()
    388416
     
    409437                printf("  error: process %x cannot be killed\n", pid );
    410438        }
     439
     440    // release semaphore to get next command
     441    sem_post( &semaphore );
     442
    411443}   // end cmd_kill()
    412444
     
    419451        char               * pathname;           // path to .elf file
    420452    unsigned int         background;         // background execution if non zero
    421     int                  status;             // new process exit status
    422453
    423454        if( (argc < 2) || (argc > 3) ) 
     
    435466    ksh_pid = getpid();
    436467
     468#if KSH_DEBUG
     469printf("\n[KSH_DEBUG] in %s : ksh PID %x / path %s / background %d\n",
     470__FUNCTION__, ksh_pid, argv[1], background );
     471#endif
     472
    437473    // KSH process fork CHILD process
    438474        ret_fork = fork();
    439475
    440     if ( ret_fork < 0 )          // it is a failure reported to KSH
     476    if ( ret_fork < 0 )     // it is a failure reported to KSH
    441477    {
    442478        printf("  error: ksh process unable to fork\n");
    443479        return;
    444480    }
    445     else if (ret_fork == 0)      // it is the CHILD process
     481    else if (ret_fork == 0) // it is the CHILD process
    446482    {
    447483        // CHILD process exec NEW process
     
    455491        }   
    456492        }
    457     else                        // it is the parent KSH : ret_fork is the new process PID
    458     {
    459         // give back terminal ownership to KSH
    460         // when new process created in background
    461         if( background )   fg( ksh_pid );
    462 
    463         // return to command interpreter
    464         return;
     493    else                    // it is the KSH process : ret_fork is the new process PID
     494    {
     495
     496#if KSH_DEBUG
     497int sem_value;
     498sem_getvalue( &semaphore , &sem_value );
     499printf("\n[KSH_DEBUG] in %s : child PID %x / background %d / sem_value %d\n",
     500ret_fork, background, sem_value  );
     501#endif
     502
     503        if( background )        // child in background =>  KSH keeps TXT ownership
     504        {
     505            // execve() tranfered TXT ownership to child => give it back to KSH
     506            fg( ksh_pid );
     507
     508            // release semaphore to get next command
     509            sem_post( &semaphore );
     510        }
    465511    }
    466512}   // end cmd_load
     
    476522                printf(" - %d\t: %s\n", i, &log_entries[i].buf);
    477523        }
    478 }
     524
     525    // release semaphore to get next command
     526    sem_post( &semaphore );
     527
     528} // end cmd_log()
     529
    479530
    480531////////////////////////////////////////////
     
    509560        closedir(dir);
    510561*/
    511 }
     562
     563    // release semaphore to get next command
     564    sem_post( &semaphore );
     565
     566} // end cmd_ls()
    512567
    513568///////////////////////////////////////////////
     
    525580
    526581    printf("  error: not implemented yet\n");
    527 /*
    528         if ( mkdir( path, 0x700) == -1 )
    529     {
    530                 printf("  error: cannot create directory %s\n", path);
    531         }
    532 */
    533 }
     582
     583    // release semaphore to get next command
     584    sem_post( &semaphore );
     585
     586} // end cmd_mkdir()
    534587
    535588////////////////////////////////////////////
     
    545598    printf("  error: not implemented yet\n");
    546599   
    547 /*
    548         int ret = giet_fat_rename(argv[1], argv[2]);
    549         if (ret < 0)
    550         {
    551                 printf("  error : cannot move %s to %s / err = %d\n", argv[1], argv[2], ret );
    552         }
    553 */
    554 
    555 }
     600    // release semaphore to get next command
     601    sem_post( &semaphore );
     602
     603}  // end cmd_mv
    556604
    557605/////////////////////////////////////////////
     
    574622                printf("%s\n", buf);
    575623        }
    576 }
     624
     625    // release semaphore to get next command
     626    sem_post( &semaphore );
     627
     628}  // end cmd_pwd()
    577629
    578630////////////////////////////////////////////
     
    590642
    591643    printf("  error: not implemented yet\n");
    592 /*
    593         if (remove(path) == -1)
    594     {
    595                 printf("  error: cannot remove %s\n", path);
    596         }
    597 */
    598 
    599 }
     644
     645    // release semaphore to get next command
     646    sem_post( &semaphore );
     647
     648}  // end_cmd_rm()
    600649
    601650///////////////////////////////////////////////
    602651static void cmd_rmdir( int argc , char **argv )
    603652{
     653    // same as cmd_rm()
    604654        cmd_rm(argc, argv);
    605655}
     
    624674        printf("  error: core[%x,%d] not found\n", cxy, lid );
    625675    }
    626 }
     676
     677    // release semaphore to get next command
     678    sem_post( &semaphore );
     679
     680}  // end cmd_trace
    627681
    628682///////////////////////////////////////////////
     
    645699        printf("  error: core[%x,%d] not found\n", cxy, lid );
    646700    }
    647 }
    648 
    649 //////////////////////////////////////////////////////////////////
     701
     702    // release semaphore to get next command
     703    sem_post( &semaphore );
     704
     705}  // end cmd_untrace()
     706
     707///////////////////////////////////////////////////////////////////////////////////
    650708// Array of commands
    651 //////////////////////////////////////////////////////////////////
     709///////////////////////////////////////////////////////////////////////////////////
    652710
    653711ksh_cmd_t cmd[] =
     
    660718        { "load",    "load an user application",                        cmd_load    },
    661719        { "help",    "list available commands",                         cmd_help    },
    662         { "kill",    "kill an application (all threads)",               cmd_kill    },
     720        { "kill",    "kill a process (all threads)",                    cmd_kill    },
    663721        { "log",     "list registered commands",                        cmd_log     },
    664722        { "ls",      "list directory entries",                          cmd_ls      },
     
    674732
    675733////////////////////////////////////////////////////////////////////////////////////
    676 // This function analyses one command (with arguments), execute it, and return.
     734// This function analyses one command (with arguments), executes it, and returns.
    677735////////////////////////////////////////////////////////////////////////////////////
    678 static void parse(char *buf)
     736static void parse( char * buf )
    679737{
    680738        int argc = 0;
     
    717775                }
    718776
    719                 if (!found)
    720         {
    721                         printf("  undefined command <%s>\n", argv[0]);
     777                if (!found)  // undefined command
     778        {
     779                        printf("  error : undefined command <%s>\n", argv[0]);
     780
     781            // release semaphore to get next command
     782            sem_post( &semaphore );
    722783                }
    723784        }
     
    729790        char         c;                                           // read character
    730791        char         buf[CMD_MAX_SIZE];           // buffer for one command
    731         unsigned int count;                               // pointer in buf
     792    unsigned int end_command;             // last character found in a command
     793        unsigned int count;                               // pointer in command buffer
    732794        unsigned int i;                                           // index for loops
     795        unsigned int state;                   // escape sequence state
     796
     797char string[80];
    733798
    734799        enum fsm_states
    735800    {
    736                 NORMAL,
    737                 ESCAPE,
    738                 BRAKET,
     801                NORMAL = 0,
     802                ESCAPE = 1,
     803                BRAKET = 2,
    739804        };
    740805
    741         // initialize command buffer
    742         memset( buf, 0x20 , sizeof(buf) );
    743         count = 0;
    744 
    745         // display first prompt
    746         printf("# ");
    747 
    748         // This lexical analyser writes one command line in the buf buffer.
    749         // It is implemented as a 3 states FSM to handle the following sequences:
     806        // This lexical analyser writes one command line in the command buffer.
     807        // It is implemented as a 3 states FSM to handle the following escape sequences:
    750808        // - ESC [ A : up arrow
    751809        // - ESC [ B : down arrow
     
    757815        // - BRAKET : the wo characters (ESC,[) have been found
    758816
    759         unsigned int state = NORMAL;
    760 
    761 // @@@
    762 parse("load /bin/user/idbg.elf");
    763 // @@@
    764 
     817    // external loop on the commands
     818    // the in teractive thread should not exit this loop
    765819        while (1)
    766820        {
    767                 c = (char)getchar();
    768 
    769         if( c == 0 ) continue;
    770 
    771                 switch (state)
    772                 {
    773                         case NORMAL:
    774                         {
     821            // initialize command buffer
     822            memset( buf, 0x20 , sizeof(buf) );   // TODO useful ?
     823            count = 0;
     824            state = NORMAL;
     825
     826        // block if the KSH process is not the TXT owner
     827        // - if the command is not a "load"
     828        //   the semaphore must be released by the cmd_***()
     829        // - if the command is a load, it depends on
     830        //   the "background" argument
     831        sem_wait( &semaphore );
     832
     833        // display prompt on a new line
     834        printf("\n[ksh] ");
     835 
     836        end_command = 0;
     837
     838        // internal loop on characters in one command
     839        while( end_command == 0 )
     840        {
     841            // get one character from TXT_RX
     842                c = (char)getchar();
     843
     844            if( c == 0 ) continue;
     845
     846                    if( state == NORMAL )  // we are not in an escape sequence
     847                    {
    775848                                if ((c == '\b') || (c == 0x7F))  // backspace => remove one character
    776849                                {
    777                                         if (count > 0) {
    778                                                 printf("\b \b");
    779                                                 count--;
     850                                    if (count > 0)
     851                    {
     852                                        printf("\b \b");
     853                                        count--;
     854                                    }
     855                                }
     856                                else if (c == '\n')                  // new line => end of command
     857                                {
     858                                    if (count > 0)               // analyse & execute command
     859                                    {
     860                                            // complete command with NUL character
     861                                            buf[count] = 0;
     862                        count++;
     863
     864                                        // register command in log arrays
     865                                            strcpy(log_entries[ptw].buf, buf);
     866                                            log_entries[ptw].count = count;
     867                                            ptw = (ptw + 1) % LOG_DEPTH;
     868                                            ptr = ptw;
     869
     870                        // echo character
     871                        putchar( c );
     872
     873                                            // call parser to analyse and execute command
     874                                            parse( buf );
     875                                    }
     876                    else                         // no command registered
     877                    {
     878                        // release semaphore to get next command
     879                        sem_post( &semaphore );
     880                    }
     881
     882                    // exit internal loop on characters
     883                    end_command = 1;
     884                }
     885                            else if (c == '\t')             // tabulation => do nothing
     886                                {
     887                            }
     888                            else if (c == (char)0x1B)       // ESC => start an escape sequence
     889                            {
     890                    state = ESCAPE;
     891                            }
     892                            else                                               // normal character
     893                                {
     894                                    if (count < sizeof(buf) - 1)
     895                                    {
     896                        // register character in command buffer
     897                                            buf[count] = c;
     898                                            count++;
     899
     900                        // echo character
     901                        putchar( c );
    780902                                        }
    781903                                }
    782                                 else if (c == '\n')      // new line => call parser to execute command
    783                                 {
    784                                         if (count > 0)
    785                                         {
    786                                                 // complete command
    787                                                 buf[count] = '\0';
    788 
    789                                                 // register command in log arrays
    790                                                 strcpy(log_entries[ptw].buf, buf);
    791                                                 log_entries[ptw].count = count;
    792                                                 ptw = (ptw + 1) % LOG_DEPTH;
    793                                                 ptr = ptw;
    794 
    795                                                 // execute command
    796                                                 printf("\n");
    797                                                 parse((char *)&buf);
    798 
    799                                                 // reinitialise buffer and display prompt
    800                                                 for ( i = 0 ; i < sizeof(buf) ; i++ ) buf[i] = 0x20;
    801                                                 count = 0;
    802                                                 printf("# ");
    803                                         }
    804                     else
    805                     {
    806                         printf("\n# ");
    807                     }
    808                                 }
    809                                 else if (c == '\t')     // tabulation => do nothing
    810                                 {
    811                                 }
    812                                 else if (c == (char)0x1B)       // ESC => start an escape sequence
    813                                 {
    814                                         state = ESCAPE;
    815                                 }
    816                                 else                                     // register character in command buffer
    817                                 {
    818                                         if (count < sizeof(buf) - 1)
    819                                         {
    820                                                 putchar( c );
    821                                                 buf[count] = c;
    822                                                 count++;
    823                                         }
    824                                 }
    825                                 break;
    826904                        }
    827                         case ESCAPE:
     905                        else if( state == ESCAPE ) 
    828906                        {
    829907                                if (c == '[')           //  valid sequence => continue
     
    835913                                        state = NORMAL;
    836914                                }
    837                                 break;
    838915                        }
    839                         case BRAKET:
     916                        else if( state == BRAKET )
    840917                        {
    841918                                if (c == 'D')   // valid  LEFT sequence => move buf pointer left
     
    900977                                        state = NORMAL;
    901978                                }
    902                                 break;
    903979                        }
    904                 }
    905         }
     980                }  // end internal while loop on characters
     981        }  // end external while loop on commands
    906982}  // end interactive()
    907983
     
    912988    unsigned int lid;             // core identifier for this KSH main thread
    913989    int          status;          // child process termination status
    914     int          pid;             // chils process identifier
     990    int          child_pid;       // child process identifier
     991    int          parent_pid;      // parent process identifier
    915992    pthread_t    trdid;           // kernel allocated index for interactive thread
     993    unsigned int is_owner;        // non-zero if KSH process is TXT owner
    916994
    917995    // initialize log buffer
     
    920998        ptr   = 0;
    921999
     1000    // get KSH process pid and core
     1001    parent_pid = getpid();
    9221002    get_core( &cxy , & lid );
     1003
    9231004        printf( "\n\n~~~ KSH on core[%x,%d] ~~~\n\n", cxy , lid );
     1005
     1006    // initializes the semaphore used to unblock the interactive thread
     1007    sem_init( &semaphore , 0 , 1 );
    9241008
    9251009    // initialize interactive thread attributes
     
    9361020    while( 1 )
    9371021    {
    938         pid = wait( &status );
    939 
    940 #if 0
    941         if     ( WIFEXITED  (status) ) printf("\n[KSH] process %x exited\n" , pid );
    942         else if( WIFSIGNALED(status) ) printf("\n[KSH] process %x killed\n" , pid );
    943         else if( WIFSTOPPED (status) ) printf("\n[KSH] process %x stopped\n", pid );
    944         else                           printf("\n[KSH] process %x strange\n", pid ); 
     1022        // wait children termination
     1023        child_pid = wait( &status );
     1024
     1025#if KSH_DEBUG
     1026if( WIFEXITED  (status) ) printf("\n[KSH] child process %x exited\n" , child_pid );
     1027if( WIFSIGNALED(status) ) printf("\n[KSH] child process %x killed\n" , child_pid );
     1028if( WIFSTOPPED (status) ) printf("\n[KSH] child process %x stopped\n", child_pid );
    9451029#endif
    9461030
     1031        // release semaphore if KSH process is TXT owner, to unblock interactive thread
     1032        is_fg( parent_pid , &is_owner );
     1033        if( is_owner ) sem_post( &semaphore );
     1034
    9471035    }
    9481036}  // end main()
Note: See TracChangeset for help on using the changeset viewer.