[Email protected] Wangjing
For the fork () function, Unix/linux provides a fork () system call, and fork () returns two times at a time,
The operating system automatically copies a copy of the current process (called the parent process), which is then returned within the parent process and the child process, respectively;
The child process always returns 0, and the parent process returns the ID of the child process.
At the end of the parent process, the child process does not end immediately with the parent process, and the parent process does not wait for the child process to finish executing.
-Use of the fork () in Python
Example One
#!/usr/bin/python3import osprint (' Process (%s) start ... '% os.getpid ()) # only works on unix/linux/macpid = Os.fork () if PID = = 0: print (' I am child process (%s) and my parent is%s. '% (Os.getpid (), Os.getppid ())) Else: print (' I (%s) just Created a child process (%s). '% (Os.getpid (), PID) ####### results ######## #Process (25912) Start ... I (25912) just created a child process (25913). I am Child process (25913) and my parent is 25912.
Example Two
#!/usr/bin/python3import osimport Time #创建子进程之前声明的变量source = 10try: pid = os.fork () if pid = = 0: #子进程 print (' I am Child process (%s) and my parent is%s. '% (Os.getpid (), Os.getppid ())) #在子进程中source自减1 Source-= 1 time . Sleep (1) else: #父进程 print (' I (%s) just created a child process (%s). '% (Os.getpid (), PID)) print (source)
time.sleep (2) except OSError as E: print ("exception", E) ####### results ####### #I (12807) just created a child process (12 808). 10I am Child process (12808) and my parent is 12807.9
-How is the zombie process in the server generated?
Reference: https://www.cnblogs.com/yuxingfirst/p/3165407.html
Reference: http://blog.csdn.net/qq_20218109/article/details/52078076
Reference: http://blog.51cto.com/forlinux/1422438
when the child process is finished, but the parent process is not finished, the child process is out of the zombie state, which requires the parent process to collect the child process information to release the child process .
If the parent process ends the child process, the child process is pinned to the PID 1 process to manage it.
The purpose of setting the zombie state for a process is to maintain the child process information so that the parent process gets it at a later time,
This information includes the process ID of the child process, the termination status, and resource utilization information (CPU time, memory usage, and so on);
Examples of zombie process generation
The child process exits before the parent process, and the parent process does not call Wait/waitpid, and the child process becomes a zombie process.
#!/usr/bin/python3import osimport Time try: pid = os.fork () if pid = = 0: #子进程 print (' I am child process (%s) a nd my parent is%s. '% (Os.getpid (), Os.getppid ())) else: #父进程 print (' I (%s) just created a child process (%s). '% (Os.getpid (), PID)) Time.sleep print ('%s end '% os.getpid ()) except OSError as E: print ("exception", e) ###### result ##### #I (19668) J UST created a child process (19669). I am Child process (19669) and my parent is 19668.19669 end19668 End # This place sleep for 50 seconds before printing
When the program runs, combine the PS command to view the zombie process:
[Email protected] [13:30:40]$ ps-a-ostat,ppid,pid,cmd | Grep-e ' ^[zz] ' z+ 19668 19669 [forkkk.py] <defunct>[email protected][13:31:28]$ [email protected][13:31:28]$ Ps-a-ostat,ppid,pid,cmd | grep forkkks+ 10582 19668/usr/bin/python3./forkkk.pyz+ 19668 19669 [forkkk.py] <defunct> # Obviously the PID is 19669, that is, the ID of the child process, the child process has been executed, but the parent process 19668 has not finished executing. S+
-How to avoid zombie processes/How to reclaim zombie processes? 1. Signal mode
When the child process exits, the kernel will give the parent process a SIGCHLD signal,
So we can set up a signal processing function that captures the SIGCHLD signal, call Wait (or waitpid) in the function body, and we can clean out the child process to prevent the zombie process.
#!/usr/bin/python3import osimport timeimport signaldef childhandler (*args, **kwargs): while True:try: result = Os.waitpid ( -1, OS. Wnohang) Except:break Else:print ("reaped child process% (PID) d, Status is% (status) s "% {' pid ': result[0], ' status ': Result[1]}) if __name__ = = ' __main__ ': signal.signal (signal. SIGCHLD, Childhandler) print ("Before the fork, parent pid is%s"% os.getpid ()) PID = Os.fork () if PID:PR Int ("Hello from the parent, the child pid is%s"% pid) print ("Parent sleeping seconds ...") Time.sleep (1 0) Print ("Parent sleep done.") Else:print ("Child sleeping 3 seconds ...") Time.sleep (3) print ("Child sleep done.") ###### results ##### #Before the fork, parent PID is 18998Hello from the parent, the child PID is 18999Parent sleeping second S ... Child sleeping 3 seconds ... Child sleep is done. Reaped child process 18999, status was 0Parent sleep done.
Os.waitpid ()-1 indicates that all child processes waiting for the main process terminate the OS. Wnohang indicates that if no child process has been terminated, it returns immediately.
2. Parent process Polls check subprocess and recycles
#!/usr/bin/python3import osimport timedef Recovery (): While True:try:result = Os.waitpid ( -1, OS. Wnohang) #result = os.wait () except:break else:return resultif __name__ = = ' __main__ ': Print ("Before the fork, parent pid is%s"% os.getpid ()) PID = Os.fork () if Pid:print ("Hell O from the parent, the child PID was%s "% pid" while true:res = Recovery () time.sleep (0.5) Print (' one loop ... ') if res[0]: print ("reaped child process% (PID) d, Status is% (Statu s) S "% {' pid ': res[0], ' status ': Res[1]}) Break print (" Parent run End ... ") Else : Print ("Child sleeping 3 seconds ...") Time.sleep (3) print ("Child sleep done.") ###### results ##### #Before the fork, the parent PID is 3391Hello from the parent and the child PID is 3392Child sleeping 3 seconds. . One loop...one loop...one loop...one loop...one Loop...one Loop ... Child sleep Done.one Loop...one loop ... Reaped child process 3392, status is 0Parent run end ...
There is no way to handle the zombie process in a timely manner (depending on the polling interval).
Attention:
-result = Os.waitpid ( -1, OS. Wnohang) This method does not block the caller .
-result = os.wait () This will block the caller , resulting in no polling.
3. Fork () two times/python implementation daemon
The parent process once fork () produces a child process, and then the parent process immediately executes WAITPID (child process PID, NULL, 0) to wait for the child process to end , and then the Child Process fork () to generate the grandson process then immediately exit (0).
This way the process terminates successfully (the parent process simply takes the child process to the corpse, does not need the return value of the child process), and then the parent process resumes execution .
The grandson process is then forwarded to the init process for hosting because it loses its parent process (that is, the child process of the parent process).
So the parent process has no inheritance relationship with the grandson process, their parent process is init, and theinit process will automatically corpse at the end of its grandson process , so there will be no zombie process.
For details see: http://blog.tangyingkang.com/post/2016/10/20/python-daemon/ * * * *
Fork () two times is not required: 1190000008556669 * * * * *
Import Osimport sysimport atexitdef daemonize (pid_file=none): "" "Create Daemon:p Aram Pid_file: Save the Process ID file: return: "" "# Fork a subprocess out of the parent process out PID = Os.fork () # The PID of the subprocess must be 0, the parent process is greater than 0 if PID: # exits the parent process, the Sys.exit () method is more than the Os._exit () method Perform some refresh buffering work sys.exit (0) # The child process inherits the parent process's working directory by default, preferably a change to the root directory, or the Unload os.chdir ('/') # that affects the file system-the child process inherits the parent process's umask (file permission mask) by default, Reset to 0 (Full control) to avoid affecting the program to read and write files Os.umask (0) # Let the child process become the new session leader and process leader Os.setsid () # Note that this is the 2nd time Fork, which is the subprocess of the child process, we call it the grandson process _p id = os.fork () If _pid: # exit Subprocess sys.exit (0) # At this point, the grandson process is already a daemon, and then redirect the standard input, output, and error descriptors (redirected instead of closed, which prevents the program Error in print) # Flush buffer First, be careful to make the perpetual ship Sys.stdout.flush () Sys.stderr.flush () # dup2 function atomically Close and copy the file descriptor, redirecting to/dev/nul, which discards the There is an input output with open ('/dev/null ') as Read_null, open ('/dev/null ', ' W ') as Write_null:os.dup2 (Read_null.fileno (), SYS . Stdin.fileno ()) os.dup2 (Write_null.fileno (), Sys.stdout.fileno ()) os.dup2 (Write_null.fileno (), SYS.STDERR.F Ileno ()) # write PID file If Pid_file:with open (pid_file, ' w+ ') as F:f.write (str (os.getpid ())) # Registers the Exit function and removes the PID file when the process exits abnormally Atexit.register (Os.remove, Pid_file)
-Extension: The cost of fork in Python
Fork () and zombie process