Experiment 1 implements a simple shell with Parameters
1. Experiment Name, experiment number, and specific name
In experiment 1, a simple shell with parameters is implemented based on the framework of 1-5 on the 9th page of the textbook, and a simple shell with parameters can be input. The original implementation cannot contain parameters. The number of parameters that can be carried by the input command is limited only by the system keyboard input buffer length (and shell input buffer length). The default length of the buffer is 4096 bytes.
2. Experiment description
1. correctly understand and use the system to call fork (), execve () and waitpid (), especially the execve () functions.
The fork () function creates a new process. A new process is a so-called child process. It is a "clone" of the process (parent process) that executes the fork () function. That is to say, the programs executed by the child process are exactly the same as those of the parent process. If the fork () function returns 0, it indicates that it is in the child process. If the returned value is greater than 0, it indicates that it is in the parent process. The returned value is the ID of the child process. Therefore, the return value of Fork () can be used to divide program segments that are only suitable for execution by Parent and Child processes. If the fork () function returns a value of-1, an error occurs.
If a child process only runs the same program as the parent process, it is of limited use. To allow a child process to run a program different from the parent process, you must call the execve function, which is the basis of all other exec functions. The execve function replaces the program that calls its process with the program specified by the parameters of the execve function. After the execve function is successfully run, the process starts to run the new program, that is, the program specified by the parameters of the execve function.
Execve function prototype: int execve (const char * path, const char * argv [], const char * envp []);
Where:
Path: The Path Name of the program to be executed, such as "/bin/ls", "cd", and "/usr/bin/GCC.
Argv: a parameter table, such as the command line parameters-L and-A that can be included in the LS command. Note that the first element of argv must be the path name of the program (command) to be executed.
Envp: Environment Variable table for the command to be executed. Real parameters can be null or the system environment variable Environ. Note: Because environ is provided by the system and is an external variable, you must use "extern" to describe it.
Example:
Char * argv [] = {"GCC", "-g", "-c", "Hello. C", null };
Char * argv1 [] = {"/bin/ls", "-L", "-A", null };
Execve ("/usr/bin/GCC", argv, Environ); // compile the program "Hello. C"
Execve ("/bin/ls", argv1, null); // execute the command "ls-l-"
Execve ("/usr/ls", argv1, null); // error, because the directory/usr/has no ls program.
// Note that only LS is useful in the first string "/bin/ls" in argv1.
The system calls waitpid () to wait for the child process to end and obtain the running status of the child process. For details, refer to Chapter 8. This experiment only uses it to make the parent process wait for the child process to end, so it is enough to maintain the 1-5 usage of the program.
(2) construct the parameters of the execve function based on the input of a simple shell.
According to program 1-5, the array Buf saves user input, including commands and parameters. Because the command names and parameters of shell commands are separated by spaces, spaces can be used as delimiters. Through a loop, the commands in the Buf array and parameters can be separated in sequence and assigned to the appropriate pointer values of each element of the array argv. The last pointer to the argv array must be null. Execve (argv [0], argv, Environ) can be called to execute user input commands.
Tip: the string pointed to by each pointer in the argv array can directly use the Buf storage space without additional memory allocation.
3. The main principles, concepts, algorithms, execution processes or techniques of design and implementation, and necessary comments and descriptions.
# Include "apue. H"
# Include <sys/Wait. H>
# Include <unistd. h>
Int main ()
{
Charbuf [maxline];
Char * envp [] = {"Path =/bin", null };
Char * argv [] = {null };
Charstr [1, 4096] [2, 256];
Inti, J, K, M, status;
Pid_t PID;
Char path [256];
Printf ("% ");
While (fgets (BUF, maxline, stdin )! = NULL ){
Memset (path, 0, sizeof (PATH); // Initialization
If (BUF [strlen (BUF)-1] = '\ n ')
Buf [strlen (BUF)-1] = 0;
J = I = k = 0;
While (BUF [J]! = '\ 0 '){
If (BUF [J]! = ''){
For (I = J; Buf [I]! = ''& Buf [I]! = '\ 0'; I ++)
STR [k] [I-j] = Buf [I];
STR [k] [I-j] = '\ 0 ';
K ++;
J = I;
} Else {
J ++;
}
}
For (I = 0; I <K; I ++)
Argv [I] = STR [I];
Argv [k] = NULL;
Strcat (path, argv [0]);
If (pid = fork () <0 ){
Err_sys ("forkerror ");
} Elseif (pid = 0 ){
Execve (path, argv, envp );
Err_ret ("Couldn 'texecute: % s", argv [0]);
Exit (127 );
}
If (pid = waitpid (PID, & status, 0) <0)
Err_sys ("waitpiderror ");
Printf ("% ");
}
Exit (0 );
}
3. Experiment results
Common commands such as/bin/LS,/usr/bin/GCC are implemented. If an error command is entered, the system prompts an error and enters the next command receiving status. You can use ctrl-C and Ctrl-\ to end a simple shell.
Source program name: prg1.c
Executable program name: prg1
Compilation Method: GCC prg1.c error. C-o prg1
Running example:./prg1
/Bin/LS-l
For example: