Linux/UNIX process control (1)

Source: Internet
Author: User
Tags glob
Process Control (1) process identifier each process has an integer representing a unique process ID. After a process is terminated, its process ID can be used again. Process Control (1) process identifier

Each process has an integer representing a unique process ID. After a process is terminated, its process ID can be used again. The following are the IDs, types, and functions of several typical processes.

ID process name Chinese name type function

0 swapper swap process system process it is part of the kernel, do not execute the program on the disk, is a scheduling process.

1. the init process user process will never terminate. start the system and read the files initialized by the system.

2 pagedaemon

In addition to the process ID, each process also has some other identifiers. The following functions return these identifiers:

# Include

# Include

Pid_t getpid (void); // return value: ID of the process to be called

Pid_t getppid (void); // return value: ID of the parent process of the calling process

Uid_t getuid (void); // return value: the actual user ID of the calling process

Uid_t geteuid (void); // return value: valid user ID of the calling process

Gid_t getgid (void); // return value: the actual group ID of the calling process

Gid_t getegid (void); // return value: valid group ID of the calling process

Fork function

# Include

Pid_t fork (void );

An existing process can call fork to create a new process.

Returned value: 0 is returned for the child process, and-1 is returned for the parent process. As follows:

A child process is a copy of the parent process. For example, a child process obtains a copy of the data space, heap, and stack of the parent process. Parent and child processes do not share these buckets. The parent-child process shares the body segment.

Since fork often belongs to exec, many implementations do not execute full replication of a parent process data segment, stack, and heap. Instead, we use the Copy-On-Write technology. These regions are shared by parent and child processes, and the kernel changes their access permissions to read-only. If any of the parent and child processes tries to modify these regions, the kernel will only make a copy of the memory in the modified region.

The following program demonstrates the fork function. it can be seen that the changes made by the sub-process to the variable do not affect the value of the variable in the parent process.

#include 
 
  #include 
  
    int    glob = 6;       /* externalvariable in initialized data */char   buf[] = "a write to stdout\n"; intmain(void){   int     var;        /* automatic variable on the stack */   pid_t   pid;    var = 88;   if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)       perror("write error");   printf("before fork\n");   /* we don't flush stdout */    if ((pid = fork()) < 0) {       perror("fork error");    }else if (pid == 0) {      /* child */       glob++;                 /* modifyvariables */       var++;    }else {       sleep(2);               /* parent*/    }    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,var);   exit(0);}
  
 

Execution and output results:

Chen123 @ ubuntu :~ /User/apue.2e $./a. out

Awrite to stdout

Beforefork

Pid = 2755, glob = 7, var = 89

Pid = 2754, glob = 6, var = 88

Chen123 @ ubuntu :~ /User/apue.2e $./a. out> temp. out

Chen123 @ ubuntu :~ /User/apue.2e $ cat temp. out

Awrite to stdout

Beforefork

Pid = 2758, glob = 7, var = 89

Beforefork

Pid = 2757, glob = 6, var = 88

Generally, the execution sequence of the parent and child processes after fork is uncertain, depending on the kernel scheduling algorithm. In the above program, the parent process is sleeping for 2 seconds to make the child process run first.

The relationship between fork and I/O functions in the program: write is not buffered, because the write is called before fork, so the data is only written to the standard output once. Standard I/O is buffered. if the standard output is to the terminal device, it is a row buffer; otherwise, it is a full buffer. When the program is run interactively, only the lines output by printf are obtained once, because the standard output to the terminal buffer is flushed by line breaks. However, when the standard output is redirected to a file, because the buffer zone is a full buffer and the line break is not output, when fork is called, its printf data is still in the buffer zone, the data is copied to the sub-process, and the buffer is also copied to the sub-process. Therefore, both parent and child processes have a standard I/O buffer with modified content. Therefore, when each process is terminated, the data in its buffer is flushed and the first printf is output twice.

File sharing

One feature of fork is that all open file descriptors of the parent process are copied to the child process. Each identical open descriptor of the parent and child processes shares a file table item. Assume that a process has three different open files. when returned from fork, we have the following structure:

There are two common scenarios for file descriptors processed 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. After the sub-process is terminated, the sub-process modifies the file offset.

2. the parent and child processes run different program segments respectively. In this case, after fork, the parent and child processes disable the file descriptors they do not need, so that they do not interfere with the use of the file descriptors. This method is often used in network service processes.

Differences between parent and child processes:

1. fork return value

2. different process IDs

3. different parent process IDs

4. the child process's tms_utime, tms_stime, tms_cutime, and tms_ustime are all set to 0.

5. the filelock set by the parent process is not inherited by the quilt process.

6. the unprocessed alarm clock of the sub-process is cleared.

7. the unprocessed signal set of the sub-process is set as an empty set.

Fork has the following usage:

1. a parent process wants to copy itself so that the parent and child processes can execute unused code segments at the same time. For example, a parent process waits for a client request and generates a child process to process the request.

