Multi-process programming of under Linux: Yu Lei (a) understand under the structure of Linux Linux under process a process has three parts data in memory is "data segment", "stack segment" and "Code", in fact, learn Those who have been assembled are certain that the general CPU icon I386 has three segment registers to facilitate the operation of the operating system. "Code Segment", as the name suggests, is the data of the program code, if there are several processes in the machine run the same program, then they can use the same code segment. The stack segment is stored is the return address of the subroutine, the parameters of the subroutine, and the local variable of the program. The data segment stores the global variables, constants, and data space allocated by the dynamic data (such as the space to be used with a function such as Malloc). There are many details of this, which is limited to the space here. If you run several identical programs at the same time, you cannot use the same stack segment and data segment. (2) How to use the system call to generate a new process under Linux is the Fork function, this function name is the meaning of "bifurcation" in English. Why is this name? Because a process is running, if you use fork, another process is generated, so the process is "bifurcated", so this name is very image. Let's take a look at how to specifically use fork, this program demonstrates the basic framework using fork: void main () {INT i; if (fork () == 0) {/ * child process program * / for (i = 1 i <1000; i ) Printf ("this is child process / n");} else {/ * parent process program * / for (i = 1; i <1000; i ) Printf ("this is After process process / n ");}} After the program runs, you can see that there is a thousand information printed with the parent process on the screen. If the program is still running, you can see that there are two it run in the system with the PS command. So what happened when calling this fork function? A program is called a Fork function, and the system prepares the foregoing three segments for a new process. First, the system allows new processes to use the same code segment as the old process, because their programs are still the same, for data segments and The stack segment, the system replicates a new process, so that all the data of the parent process can leave a child process, but once the child process starts, although it inherits all the data of the parent process, but actually data It has been separated, no more affected, which is no longer shared between them. And if you want to share what data is shared, you should use another set of functions (SHMGET, SHMAT, SHMDT, etc.). Now, it is already two processes. For the parent process, the Fork function returns the process number of the subroutine, and for the subroutine, the Fork function returns zero, so for the program, just determine the return value of the Fork function, you know yourself Is it in a parent process or a child process.
The reader may ask, if a big program is running, its data segment and stack are very large, once a Fork is going to copy once, then the Fork system overhead is not very big? In fact, UNIX has its own solution. Everyone knows that the general CPU is allocated with "Page" as the CPU of Intel, which is usually 4K bytes size, regardless of the data segment or The stack segment is composed of many "pages", and the Fork function replicates these two segments, just "logical", not "physics", that is, when actually executing Fork, two processes on physical space Data segments and stack segments are shared. When there is a process writes a certain data, the data between the two processes is different, and the system will distinguish the "page" from physically separate. . The system can be minimized in the overhead of the system. A small humor: The following demonstrates a small program sufficient to "die" Linux, and its source code is very simple: void main () {for (;;) fork ();} This program does not do, that is, death Fork The result is that the program continues to generate the process, and these processes continue to produce new processes, soon, the system's process is full, and the system is "supported" by so much progress. It is not necessary to be root, and anyone runs the above procedure is enough to let the system die. Haha, but this is not the reason for Linux insecurity, because as long as the system administrator is smart enough, he (or her) can set the maximum number of processes that can be run for each user, so as long as it is not root, any process can run. The number may not be in the system's total operation and one tenth of the number of processes, so that the system administrator can deal with the above malicious procedures. (3) How to start another program to see how we will see how the process starts the execution of another program. In Linux, you want to use the exec class's function, the function of the Exec class is more than one, but roughly the same, in Linux, each: Execl, Execlp, Execle, Execv, Execve, and Execvp, I only take Execlp as an example, others What is the difference between the function and the execlp, please understand their specific situation via the Manexec command. Once a process is called, it itself is "dead", the system replaces the code segment into the code of the new program, discard the original data segment and stack segment, and allocates new data segments and stack segments for the new program. The only left is the process number, that is, for the system, or the same process, but it is already another program. (However, there is also information such as inheriting environment variables in the EXEC class function.) So if my program wants to start another program, but what should I continue to run? That is combined with the use of Fork and Exec.
The following segment shows how to start running other programs: char command [256]; void main () {int {Int RTN; / * child process returns value * / while (1) {/ * from the terminal reads the command * / Printf (">"); FGETS (Command, 256, stdin); Command [Strlen (Command) -1] = 0; if (fork () == 0) {/ * child process executes this command * / execlp (Command) If the EXEC function returns, it indicates that there is no normal execution command, the error message * / perror (command); EXIT (ErrorNo);} else {/ * parent process, waiting for the sub-process, and print the child process Return value * / wait (& RTN); PrintF ("Child Process Return% D / N" ,. RTN);}}} This program reads the command from the terminal, after execution, the parent process continues to read from the terminal Enter the command. Friends who are familiar with DOS and Windows systems must know that DOS / Windows also has an Exec class function, which is similar, but DOS / Windows also has a spawn class function, because DOS is a single task system, it can only "parent process" "Residing in the machine and execute the" child process ", which is a function of the spawn class. Win32 is already a multitasking system, but the spawn class function is retained, and the method of implementing the spawn function in Win32 is similar to the method in the aforementioned UNIX. After opening the child process, the child process will continue to run after the child process. Unix is a multi-task system at its beginning, so it does not require a spawn class function from the core perspective. In addition, there is a simpler function system, which is a function of other programs, which is actually equivalent to executing a command in the shell environment, and the EXEC class function is a low-level system call. (4) Linux process and Win32 process / threads are familiar with Win32 programming people must know that Win32's process management is very different from UNIX, in UNIX, only the concept of the process, but in Win32 There is also a "thread" concept, then what is the difference between UNIX and WIN32? In the 1970s, UNIX has been achieved after long-term theory and practice after long-term theory and practice, it allows the operating system to pay the minimum price in process management. On the other hand, Provides a simple multi-process method for programmers. The process / thread in Win32 is inherited from OS / 2. In Win32, "Process" refers to a program, and "thread" is an "clue" in a "process". From the core, Win32's multi-process and Unix have no big difference, and the thread in Win32 is equivalent to UNIX process, is an actual code that is actually executed. However, there is a shared data section between each thread in the same process in Win32. This is the biggest difference with UNIX's process.