The process of explanation

Source: Internet
Author: User
Tags syslog terminates

The Process Control block (PCB) in Linux TASK_STRUCT the structure is the PCB. The PCB is the unique identification of the process, the PCB is implemented by the linked list (for dynamic insertion and deletion). When the process is created, a PCB is generated for the process, and the PCB is recycled when the process terminates. The PCB contains information: 1, process status (state), 2, process identification information (UID, GID), 3, Timer (time), 4, User visible Register, control status register, stack pointer, etc. (TSS) each process has a non-negative unique process ID (PID). Although it is unique, the PID can be reused, and when a process terminates, other processes can use its PID. PID 0 process is the scheduling process, the process is part of the kernel, also known as the system process, the PID 1 process is the init process, it is a normal user process, but with superuser privileges to run; The PID 2 process is the page daemon, which is responsible for paging operation of the virtual storage system. In addition to the PID, there are other identifiers for each process: five process state transitions as shown: The Task_struct and system space stacks for each process are stored in the following locations: Two contiguous physical pages "Linux kernel source Scenario analysis" 271 page "system stack space cannot be dynamically extended, In the design of the kernel, the driver should avoid too deep nesting of functions, but also should not use too much local variables, because the local variables are present in the stack. The creation of a new process creates a task_struct structure in memory for the new process, then copies the task_struct contents of the parent process, and then modifies some of the data. Assign a new kernel stack, a new PID, and then add the Task_struct node to the list. The so-called creation, is actually "copy". At the beginning of the child process, the kernel does not allocate physical memory for it, but instead shares the parent process memory in a read-only manner, only when the child process is written. That is, "Copy-on-write". Fork is implemented by Do_fork, and the simplified flow of do_fork, such as the fork function Fork function, is called once and returned two times. Called once in both the parent and child processes. The return value in the child process is 0, and the parent process returns the PID of the child process. Programmers can have the parent and child processes execute different code depending on the return value. An image of the process: Run a demo program like this:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4  5 int main () 6 {7  pid_t pid; 8  Char *message; 9  int n = 0;10  pid = fork (), one while  (1) {  if (PID < 0) {  perror ("fork Faile D\n ");  exit (1);  }16  else if (pid = = 0) {  n--;18  printf (" Child ' s n is:%d\n ", n);  else{21  n++;22  printf ("Parent ' s n is:%d\n", N),  }24  Sleep (1),  }26  exit ( 0); 27}

Run Result: You can find that the child and parent processes do not have an impact on their respective variables. In general, the order in which the parent and child processes are executed after the fork is indeterminate depends on the kernel scheduling algorithm. Process communication is required to implement synchronization between processes. When do I use fork? A parent process expects a child process to execute a different code snippet at the same time, which is common in a network server--the parent process waits for a service request from the client, and when the request arrives, the parent process calls fork to cause the child process to process the request. A process to execute a different program, the General Fork immediately after the call execvfork function vfork and fork: The same: The return value is the same: fork to create the child process, the parent process data space, heap and stack Copya copy of; vfork Create child processes, with parent process memory data sharedVfork first ensure that the child process executes first, when the child process calls exit () or exec, the parent process goes down why do I need to vfork? Because vfork is usually followed by calling exec, it does not access the parent process data space, and it does not take time to replicate the data, so Vfork is "born for exec". Run a demo program like this:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4  5 int main () 6 {7  pid_t pid; 8  Char *message; 9  int n = 0;10  int i;11  pid = Vfork (); (  i = 0; i < i++) {  if (PID &L T 0) {  perror ("fork failed\n"),  exit (1),  }17  else if (pid = = 0) {  n--;19  printf (" Child ' s n is:%d\n ", n),  if (i = = 1)  _exit (0),  //return 0;23  //exit (0),  }25  Else {  n++;27  printf ("Parent ' s n is:%d\n", N),  }29  Sleep (1),  }31  exit (0); 32}

Run Result: can find the child process is executed first, exit, the parent process is executed, and the child process changes the data in the parent process What happens to the child process return 0? Operation Result:From the above we know that the call to end the child process is exit () instead of return, if you return in vfork, then this means that the main () function return, note because the function stack parent-child process is shared, so the entire program stack is kneeling. If you return in a subprocess, it is basically the following procedure: 1) the main () function of the subprocess return, and the function stack of the program has changed. 2) when the main () function returns, it is usually called exit () or similar function (e.g. _exit (), Exitgroup ()) 3) At this point, the parent process receives the child process exit () and starts returning from Vfork, but the Lao Tzu's stack has been your child process to return the dry waste, you let me how to carry out? (Note: The stack will return a strange stack address, for some kernel version implementation, directly reported "Stack error" on the kneeling, however, for some kernel version of the implementation, it is possible to call main () again, then entered an infinite loop results until the vfork call return error) Okay, Now return to return and Exit,return will release the local variables, and play the stack, back to the upper function execution. Exit directly. If you use C + + you know that return calls the destructor of the local object, exit does not. (Note: Exit is not a system call, it is glibc to the encapsulation of the system call _exit () or _exitgroup (), and the child process call exit () does not modify the function stack, so the parent process executes "a problem that the vfork hangs out" http:/ coolshell.cn/articles/12103.html#more-12103 "Execve executable file is loaded into the LINUX_BINPRM structure of the kernel. When the process calls exec, the program executed by the process is completely replaced, and the new program executes from the main function. Because calling exec does not create a new process, it simply replaces the code area, data area, heap, and stack of the current process. Six different exec functions: When you specify filename as a parameter: if filename contains/, it is treated as a pathname. Otherwise, the executable file is searched in each directory specified by the system's PATH environment variable.  * for security reasons, some people require that the current directory not be included in the search path. Of these 6 functions, only EXECVE is a system call to the kernel. The other 5 are just library functions, and they end up calling the system call, as shown in: the implementation of EXECVE is done by Do_execve, and the simplified implementation process, such as:  about these functions, can be viewed in the APUE "about the contents of the EXEC function section.   Run a demo program like this:
1 #include <errno.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4  5 char command[256]; 6 void Main () 7 {8    int rtn;/*child process return value*/9 while    (1) {Ten        printf (">");        fgets (Command, N, std In),        command[strlen (command)-1] = 0;13        if (fork () = = 0) {           execlp (command, NULL);           perror (Comman d);           exit (errno)            ,}18 else {(           &rtn);           printf ("Child process return%d\n", R TN);        }22    }23}