2. a process needs to execute a different program. For example, after a sub-process returns from fork, it calls the exec function.

Reason for fork call failure:

1. there are too many processes in the system

2. the actual number of processes exceeds the limit.

Vfork function

The call sequence and return value of the vfork function are the same as those of the fork function, but their semantics is different.

Vfork is used to create a new process, which aims to exec a new program. Both vfork and fork create a sub-process, but it does not copy the address space of the parent process to the sub-process. because the sub-process will call exec immediately, it will not access the address space. On the contrary, before a child process calls exec or exit, it runs in the space of the parent process, that is, it changes the data segment, stack, and heap of the parent process. Another difference between vfork and fork is that vfork ensures that the sub-process runs first. after it calls exec, the parent process can be scheduled to run.

The following is the vfork application:

#include"unistd.h"#include"stdio.h" int     glob = 6;       /* external variable in initialized data*/ intmain(void){    int    var;        /* automatic variableon the stack */    pid_t  pid;     var = 88;   printf("before vfork\n");  /* we don't flush stdio */    if ((pid = vfork()) < 0) {        perror("vfork error");    } else if (pid == 0) {      /* child */        glob++;                 /* modify parent's variables*/        var++;        _exit(0);               /* child terminates */    }    /*     * Parent continues here.     */    printf("pid = %d, glob = %d, var =%d\n", getpid(), glob, var);    exit(0);} 

The execution and output results are as follows:

Chen123 @ ubuntu :~ /User/apue.2e $./a. out

Before vfork

Pid = 2984, glob = 7, var = 89

The sub-process directly changes the variable value of the parent process because the sub-process runs in the address space of the parent process.

Here, the sub-process calls _ exit because _ exit does not perform standard I/O buffer flushing. If exit is called, the program results are uncertain and dependent on the implementation of the standard I/O library. Because exit may close the standard I/O stream, the parent process will not generate any output.

Exit function

There are 5 normal termination methods for processes, and 3 abnormal termination methods. (See the previous article ).

For any termination scenario, we want the termination process to govern how the parent process is terminated. For the three termination functions (exit, _ exit, and _ Exit), the exit status is transmitted to the function as a parameter. When an exception is terminated, the kernel generates a termination state indicating the cause of the exception. In any case, the parent process in the terminated state can use the wait or waitpid function to obtain its termination state.

When _ exit is called, the kernel converts the exit status of the process to the termination status.

For all processes terminated by the parent process, their parent process changes to the init process. We call these processes Init adoption. When an init sub-process (including the adoption process) terminates, init calls a wait function to obtain its termination state.

A process that has been terminated but has not been well processed by its parent process (obtain information about the final child process and release the resources it still occupies) is called a Zombie process. The child process does not run when it is terminated, but it still exists in the system. The table items in the progress table that represent the child process are not released immediately, because its exit code also needs to be stored in the progress table for future wait calls by the parent process, that is, the association between the child process and the parent process will be maintained at the end, it will not end until the parent process ends normally or the parent process calls wait.

Wait and waitpid functions

When a process terminates normally or abnormally, the kernel sends a SIGCHLD signal to its parent process. Because the termination of a sub-process is an asynchronous event, this signal is also an asynchronous notification sent by the kernel to the parent process. The parent process can ignore the signal or provide a function that is called when the signal occurs. The default action for this signal is to ignore it. Now you need to know what may happen to the process that calls wait or waitpid:

1. if all its sub-processes are still running, blocking

2. if a child process has been terminated and is waiting for the parent process to obtain its termination status, the child process will be terminated and returned immediately.

3. if it does not have any sub-process, an error is returned immediately.

# Include

# Include

Pid_t wait (int * status );

Pid_twaitpid (pid_t pid, int * status, int options );

If a process calls wait because it receives SIGCHLD, it is expected that wait will return immediately. However, if wait is called at any time, the process may be blocked.

Before a sub-process is terminated, wait blocks its callers, while waitpid has an option to prevent callers from blocking.

The statloc parameter of these two functions is an integer pointer. If statloc is not a null pointer, the termination status of the terminated process is stored in the unit it refers. If you do not care about the termination status, you can set this parameter as a null pointer.

You can use the following macros to check the termination status returned by wait and waitpid:

If WIFEXITED (status) is returned by a normal process, it is true.

WEXITSTATUS (status) if WIFEXITED is not zero, the sub-process exit code is returned.

If WIFSIGNAKED (status) is returned for abnormal termination of the sub-process (an uncaptured signal is received), it is true.

WTERMSIG (status) if WIFSIGNAKED is not zero, a signal number is returned.

WIFSTOPPED is true if it is unexpectedly terminated by the sub-process

If WSTOPSIG is not zero, a signal number is returned.

Waiptpid provides three functions not provided by wait:

1. waitpid can wait for a specific process

2. waitpid provides a non-blocking version of wait.

3. waitpid supports job control

Related Article

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.