Changeset 469 for trunk/user/ksh
- Timestamp:
- Aug 20, 2018, 1:04:16 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/user/ksh/ksh.c
r459 r469 1 /////////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : ksh.c 3 3 // Date : October 2017 4 4 // Author : Alain Greiner 5 /////////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////////////////// 6 6 // This application implements a minimal shell for ALMOS-MKH. 7 7 // 8 8 // This user KSH process contains two POSIX threads: 9 9 // - the "main" thread contains the infinite loop implementing 10 // the children processes termination monitoring using the wait syscall. 11 // - the "interactive" thread contains the infinite loop implementing 12 // 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. 10 // the children processes termination monitoring, using the wait syscall. 11 // - the "interactive" thread contains the infinite loop implementing the command 12 // interpreter attached to the TXT terminal, and handling one KSH command 13 // per iteration. 16 14 // 17 // Note: the children processes are created by the <load> command, and are15 // The children processes are created by the <load> command, and are 18 16 // 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. 23 /////////////////////////////////////////////////////////////////////////////// 17 // A child process can be lauched in foreground or in background: 18 // . when the child process is running in foreground, the KSH process loses 19 // the TXT terminal ownership, that is transfered to the child process. 20 // . when the child process is running in background: the KSH process keeps 21 // the TXT terminal ownership. 22 // 23 // A semaphore is used to synchronize the two KSH threads. At each iteration, 24 // the interactive thread check the semaphore (with a sem_wait). It blocks 25 // and deschedules, if the KSH process loosed the TXT ownership (after a load, 26 // or for any other cause. It unblocks with the following policy: 27 // . if the command is "not a load", the semaphore is incremented by the 28 // cmd_***() function when the command is completed, to allow the KSH interactive() 29 // function to get the next command in the while loop. 30 // . if the command is a "load without &", the TXT is given to the NEW process by the 31 // execve() syscall, and is released to the KSH process when NEW process terminates. 32 // The KSH process is notified and the KSH main() function increments the semahore 33 // to allow the KSH interactive() function to handle commands. 34 // . if the command is a "load with &", the cmd_load() function returns the TXT 35 // to the KSH process and increment the semaphore, when the parent KSH process 36 // returns from the fork() syscall. 37 ///////////////////////////////////////////////////////////////////////////////////////// 24 38 25 39 #include <stdio.h> … … 37 51 #define FIFO_SIZE (1024) // FIFO depth for recursive ls 38 52 39 #define KSH_DEBUG 0 40 41 //////////////////////////////////////////////////////////////////////////////// 53 #define KSH_DEBUG 0 54 #define CMD_LOAD_DEBUG 0 55 56 ////////////////////////////////////////////////////////////////////////////////////////// 42 57 // Structures 43 //////////////////////////////////////////////////////////////////////////////// 58 ////////////////////////////////////////////////////////////////////////////////////////// 44 59 45 60 // one entry in the registered commands array … … 61 76 62 77 63 //////////////////////////////////////////////////////////////////////////////// 78 ////////////////////////////////////////////////////////////////////////////////////////// 64 79 // Global Variables 65 //////////////////////////////////////////////////////////////////////////////// 80 ////////////////////////////////////////////////////////////////////////////////////////// 66 81 67 82 ksh_cmd_t cmd[]; // array of supported commands … … 76 91 sem_t semaphore; // block interactive thread when zero 77 92 78 //////////////////////////////////////////////////////////////////////////////// 93 ////////////////////////////////////////////////////////////////////////////////////////// 79 94 // Shell Commands 80 //////////////////////////////////////////////////////////////////////////////// 95 ////////////////////////////////////////////////////////////////////////////////////////// 81 96 82 97 ///////////////////////////////////////////// … … 454 469 if( (argc < 2) || (argc > 3) ) 455 470 { 456 printf(" usage: %s pathname [&] \n", argv[0] );471 printf(" usage: %s pathname [&] / argc = %d\n", argv[0], argc ); // @@@ 457 472 return; 458 473 } … … 466 481 ksh_pid = getpid(); 467 482 468 #if KSH_DEBUG 469 printf("\n[KSH_DEBUG] in %s : ksh PID %x / path %s / background %d\n", 470 __FUNCTION__, ksh_pid, argv[1], background ); 483 #if CMD_LOAD_DEBUG 484 long long unsigned cycle; 485 get_cycle( &cycle ); 486 printf("\n@@@ %s : KSH PID %x before fork / path %s / background %d / cycle %d\n", 487 __FUNCTION__, ksh_pid, argv[1], background, (int)cycle ); 471 488 #endif 472 489 … … 481 498 else if (ret_fork == 0) // it is the CHILD process 482 499 { 500 501 #if CMD_LOAD_DEBUG 502 get_cycle( &cycle ); 503 printf("\n@@@ %s : CHILD_PID %x after fork, before exec / cycle %d\n", 504 __FUNCTION__ , getpid(), (int)cycle ); 505 #endif 506 483 507 // CHILD process exec NEW process 484 508 ret_exec = execve( pathname , NULL , NULL ); 509 510 #if CMD_LOAD_DEBUG 511 get_cycle( &cycle ); 512 printf("\n@@@ %s : CHILD_PID %x after exec / ret_exec %d / cycle %d\n", 513 __FUNCTION__ , getpid(), ret_exec, (int)cycle ); 514 #endif 485 515 486 516 // this is only executed in case of exec failure … … 494 524 { 495 525 496 #if KSH_DEBUG 497 int sem_value; 498 sem_getvalue( &semaphore , &sem_value ); 499 printf("\n[KSH_DEBUG] in %s : child PID %x / background %d / sem_value %d\n", 500 ret_fork, background, sem_value ); 526 #if CMD_LOAD_DEBUG 527 get_cycle( &cycle ); 528 printf("\n@@@ %s : KSH_PID %x after fork / ret_fork %x / cycle %d\n", 529 __FUNCTION__, getpid(), ret_fork, (int)cycle ); 501 530 #endif 502 531 503 if( background ) // child in background => KSH keepsTXT ownership532 if( background ) // child in background => KSH must keep TXT ownership 504 533 { 505 534 // execve() tranfered TXT ownership to child => give it back to KSH … … 734 763 // This function analyses one command (with arguments), executes it, and returns. 735 764 //////////////////////////////////////////////////////////////////////////////////// 736 static void parse( char * buf )765 static void __attribute__ ((noinline)) parse( char * buf ) 737 766 { 738 767 int argc = 0; … … 758 787 } 759 788 789 // analyse command type 760 790 if (argc > 0) 761 791 { … … 765 795 766 796 // try to match typed command 767 for (i = 0 ; cmd[i].name; i++)797 for (i = 0 ; cmd[i].name ; i++) 768 798 { 769 799 if (strcmp(argv[0], cmd[i].name) == 0) … … 788 818 static void interactive() 789 819 { 790 char c; // read character 791 char buf[CMD_MAX_SIZE]; // buffer for one command 792 unsigned int end_command; // last character found in a command 793 unsigned int count; // pointer in command buffer 794 unsigned int i; // index for loops 795 unsigned int state; // escape sequence state 796 797 // @@@ 798 // parse( "load /bin/user/fft.elf" ); 799 // @@@ 820 char c; // read character 821 char buf[CMD_MAX_SIZE]; // buffer for one command 822 unsigned int end_command; // last character found in a command 823 unsigned int count; // pointer in command buffer 824 unsigned int i; // index for loops 825 unsigned int state; // escape sequence state 826 827 /* This can be used to remove interactive mode 828 829 for( i=1 ; 1 ; i += 2) 830 { 831 if( sem_wait( &semaphore ) ) 832 { 833 printf("\n[ksh error] cannot found semafore\n" ); 834 exit( 1 ); 835 } 836 else 837 { 838 printf("\n[ksh] %d for sort\n", i ); 839 } 840 strcpy( buf , "load /bin/user/sort.elf" ); 841 parse( buf ); 842 843 if( sem_wait( &semaphore ) ) 844 { 845 printf("\n[ksh error] cannot found semafore\n" ); 846 exit( 1 ); 847 } 848 else 849 { 850 printf("\n[ksh] %d for fft\n", i+1 ); 851 } 852 strcpy( buf , "load /bin/user/fft.elf" ); 853 parse( buf ); 854 } 855 856 */ 800 857 801 858 enum fsm_states … … 826 883 state = NORMAL; 827 884 828 // block if the KSH process is not the TXT owner829 // - if the command is not a "load"830 // the semaphore must be released by the cmd_***()831 // - if the command is a load, it depends on832 // the "background" argument833 sem_wait( &semaphore );885 // decrement semaphore, and block if the KSH process is not the TXT owner 886 if ( sem_wait( &semaphore ) ) 887 { 888 printf("\n[ksh error] cannot found semafore\n" ); 889 exit( 1 ); 890 } 834 891 835 892 // display prompt on a new line … … 991 1048 int status; // child process termination status 992 1049 int child_pid; // child process identifier 993 int parent_pid; // parent process identifier 994 pthread_t trdid; // kernel allocated index for interactive thread1050 int parent_pid; // parent process identifier (i.e. this process) 1051 pthread_t trdid; // interactive thread identifier (unused) 995 1052 unsigned int is_owner; // non-zero if KSH process is TXT owner 996 1053 … … 1005 1062 1006 1063 // initializes the semaphore used to unblock the interactive thread 1007 sem_init( &semaphore , 0 , 1 ); 1064 if ( sem_init( &semaphore , 0 , 1 ) ) 1065 { 1066 printf("\n[KSH ERROR] cannot initialize semaphore\n" ); 1067 exit( 1 ); 1068 } 1069 1070 printf("\n@@@ in KSH %s : &semaphore = %x\n", __FUNCTION__, &semaphore ); 1008 1071 1009 1072 // initialize interactive thread attributes
Note: See TracChangeset
for help on using the changeset viewer.