Linux Operating System - Chapter 2 Process Control

 

 

Table of contents

process creation

Introduction to the fork function

fork function return value

copy-on-write

common usage of fork

The reason for the failure of the fork call

process terminated

process exit scenario

Common ways to exit a process

_exit function

exit function

return exit

process waiting

Process waiting necessity

How the process waits

wait method

waitpid method

Get subprocess status

process program replacement

Replacement principle

replace function




process creation



Introduction to the fork function



The fork function is a very important function in linux, which creates a new process from an existing process. The new process is the child process, and the original process is the parent process.

#include <unistd.h>
pid_t fork(void);
return value: return 0 in the child process, return the child process id in the parent process, return -1 in error

The process calls fork. When the control is transferred to the fork code in the kernel, the kernel does:
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 system process list
fork return, start scheduler scheduling

When a process calls fork, there are two processes with the same binary code. And they all run to the same place. But each process will be able to start their own journey.

Before the fork, the parent process executes independently. After the fork, the two execution flows of the parent and the child are executed separately. Note that after fork, who executes first is completely determined by the scheduler.


fork function return value



The child process returns 0, and the parent process returns the pid of the child process.



copy-on-write



Usually, the code is shared between father and son. When the father and son do not write, the data is also shared. When either party tries to write, they will each have a copy in the form of copy-on-write.


common usage of fork



A parent process wishes to duplicate itself so that the parent and child processes execute different sections of code concurrently. For example, a parent process waits for a client request and spawns a child process to handle the request.
A process executes a different program. For example, after the child process returns from fork, it calls the exec function.



The reason for the failure of the fork call



There are too many processes in the system.
The number of processes for the actual user exceeds the limit'



process terminated



process exit scenario



Code completes with correct result
Code completes with incorrect result
Code terminates abnormally



Common ways to exit a process



Normal termination (you can view the process exit code through echo $?):
1. Return from main
2. Call exit
3. _exit


Abnormal exit:
ctrl + c, signal termination



_exit function



#include <unistd.h>
void _exit(int status);


Parameters: status defines the termination status of the process, and the parent process obtains this value through wait

Although status is an int, only the lower 8 bits can be used by the parent process. So when _exit(-1), execute $? in the terminal and find that the return value
is 255


exit function


 #include <unistd.h>
void exit(int status);


Exit will also call exit at the end, but before calling exit, other work is done:
1. Execute the cleanup function defined by the user through atexit or on_exit.
2. Close all open streams, all buffered data is written
3. Call _exit

int main()
{
        printf("hello");
        exit(0);
}

Operation result:
[root@localhost linux]# ./a.out
hello[root@localhost linux]#
int main()
{
        printf("hello ");
        _exit(0);
}

Operation result:
[root@localhost linux]# ./a.out
[root@localhost linux]#


return exit



return is a more common way to exit a process. Executing return n is equivalent to executing exit(n), because the runtime function calling main will use the return value of main as the parameter of exit. 



process waiting




Process waiting necessity



If the child process exits, if the parent process is ignored, it may cause the problem of a 'zombie process', which in turn will cause a memory leak. In addition, once a process becomes a zombie, it is invulnerable, and the "kill without blinking" kill -9 can do nothing, because no one can kill a dead process.
Finally, we need to know how the tasks assigned by the parent process to the child process are completed. For example, whether the child process finishes running, whether the result is correct or not, or 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



How the process waits



wait method



#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);

Return value:
Returns the pid of the process being waited for if successful, returns -1 if failed.
Parameters:
Output parameters, get the exit status of the child process, if you don't care, you can set it to NULL


waitpid method


pid_ t waitpid(pid_t pid, int *status, int options);
return value:
when returning normally, waitpid returns the process ID of the collected child process;
if the option WNOHANG is set, and waitpid finds that there is no exited child process during the call If the process can be collected, it will return 0;
if there is an error in the call, it will return -1, and errno will be set to the corresponding value to indicate the error;
Parameters:
pid:
Pid=-1, waiting for any child process. Equivalent to wait.
Pid > 0. Wait for a child process whose process ID is equal to pid.
status:
WIFEXITED(status): True if this is the status returned by a normally terminated child process. (Check whether the process exited normally)
WEXITSTATUS(status): If WIFEXITED is non-zero, extract the exit code of the child process. (Check the exit code of the process)
options:
WNOHANG: If the child process specified by pid has not ended, the waitpid() function returns 0 and does not wait. If it ends normally, the ID of the child process is returned.

If the child process has already exited, when calling wait/waitpid, wait/waitpid will return immediately, release resources, and obtain the exit information of the child process.
If at any time wait/waitpid is called, the child process exists and is running normally, the process may block.
If the subprocess does not exist, return an error immediately


Get subprocess status



Both wait and waitpid have a status parameter, which is an output parameter filled by the operating system.
If NULL is passed, it means that the exit status information of the child process is not concerned.
Otherwise, the operating system will feed back the exit information of the child process to the parent process according to this parameter.
The status cannot be simply viewed as an integer, but can be viewed as a bitmap. The details are as follows (only the lower 16 bits of the status are studied): 

 



process program replacement




Replacement principle



After using fork to create a child process, it executes the same program as the parent process (but it may execute a different code branch), and the child process often needs to call an exec function to execute another program. When a process calls an exec function, the process's user-space code and data are completely replaced by the new program, and execution starts from the new program's startup routine. Calling exec does not create a new process, so the process id does not change before and after calling exec 


replace function


 

#include <unistd.h>`
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]); 

int execve(const char *path, char *const argv[], char *const envp[]);

If these functions are called successfully, the new program will be loaded and executed from the startup code, and will not return.
If there is an error in the call, -1 is returned
, so the exec function only has an error return value and no successful return value.

In fact, only execve is a real system call, and the other five functions eventually call execve 


               

 

 

 

 

Guess you like

Origin blog.csdn.net/MuqiuWhite/article/details/131078606