[Apue] Process Control (UP)

Source: Internet
Author: User
Tags glob terminates

One, process identification

Process ID 0 is the dispatch process, often referred to as the interchange process (swapper). The process does not execute any program on disk-it is part of the kernel and is therefore referred to as a system process. Process ID 1 is the init process, which is called by the kernel at the end of the bootstrap (bootstrapping) process. The program file for this process is/etc/init in earlier versions of UNIX and is/sbin/init in the newer version. This process is responsible for starting a UNIX system after the kernel bootstrap. Init typically reads system-related initializations (/etc/rc* files) and directs the system to a state (for example, multiple users). The init process never terminates. It is a normal user process (unlike the swap process, which is not a system process in the kernel), but it runs with superuser privileges.
In some UNIX virtual memory implementations, Process ID 2 is the page sprite process (Pagedaemon). This process is responsible for paging operations that support the virtual storage system. As with the swap process, the page daemon process is also a kernel process.
In addition to the process ID, there are additional identifiers for each process. The following functions can return these identifiers:

#Include<sys/types.h>#Include<unistd.h>pid_t getpid ( void); return: Process idpid_t getppidvoid); return: The parent process of the calling process iduid_t getuid void); return: The actual user of the calling process iduid_t Span class= "Hljs-title" >geteuid (void); return: A valid user of the calling process idgid_t getgid ( void); return: The actual group of the calling process idgid_t  Getegidvoid); return: the effective Resistance ID of the calling process      

None of these functions are returned in error

Second, fork function

A process call to the fork function is the only way the Unix kernel creates a new process (except the swap process, the INIT process, and the page sprite process)

#include <sys/types.h>#include <unistd.h>pid_t fork(void);返回: 子进程中为0,父进程中为子进程的进程ID,出错为-1.

The child process and the parent process continue to execute the instruction after the fork. A child process is a replica of the parent process. For example, a process obtains a replica of the parent process data space, heap, and stack. But these are process-owned copies that are not shared with the parent process. If the body segment is read-only, the parent and child processes share the body segment.
Many implementations now do not make a full copy of the parent process data segment and the heap because it is often followed by exec after fork. As an alternative, the technique of copying (copy on write, COW) * * on write is used. These zones are shared by the parent and child processes, and the kernel changes their access rights to read-only. If a process attempts to modify these zones, the kernel makes a copy of the relevant section (typically "pages" in the virtual storage System).

#include <sys/types.h>#include<stdio.h>#inlcude<unistd.h>intGlob =6;CharBuf[] ="a write to stdout\n";intMainvoid){    int var;        pid_t pid; var= the; if(Write (Stdout_fileno, buf,sizeof(BUF)-1) !=sizeof(BUF)-1) {fprintf (stderr,"Write Error"); } printf ("before fork \ n"); if(PID = fork ()) <0) {fprintf (stderr,"Fork Error"); } Else if(PID = =0) {Glob++; var++; } Else{sleep (2); } printf ("pid=%d,glob=%d,var=%d\n", Gitpid (), Glob,var); return 0;}

  

Compile to run the above process:

You can see the output of a before fork when we redirect the output to the Temp.out file. The Write function is not cached. Because write is called before the fork, its data is written to standard output once. However, standard IO is cached. If the standard output is attached to an end device, it is a row cache, otherwise it is a full cache. When you run the program interactively, only the rows that are output by printf are made once, because the standard output cache is refreshed by the new line character. But when the callout output is redirected to a file, it gets the printf output line two times. The reason for this is that printf was called once before the fork, but when Fork was called, the row's data was still in the cache, and the cached data was copied to the child process when the parent process data space was copied to the child process. Then the parent and child processes each have a cache with the contents of the row. The second printf before exit adds its data to the existing buffer. When each process terminates, the contents of the cache are written to the appropriate file.
file sharing is important for the above programs: the standard output of the child process is also redirected when the parent process's standard output is redirected. One feature of fork is that all file descriptors that are opened by the parent process are copied into the child process. The parent and child processes share a single file table entry for each of the same open file descriptors.
This way of sharing files makes the parent-child process use a file offset for the same file. For the following situations: a process fork a child process and wait for the child process to terminate. Assume that, as part of normal processing, both parent and child processes write to standard output. If the parent process redirects its standard output (most likely by the shell), when the child process writes to the standard output, he updates the amount of displacement that the file shares with the parent process. In the example we consider, when the parent process waits for a child process, the child process writes to standard output, and after the child process terminates, the parent process is written to the standard output, and the output is known to be added after the child process writes the data. This form of interaction is difficult to implement if the parent and child processes do not share the same file offset. [For the sake of understanding this point can be see APUE3.10 section]