A.out is an executable file that prints Hello world. Run Result: Process termination normal termination (5 kinds) return from main, equivalent to call exit call Exitexit First call each termination handler, and then call fclose as many times as necessary, close all open streams. Call _exit or _exit last thread from its startup routine to return the last thread call Pthread_exit abort (3 kinds of) call aborting to receive a signal and terminate the last one to respond to the cancellation request The wait and waitpid function wait is used to block the parent process and wait for the child process to exit; Waitpid has several options, such as providing a non-blocking version of Wait, and also implementing the same functionality as wait, in fact, The implementation of wait in Linux is also implemented by calling Waitpid. Waitpid return value: Normal return child process number, using Wnohang and No child process exit return 0; Call error return 1; Run the following demo program
  1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/wait.h>  5 6 int Main () 7 {8 pid_t pid0,pid1; 9 pid0 = fork (); if (Pid0 < 0) {One perror ("fork"), exit (1); (pid0 = = 0)                         {sleep (5); + exit (0);//child) else{do{20 PID1 = Waitpid (Pid0,null,wnohang); if (Pid1 = = 0) {$ printf ("The child process had not exited.\n") ; Sleep (1); }while (Pid1 = = 0);                         if (pid1 = = pid0) {28 printf ("Get Child pid:%d", PID1); Exit (0); else{to exit (1); 32} 33} 34         return 0; 35} 36 37 38 39 When you change the third parameter Wnohang to 0 o'clock, there will be no more than five display statements, indicating that the parent process is blocked. The code for the a.out is as follows: #include <stdio.h> void Main () ("Hello wyj\n") The code for the PROCESS.C is as follows: #include <stdio.h> #include <sys/types.h> #include <unist  d.h> #include <stdlib.h> #include <sys/times.h> #include <sys/wait.h> 65 int main () { pid_t pid_1,pid_2,pid_wait; Pid_1 = fork (); Pid_2 = fork (); if (Pid_1 < 0) {perror ("Fork1 failed\n"),}else exit (1); Pid_1 = = 0 && pid_2! = 0) {//do not allow child 2 to excute this process. if (EXECLP ("./a.out", N        ULL) < 0) {perror ("exec failed\n");}//child; Exit (0); (Pid_2 < 0) {perror ("Fork2 failded\n"); Exit (1);                 Bayi}else if (pid_2 = = 0) {85); (Pid_2 > 0) do{pid_wait = Waitpid (Pid_2, NULL, Wnohang);//no Hang the SL EEP (2); ("Child 2 have not exited\n"); }while (pid_wait = = 0);                         if (pid_wait = = pid_2) {("Child 2 have exited\n"); 92 Exit (0); 94//printf ("pid_2:%d\n", pid_2),}else{perror ("WAITPI D error\n "); (1); 98}}100 exit (0); 101}

Running results: Write a multi-process program: The experiment has 3 processes, one of which is the parent process, the remaining two are the child processes created by the parent process, one of the child processes runs the "ls-l" instruction, another child process exits unexpectedly after pausing 5s, the parent process does not block itself, and waits for the child process to exit information. When the information is collected, the parent process returns.
1 #include <stdio.h> 2 #include <string.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <sys/wait.h> 7 int main () 8 {9  pid_t child1,child2,child;10  if ((Child1 = for K ()) < 0) {  perror ("Failed in fork 1"),  exit (1),  }14  if ((child2 = fork ()) < 0) {  perror ("Failed in Fork 2"), +  exit (1),  }18  if (child1 = = 0) {  //run ls-l20  if (child2 = = 0) {  printf ("in grandson\n");  }23  else if (EXECLP ("ls", "ls", "-l", NULL) < 0) {  perror ("Child1 EXECLP" );  }26  }27  else if (child2 = = 0) {  sleep (5);  exit (0);  }31  else{32  Do{33  Sleep (1);  printf ("Child2 not exits\n"), and child  = Waitpid (Child2, NULL, Wnohang);  while (child = = 0), PNs  if (child = = child2) {$  printf ("Get child2\n"),  }40  else{41  printf (" Error occured\n ");  }43  }44}

Run Result: The init process becomes the parent process of all zombie processes (orphan process) zombie process

After the process has called exit, the process does not immediately disappear, leaving behind a data structure that is a zombie process that records information such as the exit status of the process for other processes to collect, and in addition, the zombie process no longer occupies any memory space.

Why does the child process go into zombie state after it's finished? Because the parent process may get exit status information for the child process.

How do I view zombie processes?

The command PS in Linux, the process marked Z is the zombie process.

Execute the following procedure:

1 #include <sys/types.h> 2 #include <unistd.h> 3 int main () 4 {5  pid_t pid; 6  pid = fork (); 7  if ( PID < 0) {8  printf ("Error occurred\n"), 9  }else if (pid = = 0) {Ten  exit (0), one  }else{12  sleep (60);  Wait (NULL);  }15}

Operation Result:

Ps-ef|grep Defunc can find out the zombie process

Ps-l can get more detailed process information

The running results show:

After running two times and then discovering that there are two Z processes, and then waiting for one minute, the z process is reclaimed by the parent process.

where s indicates the state:

O: The process is running on the processor

S: Sleep state

R: Waiting to run

I: Idle state

Z: Zombie Status

T: Tracking Status

B: The process is waiting for more memory paging

Estimate of C:CPU utilization

Collecting information about the zombie process and ending these zombie processes requires us to use waitpid and wait in the parent process, which is capable of leaving information on the phone's zombie process and completely disappearing the process.

Daemon Daemon is a background service process for Linux. It is a long-lived process, no control terminal, output nowhere to display. The parent process of the user layer daemon is the init process. Daemon creation steps: 1, the creation of child processes, the parent process exits, the child process is automatically adopted by Init; fork Exit2, call Setsid to create a new session, become the first process of newly session, become the group leader process, get rid of the parent process inherits the session, process group, etc. setsid3, Change the current directory to the root directory, to ensure that the working file directory is not deleted; ChDir ("/") 4, resets the file permission mask, gives the child process greater permissions, Umask (0) 5, closes the unused file descriptor because it consumes resources; Close a daemon instance: Every 10s writes a " Tick
1 #include <stdio.h> 2 #include <string.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #define Maxfile 65535 7  8 int main () 9 {ten  int fd,len,i;11  pid_t pid;12  char *buf = "Tick\n",  len = strlen (buf),  if (pid = fork ()) < 0) {  perror ("Fork Failed"), and  exit (1); 17  }18  else if (pid > 0) {+  exit (0),  }21  setsid (),  if (ChDir ("/") < 0) {  Perror ("ChDir failed"),  exit (1),  }26  umask (0),  (i = 0; i < maxfile; i++) {  Close (i);  }30 while  (1) {(  fd = open ("/tmp/dameon.log", O_creat | o_wronly | O_append, 0600) < 0) {  perror ("Open log Failed"),  exit (1),  }35  write (FD, buf, len+1); 36< C27/>close (FD); Notoginseng  Sleep ();  }39}

Operation Result:

 1 #include <stdio.h> 2 #include <string.h> 3 #include <fcntl.h> 4 #include <unistd.h> 5 #include <sys/types.h> 6 #include <syslog.h> 7 #define MAXFILE 65535 8 9 int main () ten {one int fd,len,i;12 pid_t PID, child;13 char *buf = "tick\n"; len = strlen (BUF), if (PID = fork ()) < 0) {perror ("fork Failed"), + exit (1); 1 8}19 else if (pid > 0) {exit (0);}22 openlog ("Jack", Log_pid, Log_daemon), if (Setsid () < 0) { Og_err, "%s\n", "Setsid"), exit (1),}27 if (ChDir ("/") < 0) {log_err, "%s\n", "chdir"); exit (1); 3  1}32 umask (0); (i = 0; i < maxfile; i++) {Close (i);}36 if ((Child = Fork ()) < 0) {Notoginseng syslog (Log_err, "%s\n", "fork"); exit (1);}40 if (child = = 0) {//printf ("in child\n");//can not use terminal from now on.42 sys Log (Log_info, "in-child");//printf (0);}46 else{47 waitpid (Child, NULL, 0); );//can not use terminal from Now on.49 syslog (log_info, "Child Exits"), Closelog (), Wuyi while (1) {10); 53}54}55 56} 

When you really write debugging, you will find that you need to kill the daemon. How do I kill the daemon? Ps-aux find the corresponding PIDkill-9 PID original Portal: please click

The process of explanation

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.