Linux system call to me (2) - Process Management

xiaoxiao2021-03-06  34

Technical Article: Linux System Call and I learn (2) - Process Management Postter This article introduces the process concept under Linux, and focuses on four important system calls with Linux process management. GetPid, Fork, EXIT And _exit, assist some routines illustrate their characteristics and methods of use. Author: This article taken from the town of Ray: IBM DW China September 24, 2002 the Japanese introduced the concept of a process under Linux, and that focused on the management of processes related to the Linux system call four important getpid, fork, exit and _exit, Support some routines illustrate their characteristics and methods of use.

Some necessary knowledge about the process

Let's take a look at the standard definition of the process in college textbooks: "The process is the process of running concurrently on a data collection." This definition is very rigorous, and it is difficult to understand, if you don't understand this sentence, Let's take a look at myself and unscrupulous explanation. We all know that an executable on the hard disk is often referred to as a program. In the Linux system, when a program starts to execute, it is executed to the execution to exit it, it is in the part of the memory. Call as a process. Of course, this explanation is not perfect, but the benefits are easy to understand, in the following articles, we will make some more comprehensive understandings. Linux Process Introduction Linux is a multitasking operating system, that is, in the same time, there can be multiple processes simultaneously. If the reader has a certain understanding of the computer hardware system, we will know that the single CPU computer we all actually executes only one instruction within a time piece, then how is Linux implementing multiple processes simultaneously? It turns out that Linux uses a means called "process schedule", first, assign a certain run time for each process, this time is usually short, short to milliseconds, and then according to some rules, Select a put into operation from many processes, other processes are temporarily waiting, when running is exhausted, or to exit, or suspended for some reason, Linux will re-scheduled, select the next process to put into operation . Because the time slice occupied by each process is very short, in our way, it seems that multiple processes are running the same. In Linux, each process is assigned a data structure when creating, called Process Control Block, and PCB. A lot of important information is included in the PCB, and the system scheduling and process itself performs use. The most important thing is the process ID (Process ID), the process ID is also called the process identifier, is an unnealed integer, in The only way to log in the Linux operating system, on our most commonly used I386 architecture (ie, the architecture used by PC), a non-negative integer variant is 0-32767, which is also all of our possible process IDs. . In fact, it can be seen from the name of the process ID. It is the ID card number of the process. Everyone's ID number will not be the same, and the process ID of each process will not be the same. One or more processes can be combined to constitute a process group, one or more process groups can fit a session (session). This way we have the ability to batch operations to the process, such as transmitting signals to each process in the group by sending signals to a process group. Finally, let's take a look at your own system in your own system through the ps command:

$ PS -AUX (The following is the results on my computer, your results are likely to be different from this.)

User PID% CPU% MEM VSZ RSS TTY Stat Start Time Command

Root 1 0.1 0.4 1412 520? S May15 0:04 init [3]

Root 2 0.0 0.0 0 0? SW May15 0:00 [KEVENTD]

Root 3 0.0 0.0 0 0? SW May15 0:00 [KAPM-iDLED]

Root 4 0.0 0.0 0 0? SWN May15 0:00 [ksoftirqd_cpu0]

Root 5 0.0 0.0 0 0? SW May15 0:00 [KSWAPD]

Root 6 0.0 0.0 0 0? SW May15 0:00 [KRECLAIMD]

Root 7 0.0 0.0 0? SW May15 0:00 [BDFlush]

Root 8 0.0 0.0 0 0? SW May15 0:00 [Kupdated]

ROOT 9 0.0 0.0 0 0? SW

Root 13 0.0 0.0 0 0? SW May15 0:00 [kjournald]

Root 132 0.0 0.0 0 0? SW May15 0:00 [KJOURNALD]

Root 673 0.0 0.4 1472 592? S May15 0:00 syslogd -m 0

Root 678 0.0 0.8 2084 1116? S May15 0:00 klogd -2

RPC 698 0.0 0.4 1552 588? S May15 0:00 Portmap

Rpcuser 726 0.0 0.6 1596 764? S May15 0:00 rpc.statd

Root 839 0.0 0.4 1396 524? S May15 0:00 / usr / sbin / apmd -p

Root 908 0.0 0.7 2264 1000? S May15 0:00 xinetd-stayalive

Root 948 0.0 1.5 5296 1984? S May15 0:00 Sendmail: Accepti

Root 967 0.0 0.3 1440 484? S May15 0:00 GPM -T PS / 2 -M / D

WNN 987 0.0 2.7 4732 3440? S May15 0:00 / usr / bin / cserver

Root 1005 0.0 0.5 1584 660? S May15 0:00 crond

WNN 1025 0.0 1.9 3720 2488? S May15 0:00 / usr / bin / tlayxfs 1079 0.0 2.5 4592 3216? S May15 0:00 xfs -droppriv -da

Daemon 1115 0.0 0.4 1444 568? S May15 0:00 / USR / SBIN / ATD

Root 1130 0.0 0.3 1384 448 TTY1 S May15 0:00 / sbin / mingetty TT

