Write a simple Shell 2 by yourself: run the program

Source: Internet
Author: User

Through the previous study, we learned what shell is and its classification and functions. Now we will learn how shell executes the program, that is, the first function of shell. Here we first understand how shell executes the program, learn the relevant knowledge (what is a process, how to create a process, how to run the program), and then implement this function, such a simple shell is born (I call this shell a shell, ash for short ).

What is a process?

How does one run a program in Linux? This looks easy: first log on, then shell prints the prompt, enter the command and press the Enter key, and the program starts running immediately. When the program ends, shell prints a new prompt. But how are these implemented? What does Shell do? What does the kernel do? What is a program? What does running a program mean?
A program is a sequence of machine commands stored in files. Running a program means to load the machine command sequence into the memory and then let the processor execute these commands one by one. In Linux terminology, an executable program is a sequence of machine commands and their data. A process consists of three parts: Process Control Block, program segment, and data segment. Simply put, a process is a running program.
We can use the ps command to view the content of the user space. This command will list the current process. There are two processes running: Bash (Shell) and PS commands. Each process has a number that uniquely identifies it, called the process ID. PID. PS has many options. Like the LS command, PS supports-A and-l options. -Option A lists all processes, but does not include shell. Option-L is used to print more details.

[
A column named s indicates the status of each process. If the value of column S is R, the process is running. If the value of column S is S, the process is sleep. Each process belongs to the user specified by the UID. Each process has a process ID and a parent process ID (ppid ). The columns marked as PRI and Ni are the process priority and niceness level. The column marked as tty indicates the terminal connected to the process. The value is? Indicates that the process is a system process.

How does Shell run the program?

Shell prints the prompt, the user enters the command, the shell executes the command, and then the shell prints the prompt again-so repeatedly. So how does Shell run the program? The main loop of a shell executes the following four steps:
1. receive commands
2. Create a new process to run this command.
3. Load the program from the disk
4. The program runs in its process until it ends.
For example, if we input the LS and PS commands in sequence, it indicates the order of events.

Shell reads the string ls from the user. Shell creates a new process, runs the LS program in the new process, and waits until the new process ends. Then shell reads a new line of input, creates a new process, runs the program in the process, and waits until the process ends. As shown in figure 2, to implement this process, we need to solve three problems: how to create a new process, how to wait for the child process to end, and how to run another program in one program.

How to create a new process

We can use the fork () system call to create a process. A new process created by fork is called a sub-process. After fork is successfully called, two processes exist, one is the parent process and the other is the child process. A child process is a new process and a copy of the parent process. Simply put, all the East and West child processes of the parent process are copied. Displays what happened before and after the fork process is called.

As shown in the figure, the kernel creates a child process by copying the parent process. It copies the code of the parent process and the current running location to the child process. The current running position is represented by an arrow that moves down with the code. The sub-process starts to run from where fork returns. After fork returns, the Parent and Child processes have the same code and run on the same row with the same data and process attributes. At this time, we can identify the Parent and Child processes through the return value of fork. For different processes, the return value of fork is different. In the child process, fork returns 0, and in the parent process, fork returns the PID of the child process.

How does a parent process wait for the child process to end?

The process can call wait to wait until the sub-process ends. The method is pid = wait (& Status). Here, the system calls wait to do two things. First, wait suspends the process that calls it until the child process ends. Then, wait obtains the exit value at the end of the sub-process. Shows how wait works.

When a child process calls exit, the kernel wakes up the parent process and passes the exit parameter. In the figure, the arrow from the parentheses of exit to the parent process indicates the action to wake up and pass the exit value. In this way, wait performs two operations: notification and communication. The notification tells the parent process that the child process has ended. The wait return value is the PID of the child process that calls exit. Therefore, the parent process can always find which child process has ended. Communication is to tell the parent process how the child process ends, and the termination status of the terminated process is returned through the wait parameter. The status parameter called by the wait system is an integer pointer. If status is not a null pointer, the termination status of the terminated process is stored in the unit to which it points. A process can end in three ways:
1. complete its tasks smoothly. In Linux, a successful program calls exit (0) or returns 0 from the main function.
2. process failed. If the program encounters a problem and calls exit to exit, the program needs to pass exit a non-zero value. This value is assigned by the programmer.
3. The program is killed by a signal. Generally, a signal that is neither ignored nor captured will kill the process.

How to run another program in one program

In Linux, a function family can solve this problem-exec function family (EXEC ). Exec contains six member functions. Each function calls the kernel service by calling execve. When a process calls exec to execute a program, the exec System Call clears the machine commands of the current program from the current process, and then loads the specified program code in an empty process, finally, run the new program. That is to say, exec is like a brain swap. The original process is replaced by the program to be executed. Some members of this function family are described as follows:
Int execl (char * pathname, char * arg0,..., argn, (char *) 0)
Int execv (char * pathname, char * argv [])
Int execle (char * pathname, char * arg0,..., argn, (char *) 0, envp)
Int execve (char * pathname, char * argv, char * const envp [])
Int execvp (char * filename, char * argv [])
Int excelp (char * filename, char * arg0 ,..., Argn, (char *) 0)
Here we mainly use the execvp function. execvp has two parameters: the program name to be run and the command line parameter array of the program. When the program runs, the command line parameter is passed to the program using argv. Note: set the first element of the array to the program name. The last element must be null.
Unlike execvp, execlp uses a parameter array. In execlp and execvp, p represents the path. The two functions search for the program specified by the first parameter in the path listed in the environment variable path. Apart from finding program files in path, execv is very similar to execvp. The parameters of these six exec functions are hard to remember. We can remember them based on the characters in the function name. The letter P indicates that the function takes filename as the parameter and uses the PATH environment variable to find the executable file. The letter "L" indicates that the function has a parameter table, and "V" indicates that the function has an argv [] array. Finally, the letter E indicates that this function is used to take the envp [] array instead of the current environment.
At this point, we can write a simple shell. This simple shell implements the functions of the running program among the three functions of shell. Here we compile it into ash. Ash accepts command names, parameter lists, run commands, and report results, and then accepts and runs other programs again. Here, Because Ash does not implement the function of managing input and output, you cannot enter all parameters in a row. The following is the source code:

 # Include <stdio. h> <br/> # include <signal. h> <br/> # include <stdlib. h> <br/> # include <string. h> <br/> # define maxargs 20 <br/> # define arglen 100 <br/> main () <br/>{< br/> char * Arglist [maxargs + 1]; <br/> int numargs; <br/> char argbuf [arglen]; <br/> char * makestring (); <br/> numargs = 0; <br/> while (1) <br/>{< br/> printf ('arg [% d]? ', Numargs); <br/> If (fgets (argbuf, arglen, stdin) & * argbuf! = '/N') <br/> Arglist [numargs ++] = makestring (argbuf ); <br/> else <br/> {<br/> If (numargs> 0) <br/> {<br/> Arglist [numargs] = NULL; <br/> execute (Arglist); <br/> numargs = 0; <br/>}< br/> return 0; <br/>}< br/> execute (char * Arglist []) /** use fork, execvp, and wait to implement */<br/> {<br/> int PID, exitstatus; <br/> pid = fork (); <br/> If (PID <0) // process creation failed <br/> {<br/> perror ('fork fail Ed '); <br/> exit (1); <br/>} else if (pid = 0) // sub-Process Execution Code <br/>{< br/> execvp (Arglist [0], Arglist); <br/> perror ('execvp failed '); <br/> exit (1); <br/>} else // Execution Code of the parent process <br/>{< br/> while (wait (& exitstatus )! = PID) <br/>; <br/> printf ('child exited with status % d, % d/N', exitstatus> 8, exitstatus & 0377 ); <br/>}< br/> char * makestring (char * BUF) /** remove the linefeed and apply for a bucket for the string */<br/> {<br/> char * CP; <br/> Buf [strlen (BUF) -1] = '/0'; <br/> CP = (char *) malloc (strlen (BUF) + 1); <br/> If (Cp = NULL) <br/>{< br/> fprintf (stderr, 'no memory/N'); <br/> exit (1 ); <br/>}< br/> strcpy (CP, Buf); <br/> return CP; <br/>}

 

More highlights please CLICK: http://www.armjishu.com/bbs/viewforum.php? Id = 39 & flag = 412

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.