If the parent, child processes write to the same file descriptor file but do not have any form of synchronization (such as having the parent process wait for the child process), then their output will be mixed (assuming that the file descriptor was opened before the fork).
There are two common scenarios for working with file descriptors after fork:
(1) The parent process waits for the child process to complete. In this case, the parent process does not need to do any processing of its descriptors.
(2) The parent and child processes each execute different program segments. In this case, after the fork, the parent and child processes each have their own file descriptors that they do not need to use, and do not interfere with the file descriptors used by the other party.

In addition to opening the file, many of the other properties of the parent process are inherited by the child process:

    • Actual user ID, actual group ID, valid user ID, valid group ID.
    • Add the group ID.
    • The Process group ID.
    • The Conversation period ID.
    • Control terminal.
    • Set-user-id flag and set-group-id flag.
    • Current working directory.
    • root directory.
    • File mode to create a masking word. (umask)
    • Signal shielding and arrangement.
    • Closes the flag on execution of any open file descriptor.
    • Environment.
    • Shared storage segment for the connection.

The differences between parent and child processes are:

    • The return value of the fork.
    • Process ID
    • A different parent process ID.
    • The Tms_utime,tms_stime,tms_cutime and tms_ustime of the child process are set to 0.
    • The parent process sets the lock that the child process does not inherit.
    • Pending alarms for child processes are cleared.
    • The pending signal set settings for the child process are cleared.
Three, vfork function

The call sequence and return value of the Vfork function is the same as fork, but the semantics of the two functions are different.
Vfork is used to create a new process that is designed to exec a new program. Vfork creates a child process like fork, but it does not completely copy the address space of the parent process into the child process, because the child process calls exec (or exit) immediately, so this address space is not used.
Another difference between vfork and fork is that vfork guarantees that the child process runs first, and the parent process may be scheduled to run after it calls Exec/exit. (If the child process relies on further actions of the parent process before calling Exec/exit, it causes a deadlock.) ) for the following example:

#Include<sys/types.h>#Include<stdio.h> #include <unistd.h>
int glob =6;int main ( void) {int var; pid_t Pid;var = 88; printf ( "before vfork\n"); 0) {fprintf ( stderr, "vfork error\n");} else if (pid = = 0) {glob++;var++;_ Exit (0); printf ( "pid=%d,glob=%d,var=%d\n", Getpid (), Glob, Var); Span class= "Hljs-keyword" >return 0;}

Compile and run the program:

It is important to note that in the above program we call _exit instead of exit. _exit does not perform an IO cache refresh operation. If you call exit instead of _exit, the output of the program is:

(It's Apue's original book, the result of my experiment on CentOS.

The result is different because in the Linux neutron process is closed, although they share the standard input, standard output, standard error and other "open files", the child process exit, but also decrements a reference count, it is not possible to close the parent process, so the parent process has output.

)

The printf output of the parent process is visible disappears. The reason for this is that the child process called exit, and it flushed off all standard IO streams, which includes standard output. Although this is performed by a child process, it is done in the address space of the parent process, so all the affected standard IO file objects are in the parent process. When the parent process calls Prinf, the standard output is closed, and printf returns-1.

Iv. Exit Function

For any of these termination scenarios, we want the terminating process to be able to notify its parent process how it terminated. For e x i T and _ E x i T, this is accomplished by relying on the exit status parameter passed to them. In an abnormal termination condition, the kernel (not the process itself) produces a terminating state (termination status) that indicates the cause of its abnormal termination. In either case, the parent process of the terminating process can use the W a i t or w a i t P i d function (described in the next section) to get its terminating state.

Must be a parent process to generate a child process. It also shows that the child process returns its terminating state to the parent process. But what if the parent process terminates before the child process? The answer is that all processes whose parent process has been terminated have their parent process changed to the INIT process. We call these processes adopted by the INIT process. The process is generally: at the end of a process, the kernel examines all active processes individually to determine if it is a child of the process that is about to terminate, and if so, the parent process I d of the process is changed to 1 (i d for i-n i-t processes). This approach ensures that each process has a parent process.

Another thing we care about is if the child process terminates before the parent process, how can the parent process get the child process's terminating state when the corresponding check is made? The answer to this question is that the kernel holds a certain amount of information for each terminating child process, so when the parent process of the terminating process calls W a i t or waitpid, the information can be obtained. This information includes at least process I D, the terminating state of the process, and the total amount of C P u time used against the process. The kernel can release all the memory used to terminate the process and close all of its open files. In the U N I x terminology, a process that has been terminated, but whose parent process has not yet processed it (getting information about terminating a child process, releasing resources it still occupies) is called a zombie process.

The last question to consider is: what happens when a process that is adopted by an I-n i-t process terminates? Will it become a zombie process? The answer to this question is "no" because I n i t is written so that as long as a child process terminates, I n i t will call a W a i t function to get its terminating state. This also prevents a lot of zombie processes in the system. When referring to "a child process of an I-n i-t", this refers to a process that is directly generated by i n i t (for example, the G e t T y process that will be described in section 9.2), or the process whose parent process has been terminated by Init.

[Apue] Process Control (UP)

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.