Root 1131 0.0 0.3 1384 448 TTY2 S May15 0:00 / Sbin / MINGETTY TT

Root 1132 0.0 0.3 1384 448 TTY3 S May15 0:00 / Sbin / MINGETTY TT

Root 1133 0.0 0.3 1384 448 TTY4 S May15 0:00 / Sbin / MINGETTY TT

Root 1134 0.0 0.3 1384 448 TTY5 S May15 0:00 / sbin / mingetty TT

Root 1135 0.0 0.3 1384 448 TTY6 S May15 0:00 / Sbin / MINGETTY TT

Root 8769 0.0 0.6 1744 812? s 00:08 0:00 in.telnetd: 192.1

Root 8770 0.0 0.9 2336 1184 PTS / 0 s 00:08 0:00 login - LEI

Lei 8771 0.1 0.9 2432 1264 PTS / 0 s 00:08 0:00 -Bash

Lei 8809 0.0 0.6 2764 808 PTS / 0 r 00:09 0:00 ps -aux

In addition to the title, each line represents a process. In columns, the PID list represents the process ID of each process. The Command is a list represents the name of the process or the command line called in the shell. I will no longer explain, I will not explain, interested readers can Refer to the relevant books. GetPid is in the 2.4.4 version of the core, getPID is a system called No. 20, which in the Linux function library is:

#include / * Provide the definition of type PID_T * /

#include / * Provide a definition of functions * /

PID_T getpid (void);

GetPid is very simple, that is, the process ID of the current process, please see the following example:

/ * getpid_test.c * /

#include

Main ()

