[APUE] Process Control (on) and apue Process Control

Source: Internet
Author: User

[APUE] Process Control (on) and apue Process Control
I. process ID

Process ID 0 is a scheduling process, which is often called a swapper ). This process does not execute any program on the disk-it is a part of the kernel and is also called a system process. Process ID 1 is the init process, which is called by the kernel at the end of the bootstrapping process. The program file of this process is/etc/init in earlier versions of UNIX, And/sbin/init in later versions. This process is responsible for starting a UNIX system after kernel self-lifting. Init usually reads system-related initialization (/etc/rc * file) and directs the system to a State (for example, multiple users ). The init process will never be terminated. It is a common user process (unlike the exchange process, it is not a system process in the kernel), but it runs with the superuser privilege.
In some UNIX virtual memory implementations, process ID 2 is a pagedaemon process ). This process is responsible for page operations that support the virtual storage system. Like the switch process, the page genie process is also a kernel process.
In addition to the process ID, each process has other identifiers. The following functions return these identifiers:

# Include <sys/types. h> # include <unistd. h> pid_t getpid (void); Return: IDpid_t getppid (void) of the Process calling process; Return: IDuid_t getuid (void) of the parent process calling the process; return: the actual user IDuid_t geteuid (void) of the calling process; Return: The valid user IDgid_t getgid (void) of the calling process; Return: the actual group IDgid_t getegid (void) of the calling process; return: valid blocking ID of the calling Process

No errors are returned for these functions.

Ii. fork Functions

A process that calls the fork function is the only way for the UNIX kernel to create a new process (except for the exchange process, init process, and page sprite process)

# Include <sys/types. h> # include <unistd. h> pid_t fork (void); Return Value: 0 for the child process, ID for the child process in the parent process, and-1 for the error.

