Process Control (Linux)
process creation
Introduction to the fork function
The function of the fork function is to create a child process in an existing process
#include <unistd.h>
pid_t fork(void);
Return value: creation failure returns -1; creation is successful, the child process returns 0, and the parent process returns the process id of the child process; a simple analogy can be made: the father can have multiple children, but the child has only one father, so after the process is created Need to give the child's id
to the father, and the child process getpid()
can get its own as long as it needsid
After the process calls the fork function, the operating system will allocate a new memory block and kernel data structure to the child process; copy part of the data structure content of the parent process to the child process; add the child process to the process list
fork function return value
Why fork
does a function have two return values? And why after returning, assign the id of the child process to the parent process, and assign a value of 0 to the child process? Why can the same return value be if else
established at the same time?
Next, take a closer look at the function
First, the user uses fork
the function, and the operating system starts to call the function to complete the corresponding task
When the function fork()
is ready return pid;
, the core code has been executed, the child process has also been created, and is ready to be scheduled in the operating queue of the operating system; therefore, before execution, the parent and child processes have been split, and the statements return pid;
can be executed separately return pid;
; the essence of return It is writing, the child process or the parent process returns first, and whoever writes into the id first, because of copy-time-writing, the same id will have two different contents, and match according to different contents and judgment if else
statements
common usage of fork
- The parent process wants to copy itself so that the parent and child processes execute different code segments at the same time
- The parent process wants the child process to execute a different program
The reason for the failure of the fork call
- Too many processes in the system
- The number of real user processes exceeds the limit
process terminated
process exit scenario
- The code runs and the result is correct
- The code runs to completion with an error
- The code terminates abnormally
Common ways to exit a process
First introduce the exit code, so far, the code written will be added at the end return 0
; why must it be the number 0 instead of other numbers? ? ?
When the process exits, it will return the corresponding exit code, indicating whether the result of the process execution is correct; generally speaking, the exit code must have a corresponding text description
Exit code: 0 means the program is running normally;! 0 Specific numbers indicate different errors
The program terminates normally,
you can echo $
view
-
return return
-
Calling the exit
program does not print immediatelyhello world
, but after two seconds; and the exit code is alsoexit(1)
consistent with the one set in the program -
Calling the _exit
program does not print at allhello world
, and the exit code is still the same
The reasons are as follows:
exit terminates the process and actively refreshes the buffer
_eixt terminates the process without refreshing the buffer
The difference between the two: exit is a library function; _exit is a system call
return function
return
It is a more common way to exit the process, and execution return n
is equivalent to executionexit(n)
process waiting
Process waiting necessity
- If the child process exits, the parent process has been unable to obtain its status, which will cause the child process to become a zombie state, resulting in memory leaks
- There is nothing the OS can do if the process becomes a zombie
- The purpose of the parent process to create the child process is to complete the task, so it is necessary to know whether the child process is running, whether the result is correct or not, and whether it exits normally
- The parent process reclaims the resources of the child process and obtains the exit information of the child process by means of process waiting
Get subprocess status
How the process waits
wait/waitpid
, each has astatus
parameter , which is an output parameter that is populated by the operating system- If NULL is passed, it means that the exit status information of the child process is not concerned (the child process is blocked)
- The operating system will feed back the exit information of the child process to the parent process according to this parameter
status
It cannot be simply viewed as a whole. The bitmap is as follows: the signal equal to 0 means normal exit, and the exit status is the exit code (the bitmap will be studied in detail later in the study)
status&0x7F
Process exit information; status >>8)&0xFF
get process exit status
wait method
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
Return value: If successful, return the id of the waiting process; if failed, return -1
Parameter: output parameter, get the exit status of the child process, if you don't care, you can set it to NULL;
The child process has been running in the first ten seconds, and the status is S+
; between ten and fifteen seconds, the child process terminates and is in a zombie process Z+
; after fifteen seconds, the parent process wait
reclaims the resources of the child process
waitpid method
#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int*status,int options);
Return value: If successful, return the id of the child process; if the option is set WNOHANG
, but waitpid
there is no exited child process to collect, then return 0; if it fails, return -1, then errno will be set to the corresponding value to wrong indication
Parameters:
pid
: child process id
status
: WIFEXITED
: If the child process is terminated normally, it is true, check whether the process exits normally; WEXITSTATUS
: If WIFEXIT is non-zero, extract the process exit code, check the exit code of the process
options
:
0 defaults to the blocking state; WNOHANG
(non-blocking): If the subprocess specified by pid has not ended, waitpd
the function returns 0 without waiting; if the process ends normally, the id of the subprocess is returned
status
The process of obtaining child process information: after the child process exits, the exit status and termination information are saved to the PCB; the parent process system call, waitpid
by status
obtaining the exit status of the child process, terminates the information
Get status by macro
Blocking vs non-blocking
Blocking: When the parent process is waiting to obtain the child process resources, if the child process has not exited, the parent process has been waiting for it to exit; non-blocking: when the parent process is waiting to obtain the child process resources, if the child process has not exited, the parent process You can execute other programs without waiting for the child process all the time, and take polling
pid_t waitpid(pid_t pid,int*status,int options);
Among them, option
when the value is 0, it represents the blocking state; option
whenWNOHANG
the value is 0, it represents the non-blocking state
The blocking state has been shown above, and the non-blocking acquisition of child process resources will be shown next
waitpid
Return value: equal to zero, the call is successful, but the child process does not exit; greater than zero, the call is successful and the child process also exits; less than zero, the call fails
- If the child process has already exited,
wait/waitpid
when called, it will return immediately, release resources, and obtain the exit information of the child process - If called at any time
wait/waitpid
, the child process exists and is running normally, the process may block - If the child process does not exist, an error is returned immediately
process program replacement
Replacement principle
After fork
the child process is created to execute the program, the child process often needs to call a exec
function to execute another program, that is, a program different from the parent process; when the process calls a function, the exec
created child process will specify The program is loaded into the memory and executed ; the call exec
does not create a new process, so exec
the id of the process does not change before and after the call
The essence of program replacement: load the code and data of the specified program to the specified location, and do not overwrite the data and code of the parent process
replace function
exec
There are six kinds of functions exec
starting with
int execl(const char *path, const char *arg, ...);
l
: list, pass execl
in
First execute the program, you need to find the program first, and then execute it, including how to execute it,
path
indicating the path of the program; arg
indicating how to execute the program, similar to command line parameters ; ...
indicating a list of variable parameters, the last parameter must beNULL
In the running result, only the first one is printed printf
, but the second one is not printed, why?
Because printf
is also a code, and the second one is execl
after the replacement function, when the replacement function is executed, the original code has been completely covered, and the new program code is started and executed, so the second one printf
cannot executed
int execlp(const char *file, const char *arg, ...);
p
:path, you can automatically find the path where the program is located, just enter the program to be executed
The first ls
represents the program to be executed; the second ls
represents how to execute
int execv(const char *path, char *const argv[]);
v
: vector, you can put all executable parameters into an array and pass them uniformly instead of using variable parameters
int execvp(const char *file, char *const argv[]);
Directly enter the program to be executed and how to execute it
So far, the system commands have been executed. Let's try to execute the program I wrote
Program written by myself:
operation result:
According to the running results, the call is very successful; so you can use the replacement function to call the program in any language
int execle(const char *path, const char *arg,
..., char * const envp[]);
e
: Custom environment variables
Try first without adding custom environment variables
The above is a simple way to obtain the environment variables in the two systems; what should I do if I want to customize the environment variables? ? ?
First introduce a function: putenv
add an environment variable to the environ
environment variable table pointed to in the system
. The operation of custom environment variables is as follows:
execle
Environment variables can be obtained. Similarly, the above replacement functions can also obtain environment variables. There are environment variable parameters in the virtual address space, and child processes can obtain environment variables through the address space.
execle
The argument list for is very similar to the command-line arguments for mian
the function
main
It is also a function, which must be called and passed as parameters, and execl
the program is loaded into the memory; so the order of program execution is: first load, then execute
The essence of the program replacement function is to load the program into the memory, and the loading work is done by the Linux exec* loader
function explanation
- If the replacement function is called successfully, the new program will be loaded and executed from the startup code without returning
- Returns -1 if the replacement fails
- Replacement function, only failure return value, no success return value