{

Printf ("" The current process id is% d

", getpid ());

}

The careful readers may notice that there is no header file Sys / Types.h in the definition of this program because we have not used the PID_T type in the program, and the PID_T type is the type of process ID. In fact, on the I386 architecture (that is, the architecture of our general PC computer), the PID_T type is fully compatible with the int type, we can use the data of the PID_T type with the method of processing the shape, such as "% D" It prints out. Compile and run the program getpid_test.c: $ gcc getpid_test.c -o getpid_test

$. / getpid_test

The current process id is 1980

(Your own run is likely to be different from this number, this is normal.)

Run again:

$. / getpid_test

The current process id is 1981

As we see, although the same application is run, all assigned process identifiers are different. For the 2.4.4 version of the kernel, the Fork is a system called No. 2, which in the Linux function library is:

#include / * Provide the definition of type PID_T * /

#include / * Provide a definition of functions * /

PID_T FORK (Void);

Just watching the name of the Fork, it may be rare to have a few people can guess what it is doing. The role of the Fork system call is to copy a process. When a process calls it, two almost extensive processes have occurred after completion, and we have found a new process. It is said that the name of the FORK is coming from this shape with a fork. In Linux, the method of creating a new process is only one, that is, the Fork we are introducing. Other library functions, such as system (), seems to have a new process, if you can see their source code, they can actually call the internally. Including we run applications in the command line, the new process is also made from the shell call fork. Fork has some very interesting features, let us have more understanding of it through a small program.

/ * fork_test.c * /

#include

#inlcude

Main ()

{

PID_T PID;

/ * Only one process at this time * /

PID = fork ();

/ * There are already two processes at the same time * /

IF (PID <0)

Printf ("ERROR in fork!");

Else IF (pid == 0)

Printf ("I am the child process, my process id is% d

", getpid ());

Else

Printf ("I am the parent process, my process id is% d

", getpid ());

}

Compile and run:

$ GCC fork_test.c -o fork_test

$. / fork_test

I am the parent process, my process id is 1991

I am the child process, my process id is 1992

When you look at this program, you must first understand a concept: before the statement pid = fork (), only one process is executing this code, but after this statement, it will become two processes, this The code parts of the two processes are identical, and the next statement to be executed is IF (pid == 0) .... In both processes, the one exists as "parent process", the new appearance is called "sub-process." The difference between the parent-child process except that the process flag (Process ID) is different, the value of the variable PID is not the same, and the PID is stored in the return value of the FORK. A wonderful thing for FORK is that it is only called once, but it can return twice, it may have three different return values: In the parent process, Fork returns the process ID of the newly created sub-process; in the child process, fork Return 0; if an error occurs, the Fork returns a negative value; for two reasons: (1) The current number has reached the upper limit of the system specified, and the value of errno is set to EAGAIN. (2) The system is insufficient, and the value of Errno is set to ENOMEM. (About Errno's meaning, please refer to the first article of this series.) The possibility of a Fork system call error is small, and if an error is generally the first error. If a second error occurs, the system has no assignable memory, which is in the edge of the crash, which is rare to Linux. Speaking here, smart readers may have fully understood the remaining code. If the PID is less than 0, the explanation has an error; PID == 0, indicating that the Fork returns 0, and the current process is a child process. To perform Printf ("I am the child!"), Otherwise (else), the current process is the parent process, performs Printf ("I am the parent!"). Perfectionists feel that this is very redundant, because there is a statement that they do forever in both processes. It is not necessary to worry too much. After all, many years ago, UNIX's nasal ancestors were written on the computer that could not imagine it at the time. Taking our "massive" memory, you can complete these bytes. Certises throw away from the clouds. Speaking here, some readers may have questions: If the Fork sub-process and the parent process are almost exactly the same, the only way to generate a new process in the system is fork, isn't that all the processes in the system be exactly the same? Then what should we do when we want to perform a new application? From the experience of the Linux system, we know that this problem does not exist. As for what method used, we left this problem to a specific discussion. EXIT is in version 2.4.4, exit is called No. 1, its prototype in the Linux function library is: #include

Void exit; Int status;

Unlike Fork so difficult to understand, you can see from the name of EXIT, this system call is used to terminate a process. Regardless of the location in the program, as long as the Exit system call is executed, the process will stop all of the following operations, clear all the data structures including the PCB, and terminate the operation of the process. Please see the following procedure:

/ * EXIT_TEST1.C * /

#include

Main ()

{

Printf ("This Process Will Exit!

");

exit (0);

Printf ("NEVER BE Displayed!

");

}

After compiling:

$ GCC EXIT_TEST1.C -O EXIT_TEST1

$. / EXIT_TEST1

This process will exit!

We can see that the program does not print "Never BE Displayed!", Because before this, the process has terminated when executed. The EXIT system calls with an integer type parameter status, which we can use this parameter to pass the state of the process, for example, the process is normal, or there is an unexpected, in general, 0 means no The unexpected normal end; other values ​​indicate an error, the process is abundant. When we actually program, we can use the WAIT system to call the return value of the receiving sub-process, thus performing different processes for different situations. About WAIT details, we will introduce in the subsequent space. EXIT and _EXIT as system calls, _exit and exit are a pair of twins brothers, what exactly, we can find answers from Linux source code:

#define __nr__exit __nr_exit / * Excerble from File Include / ASM-I386 / Unistd.h 334 line * /

"__Nr_" is a prefix that calls each system call in the source code of Linux, please note that there are 2 underlined lines in front of the first exit, and only one underline is only one under the second EXIT. At this time, I will know how to know the C language and the mind is clear, and _exit and exit have no difference, but we have to talk about the difference between the two, which is mainly reflected in their definitions in the library. _EXIT in the Linux function library is:

#include

Void_exit (int stat);

Compared with Exit, the exit () function is defined in stdlib.h, and _exit () is defined in Unistd.h, from the name, stdlib.h seems to be higher than Unistd.h, then, between them what differences are there? Let us first look at the flow chart. Through the picture below, we will have a more intuitive understanding of the implementation process of the two system calls.

As can be seen from the figure, the _exit () function is the most simple: directly stops the process, clear the memory space used, and destroys the various data structures in the kernel; the exit () function is on these I have made some packaging, and I have added several ways before executing exit, and because of this reason, some people think that EXIT is no longer a pure system call. The maximum difference between the exit () function and the _exit () function is that the exit () function wants to check the open situation of the file before calling the EXIT system call, writing the content in the file buffer back to the file, is the "Clean I / O buffer "one. In Linux standard library, there is a function called "Advanced I / O", we are well known to Printf (), Fopen () () (), FWRITE () is here, they are also known as " Buffer I / O (Buffered I / O) ", which corresponds to each open file, there is a buffer in memory. When reading the file, read the records more records, which next read files You can read directly from the buffer from the memory. When you write a file, it is just a buffer written in memory, and some conditions are met (reach a certain amount, or encounter specific characters, such as the wrap. The compassion and file end character EOF), then write the content in the buffer one-time, which greatly increases the speed of file read and write, but also brought a little trouble for our programming. If there are some data, we believe that files have been written, actually because they do not meet specific conditions, they are only saved in the buffer, then we use the _exit () function to close the process directly, the data in the buffer It will be lost. Conversely, if you want to ensure the integrity of the data, you must use the exit () function. Please see the following routines: / * EXIT2.C * /

#include

Main ()

{

Printf ("Output Begin

");

Printf ("Content In Buffer";

exit (0);

}

Compile and run:

$ GCC EXIT2.C -O EXIT2

$. / EXIT2

Output Begin

Content in buffer

/ * _Exit1.c * /

#include

Main ()

{

Printf ("Output Begin

");

Printf ("Content In Buffer";

_exit (0);

}

Compile and run:

$ GCC _EXIT1.C -O _EXIT1

$. / _ exit1

Output Begin

In Linux, both standard input and standard output are filed as file processing, although a special type of special file, but from a programmer's point of view, there is no difference between them and the ordinary files that store data on the hard disk. Like all other files, they have their own buffers after opening. Please read the readers to think about why the two programs will have different results. I believe that if you understand the content I've been in front, it will be easily concluded. In this article, we have a preliminary understanding of Linux's process management and learn from getPid, Fork, Exit and _exit four system calls. In the next article, we will learn from other system-related systems related to Linux process, and will make some more in-depth discussions. "From IBM DW China"

转载请注明原文地址:https://www.9cbs.com/read-64430.html

New Post(0)