The sub-process and the parent process continue to execute the commands after fork. A child process is a replica of the parent process. For example, a process obtains copies of the data space, heap, and stack of the parent process. However, these copies are not shared with the parent process. If the body segment is read-only, the Parent and Child processes share the body segment.
At present, many implementations do not make a full copy of the Data Segment and heap of the parent process, because after fork, it often follows exec. As an alternative, the ** Copy On Write, COW ** technology is used. These regions are shared by Parent and Child processes, and the kernel changes their access permissions to read-only. If a process tries to modify these regions, the kernel will make a copy of the relevant part (typically the "page" in the virtual storage system.

#include <sys/types.h>#include <stdio.h>#inlcude <unistd.h>int glob = 6;char buf[] = "a write to stdout\n";int main(void){    int var;    pid_t pid;        var = 88;    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 and run the above process:
 

We can see that when we redirect the output to the temp. out file, there will be moreBefore fork. The write function is not cached. Because write is called before fork, the data is written to the standard output once. However, standard I/O is cached. If the standard output is connected to the terminal device, it is a row cache; otherwise, it is a full cache. When the program is run interactively, only the row output by printf is obtained once, because the standard output cache is refreshed by the new line character. When we remove the linefeed after printf ("before fork \ n");, that is, printf ("before fork"); to verify this, the output result after the modification is:

We can see that before fork has been printed twice, which means that the row cache of the standard output stream will not be flushed because we have removed the line break.

However, when the annotation output is redirected to a file again, the printf output line is obtained twice. The reason is that when the standard output is redirected to a file again, the standard output stream is not a row cache but a full cache. printf is called once before fork, but when fork is called, the row of data is still in the cache. When the data space of the parent process is copied to the child process, the cached data is also copied to the child process. At that time, the Parent and Child processes each had a cache containing the content of the row. The second printf before exit adds its data to the existing buffer. When each process is terminated, the cached content will be written to the corresponding file.
File SharingFor the above program, note that the standard output of the child process is also redirected when the standard output of the parent process is redirected. One feature of fork is that all file descriptors opened by the parent process are copied to the child process. Each of the Parent and Child processes shares a file table item with the same open file descriptor.
This file sharing method allows the Parent and Child processes to use a file displacement for the same file. A process fork has a sub-process and waits for the sub-process to terminate. Assume that, as part of normal processing, both parent and child processes perform write operations to the standard output. If the parent process redirects its standard output (probably implemented by shell), when the child process writes to the standard output, it updates the file displacement shared with the parent process. In our example, when the parent process is waiting for the child process, the child process is written to the standard output. After the child process is terminated, the parent process is also written to the standard output, it is also known that its output will be added after the data written by the child process. If the parent and child processes do not share the same file displacement, this form of interaction is hard to achieve. [For understanding this, see APUE3.10]

 


If the parent and child processes write to the same file descriptor file, but there is no form of synchronization (for example, to make the parent process wait for the child process ), then their output will be mixed with each other (assuming that the file descriptor is opened before fork ).
There are two common scenarios for processing 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 process its descriptor.
(2) Parent and Child processes execute different program segments respectively. In this case, after fork, the Parent and Child processes do not need to use the file descriptors, and do not interfere with the file descriptors used by the other party.

In addition to opening a file, many other properties of the parent process will also be inherited by the child process:

  • Actual user ID, actual group ID, valid user ID, and valid group ID.
  • Add group ID.
  • Process Group ID.
  • Dialog period ID.
  • Control terminal.
  • Set-user-ID Flag and set-group-ID Flag.
  • Current working directory.
  • Root directory.
  • Create a blocked word in file mode. (Umask)
  • Signal shielding and arrangement.
  • Disable the flag when executing any opened file descriptor.
  • Environment.
  • Shared storage segment of the connection.

The differences between parent and child processes are:

  • The return value of fork.
  • Process ID
  • Different parent process IDs.
  • Set tms_utime, tms_stime, tms_cutime, and tms_ustime to 0.
  • The lock set by the parent process. The child process does not inherit the lock.
  • The pending alarms of sub-processes are cleared.
  • The pending Signal Set settings of the sub-process are cleared.
Iii. vfork Functions

The call sequence and return value of the vfork function are the same as those of the fork function, but the semantics of the two functions is different.
Vfork is used to create a new process, which aims to exec a new program. Both vfork and fork create a child process, but it does not completely copy the address space of the parent process to the child process, because the child process will immediately call exec (or exit ), therefore, this address space is not used.
Another difference between vfork and fork is that vfork ensures that the sub-process runs first. Only after it calls exec/exit can the parent process be scheduled to run. (If the child process is dependent on the further action of the parent process before exec/exit is called, a deadlock will occur .) 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");if ((pid = vfork()) < 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);return 0;}

Compile and run the program:
 

Note that the above program calls _ exit instead of exit. _ Exit does not refresh the IO cache. If you call exit instead of _ exit, the output of the program is:

(This is the original APUE book. It is the result of my experiment on centos.

The result is different because in linux, neutron processes close their own services. Although they share "open files" such as standard input, standard output, and standard errors, when the child process exits, it is also a matter of decreasing the reference count. It is impossible to close the parent process, so the parent process still has output.

)

The printf output of the parent process disappears. The reason is that the sub-process calls exit, which refresh and closes all standard IO streams, including standard output. Although this is performed by a child process, it is performed in the address space of the parent process. Therefore, all the affected standard io file objects are in the parent process. When the parent process calls prinf, the standard output is disabled, and printf returns-1.

Iv. exit Function

There are three methods for normal Process Termination and two methods for abnormal Process Termination.

(1) normal termination:

(A) execute the return statement in the main function, which is equivalent to calling exit.

(B) Call the exit function.

(C) Call the _ exit function.

(2) termination of exceptions:

(A) call abort. It generates the SIGABRT signal, so it is a special case of Abnormal Termination.

(B) When a process receives a signal. Processes themselves (such as calling the abort function), other processes and kernels can generate signals sent to a specific process. For example, if a process accesses a storage unit from its address space or is divided by 0, the kernel generates a signal for the process.

For any of the above Termination cases, we all want the termination process to notify its parent process how it is terminated. For e x I t and _ e x I t, it depends onExit status)Parameters. In case of abnormal termination, the kernel (not the process itself) generates a termination status that indicates the cause of the exceptional termination ). In any case, the parent process of the terminating process can use the w a I t or w a I t p I d function (as described in the next section) to obtain itsTermination status. (The exit status is the parameter passed to exit/_ exit, or the return value of main. At the end of the call _ exit, the kernel changes the exit status to terminate. If the child process terminates normally, the parent process can get the exit status of the child process.).

It must be a parent process that generates a child process. The above explains that the child process returns its termination status to the parent process. But what if the parent process stops before the child process? The answer is that for all processes whose parent processes have terminated, their parent processes are changed to init processes. We call these processes adopted by the init process. The operation process is roughly: when a process is terminated, the kernel checks all active processes one by one to determine whether it is a sub-process of the process to be terminated. If yes, then the parent process I d of the process is changed to 1 (I n I t process I D ). This method ensures that each process has a parent process.

Another concern is that if the child process is terminated before the parent process, how can the parent process get the termination status of the child process during the corresponding check? The answer to this question is that the kernel stores a certain amount of information for each end-to-end sub-process. Therefore, when the parent process of the terminated process calls w a I t or waitpid, you can obtain the relevant information. This information includes at least process I D, the termination status of the process, and the total amount of C P U time used to counter the process. The kernel can release all the memory used to terminate the process and close all open files. In terms of u n I X, a terminated child process has not been processed by its parent process (obtain information about the child process and release resources it still occupies) is called a zombie process.

The last question to consider is: what will happen when a process adopted by the I n I t process is terminated? Will it become a zombie process? The answer to this question is "no", because I n I t is written as long as a sub-process is terminated, I n I t calls a w a I t function to get its termination state. This prevents many zombie processes in the system. When we mention "a sub-process of I n I t", this refers to the process directly generated by I n I t (for example. 2), or the parent process has been terminated, adopted by init.

 

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.