Process Control Block
In Linux, each process has a process control block (PCB) in the kernel to maintain process-related information. It usually contains the following information:
- Process id. Each process in the system has a unique id, which is represented by the pid_t type in C language. It is actually a non-negative integer.
- The status of a process, including running, suspended, stopped, and botnets.
- Some CPU registers that need to be saved and restored during process switching.
- Description of the virtual address space.
- Describes the information of the control terminal.
- Current Working Directory ).
- Umask mask.
- The file descriptor table contains many pointers to the file struct.
- Information related to the signal.
- User id and group id.
- Control terminals, sessions, and process groups.
- Resource Limit ).
Fork and exec
Fork is used to copy a new Process based on an existing Process. The original Process is called the Parent Process, and the new Process is called the Child Process ).
Many processes run simultaneously in the system. These processes are copied one by one from the beginning. Enter a command in Shell to run a program, because the Shell process will call fork to copy a new Shell process after reading the command entered by the user, then the new Shell process calls exec to execute the new program.
A program can be loaded to the memory multiple times to become multiple processes running at the same time. For example, you can run/bin/bash in multiple terminal windows at the same time. On the other hand, A process can also execute two different programs before and after exec is called. For example, if you enter the ls command at a Shell prompt, fork creates a sub-process, at this time, the sub-process is still executing the/bin/bash program, and then the sub-process calls exec to execute the new program/bin/ls, as shown in.
Fork Function
The fork function declaration is as follows:
Pid_t fork (void );
When the fork replication process fails,-1 is returned. When the replication process succeeds, the copied process only executes the code after the fork function. Although both the parent and child processes execute subsequent code, they can be distinguished by the fork return values. A simple example is as follows:
# Include <sys/types. h>
# Include
<Unistd. h>
# Include
<Stdio. h>
# Include
<Stdlib. h>
Int main (void)
{
Pid_t pid;
Char * message;
Int n;
Pid = fork ();
If (pid <0 ){
Perror ("fork failed ");
Exit (1 );
}
If (pid = 0 ){
Message = "This is the child \ n ";
N = 6;
} Else {
Message = "This is the parent \ n ";
N = 3;
}
For (; n> 0; n --){
Printf (message );
Sleep (1 );
}
Return 0;
}
Fork returns the ID of the child process to the parent process, and returns 0 to the child process. Therefore, you can use the return value to identify whether the child process is a parent process or a child process.
This design makes sense. Although the child process cannot obtain the process ID through the return value, you can use the getpid function to obtain the id of the parent process, or call the getppid function to obtain the id of the parent process. Getpid can be used in the parent process to get its own process id. However, to get the id of a child process, you only need to record the fork return value.
After separating processes based on the returned values, you can specify their processes. In the above example, their processes are as follows:
Exec Function
After a child process is created with fork, the same program is executed as the parent process. The child process can also execute another program through the exec function. When a process calls an exec function, the user space code and data of the process are completely replaced by the new program, and the execution starts from the startup routine of the new program. Function is similar to the C system function.
An example is as follows:
# Include
<Unistd. h>
# Include
<Stdlib. h>
Int main (void)
{
Execlp ("ps", "ps", "-o", "pid, ppid, pgrp, session, tpgid, comm", NULL );
Perror ("exec ps ");
Exit (1 );
}