Linux Programming Learning Notes----process management and program development (next)

Source: Internet
Author: User
Tags glob openlog syslog

Reprint Please specify source: http://blog.csdn.net/suool/article/details/38419983, thank you!


Process management and its control creation process

Fork () function

Function description See: http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

Return value: Upon successful completion, fork() shall return 0 to the child process and shall return the process ID of the Childprocess to the parent process. Both processes shall continue to execute from theFork() function. Otherwise, 1 shall bereturned to the parent process, no child process shall be created, anderrno shall is set to Indicate the error.

After the fork () function is successfully called, the PCB and user memory space will be requested for the child process. The child process replicates almost all the information of the parent process, copying all the data (code snippets, data segments, BSS, heaps, stacks) in the user space, copying the vast majority of the information of the parent process's kernel space PCB. The child process inherits the following attributes from the parent process: Valid user/group number, Process group number, environment variable, closing flag on file execution, signal processing mode setting, signal masking set, current working directory, root directory, file mask format, file size limit, open file descriptor.

To create a child process example:

#include <stdio.h> #include <unistd.h> #include <sys/types.h>int main (int Argc,char *argv[]) {pid_t Pid;if ((Pid=fork ()) ==-1)          //Create child process, run printf ("Fork Error") in parent process;p rintf ("bye!\n");        The parent-child process will execute this return 0;}

Result:

Here is also a:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>int main (void) {pid_t pid;if (pid=fork ( ) ==-1)   //Create Child process printf ("fork Error"); else if (pid==0) {printf ("in the" process\n ");  There is code}else{printf running in the subprocess ("in the parent process\n");//code running in the parent process}return 0; The parent-child process will return}

Result:


In the previous study, we know that the file buffer resource is in the user space area, so the user space of the child process that is created will replicate all the information of the parent process's user space, obviously including the buffered stream. If there is information in the parent process buffer stream, it is also copied into the user space buffer stream of the child process.

As follows:

#include <stdio.h> #include <sys/types.h> #include <unistd.h>int main (void) {pid_t pid;if (pid=fork ( ) ==-1)   //Create Child process printf ("fork Error"); else if (pid==0) {printf ("in the" process\n ");  There is code}else{printf running in the subprocess ("in the parent process\n");//code running in the parent process}return 0; The parent-child process will return}


Processing of the file descriptor opened by the child process to the parent process

When you create a child process, the parent-child process handles the open file as follows:


The sample code is as follows:

#include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <    String.h> #include <stdlib.h>int main (int Argc,char *argv[]) {pid_t pid;    int FD;    int i=1;    int status;    Char *ch1= "Hello";    Char *ch2= "World";    Char *ch3= "in"; if ((Fd=open ("Test.txt", o_rdwr|    o_creat,0644) ==-1)//Open a file in o_creat mode {perror ("parent open"); exit (Exit_failure);    } if (Write (Fd,ch1,strlen (CH1)) ==-1)//parent process writes data to file {perror ("parent write"); exit (Exit_failure);    } if ((Pid=fork ()) ==-1)//Create new Process {perror ("fork"); exit (Exit_failure);             } else if (pid==0)//child process {i=2;printf ("in child\n");p rintf ("i=%d\n", I);        Print I-value if (Write (Fd,ch2,strlen (CH2)) ==-1)//write file, share perror with parent process ("Child write");    return 0;      } else//parent Process {sleep (1);p rintf ("in parent\n");p rintf ("i=%d\n", I); Prints the I value, compared to the sub-process if (write (Fd,ch3,strlen (CH3)) ==-1)//write operation, the result is added to the tail perror ("parEnt,write "); Wait (&status);    Wait for process to end return 0; }}

Operation Result:


As can be seen from the above, parent-child processes share File table entries, not cross-overwrite writes, shared file offsets.

Vfork () function

Vfork () Creates a child process without copying the address space of the parent process, but only when it is necessary to replicate it. If the child process executes the EXEC () function, the data space that is copied from the parent process to the child process by using the fork () function is no longer used. This is inefficient, making the vfork () function very useful. Depending on the size of the parent process data space, vfork () can improve performance to a large extent than fork (). Vfork () replicates only when needed, and generally takes the form of sharing all resources with the parent process.

See also: http://pubs.opengroup.org/onlinepubs/009695399/functions/vfork.html

In the process of execution, the fork () and vfork () functions make a difference, and the fork () function replicates a copy of a parent process, thus having its own separate code snippet, data segment, and stack space, which becomes an independent entity. Vfork () is the code and data segment that shares the parent process.

Here's a sample of the program and this difference:

#include <unistd.h> #include <error.h> #include <sys/types.h> #include <stdio.h> #include < Stdlib.h>int glob=6;            The global already initialized variable, located in the data segment int main () {int var;pid_t pid;var=88;        Local variables, located in the stack space printf ("in beginning:\tglob=%d\tvar=%d\n", Glob,var); Print global variable, local variable if ((Pid=vfork ()) <0) {perror ("vfork"); exit (exit_failure);} else if (pid==0)    //child process {printf ("in child,modify the var:glob++,var++\n"); glob++;     The child process modifies the global variable var++;      Modifying local variables in a child process printf ("in child:\tglob=%d\tvar=%d\n", Glob,var); _exit (0);   Use _exit () to exit the}else     //parent process to print two variables {printf ("in parent:\tglob=%d\tvar=%d\n", Glob,var); return 0;}}

Compile run Result:

Now change the vfork in the above program to the fork () function, and the result is:

The child function calls the Vfork () function to create a child process

Here is an example:

First post the results of the operation:

There was clearly a paragraph error.

The code is as follows:

#include <stdio.h> #include <unistd.h> #include <stdlib.h>void test ()          //Call the Vfork () function in this function {    pid_t pid;    Pid=vfork ();    if (pid==-1)    {       perror ("vfork");       Exit (exit_failure);    }    else if (pid==0)   //child process the print process information is returned, from the results, it works    {          printf ("1:child pid=%d,ppid=%d\n", Getpid (), Getppid ()) ;        return;    }    else             /Parent process printing process information, from the results, can be run normally       printf ("2:parent pid=%d,ppid=%d\n", Getpid (), Getppid ());} void Fun ()           //This function code, from the result, can run {                    //But does not work in the parent process, there is a segment error    int i;   int buf[100];   for (i=0;i<100;i++)       buf[i]=0;   printf ("3:child pid=%d,ppid=%d\n", Getpid (), Getppid ());} int main () {   pid_t pid;       Given a temporary variable, no   test () is used;          Call Test fun   ();           Call Fun}
Here is an explanation of why the error occurred:


Running new code in the process

function function and Introduction

After you create a child process using the fork () function, you can call the EXECX series function if you want to run a new program in the current process. When the process calls EXECX

Any one of the series functions, the process user resource is completely replaced by the new program.

function differences:


function of the specific functions and use of access to relevant information can be.

Execute new code to open file for processing

When executing the EXEC series function, by default, the new code can use the file descriptor opened in the original code, that is, when the EXEC series function is executed, the file that was originally opened by the process is not closed.

Reclaim User Space Resources

is a Linux system, you can use the following methods to reclaim user space resources.

    • Show call exit or _exit system call
    • Execute the return statement in the main function
    • Implicitly leaving the main function, for example, encountering the Mian function}

The process needs to execute the registered exit handler function, flush the stream buffer, and so on before the normal exit, and then free all resources of the process user space. The Process Control block PCB is not released at this point. Only the process that calls the Exit function belongs to a zombie process.

There is an essential difference between the exit and return of the C language.

Reclaim Kernel Space Resources

The above describes the release of the process when the user space resources, but the process PCB is released, this work is obviously not done by itself, but by the current process of the parent process, can be displayed by calling the wait and waitpid function to complete. At the end of the function, consult the function description document.

Orphan process and zombie process

Orphan process: Because the parent process exits the process that causes a child process to be adopted by the INIT process, it is the orphan process that the parent process changes to the INIT process, and the kernel resources are reclaimed by it.

Zombie Process: The process has exited, but his parent process has not yet reclaimed his kernel space resources. That is, the process's PCB in the kernel space is not recycled.

The following is an example of an orphan process:

#include <stdio.h> #include <stdlib.h> #include <unistd.h>int main () {pid_t pid;if ((Pid=fork ()) ==-1) Perror ("fork"), else if (pid==0) {printf ("pid=%d,ppid=%d\n", Getpid (), Getppid ()), Sleep (2);p rintf ("pid=%d,ppid=%d\n" , Getpid (), Getppid ());} Elseexit (0);}

1693 is the init process for the current user.

Modify process user-related information

1. Access verifies user permissions

This function checks whether the current process has the appropriate access rights to a file.

2. Set process Real User UID

Use the setuid function.

The Setgid function can modify the GID of the user of the process.

3, set the process of the effective user Euid

Using the Seteuid function

Setegid set Egid.

As long as the above function is known, it is OK to check the corresponding document description when using it.

Special process of Linux waiting process

A daemon (Daemon) is a special process that runs in the background. It is independent of the control terminal and periodically performs some sort of task or waits to handle certain occurrences. Daemons are a very useful process. Most Linux servers are implemented with daemons. For example, the Internet server Inetd,web server httpd and so on. At the same time, the daemon completes many system tasks. For example, the job planning process Crond, the printing process lpd and so on.
The daemon programming itself is not complex, the complexity of the various versions of UNIX implementation mechanism is not the same, resulting in different UNIX environment daemon programming rules are not consistent. This requires the reader's attention that copying some of the rules of the book (especially BSD4.3 and the lower version of System V) to Linux will be wrong.

How to start the waiting process:
    • The startup script starts when the system starts.
    • Start with the inetd super server, such as Telnet.
    • A process that is started periodically by the cron command and started with the Nohup command in the terminal is also the waiting process.
daemon and its characteristics

The most important feature of the daemon is running in the background. At this point, the resident memory program in DOS is similar to the TSR. Second, the daemon must be isolated from the environment before it runs. These environments include file descriptors that are not closed, control terminals, session and process groups, working directories, and file creation masks. These environments are typically inherited by daemons from the parent process that executes it, especially the shell. Finally, the way the daemon is launched has its special place. It can be started from the startup script/ETC/RC.D when the Linux system starts, can be started by the job planning process Crond, and can be performed by the user terminal (usually the shell).
In short, despite these peculiarities, daemons are basically no different from ordinary processes. Therefore, the process of writing a daemon is actually transforming a normal process into a daemon based on the nature of the daemon described above. It is easier to understand and program if the reader has a deeper understanding of the process.

Programming Essentials for Daemons

As mentioned earlier, the programming rules for daemons in different UNIX environments are not consistent. Fortunately, the Daemon programming principle is the same, the difference is that the specific implementation details are different. The principle is to satisfy the nature of the daemon. At the same time, Linux is based on Syetem v SVR4 and follows the POSIX standard, which is more convenient than BSD4. Programming essentials are as follows;
1. Run in the background.
To avoid suspending the control terminal, put the daemon into the background. The method is to call fork in the process to terminate the parent process, allowing Daemon to execute in the background in the child process.
if (Pid=fork ())
Exit (0);//is the parent process that ends the parent process, and the child process continues
2. Out of control terminal, logon session and process group
It is necessary to introduce the relationship between the process and the control terminal in Linux, the logon session and the process group: the process belongs to a process group, and the process group number (GID) is the process number (PID) of the process leader. A logon session can contain multiple process groups. These process groups share a control terminal. This control terminal is usually the login terminal of the creation process.
Control terminals, logon sessions and process groups are usually inherited from the parent process. Our aim is to get rid of them so that they are not affected by them. The method is based on the 1th, call Setsid () to make the process a conversation leader:
Setsid ();
Description: The Setsid () call failed when the process was the session leader. But the 1th has ensured that the process is not a conversation leader. After the Setsid () call succeeds, the process becomes the new session leader and the new process leader, and is detached from the original logon session and process group. Due to the exclusivity of the session process to the control terminal, the process is disconnected from the control terminal at the same time.
3. Disable process re-opening control terminal
Now, the process has become a session leader without terminal. But it can be re-applied to open a control terminal. You can prevent a process from reopening the control terminal by making the process no longer a session leader:
if (Pid=fork ())
Exit (0);//End first child process, second child process continue (second child process is no longer a conversation leader)
4. Close the Open file descriptor
The process inherits the open file descriptor from the parent process that created it. Without shutting down, system resources will be wasted, causing the file system where the process is located to fail to unload and cause unexpected errors. Close them as follows:
For (i=0;i Close Open file descriptor Close (i);>
5. Change the current working directory
The file system in which the working directory resides cannot be unloaded while the process is active. It is generally necessary to change the working directory to the root directory. For processes that require dump cores, the process that writes the log changes the working directory to a specific directory such as/tmpchdir ("/")
6. Resetting the file creation mask
The process inherits the file creation mask from the parent process that created it. It may modify the access bit of the file created by the daemon. To prevent this, the file creation mask is cleared: umask (0);
7. Handling SIGCHLD Signals
Processing SIGCHLD signals is not a must. However, for some processes, in particular, server processes often generate child processes to process requests when requests arrive. If the parent process does not wait for the child process to end, the child process becomes a zombie process (zombie) and thus consumes system resources. If the parent process waits for the child process to end, it increases the burden on the parent process and affects the concurrency performance of the server process. The operation of the SIGCHLD signal can be easily set to Sig_ign under Linux.
Signal (sigchld,sig_ign);
This way, the kernel does not spawn a zombie process at the end of the child process. Unlike BSD4, the BSD4 must explicitly wait for the child process to end before releasing the zombie process.

Log Information

In order to tell the system administrator to wait for the process to run, especially when an exception occurs, the waiting process needs to output specific information, and the waiting process can not output information to a terminal, so the general use of output to the log information method. There are two ways to write log messages for the waiting process under Linux:

    • Processes directly linked to log files

    • Use the log to wait for a process

The system established a log waiting process syslogd specialized in the management of various log files.

In general, calling the Openlog function will establish a connection to the log waiting process, which requires that the function be called when the log information needs to be written.

The syslog () generates a log message, which is then published by the log-waiting process to each log file.

The specific usage of each function needs to be explained.


Example of a waiting process:

#include <unistd.h> #include <signal.h> #include <fcntl.h> #include <sys/syslog.h> #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <         Stdlib.h>int Init_daemon (const char *pname, int facility) {int PID;     int i;  Signal (sigttou,sig_ign);      Processing of possible terminal signal signal (sigttin,sig_ign);      Signal (sigtstp,sig_ign);         Signal (SIGHUP, sig_ign);         if (Pid=fork ())//Create child process, parent process exits exit (exit_success);        else if (pid< 0) {perror ("fork"); exit (Exit_failure);                } setsid ();         Set up a new session leader, new process leader, out of the terminal if (Pid=fork ())//Create a new process, the child process can not be at the application Terminal exit (exit_success);        else if (pid< 0) {perror ("fork"); exit (Exit_failure);         } for (i=0;i< nofile;++i)//Close the file descriptor opened by the parent process close (i);    Open ("/dev/null", o_rdonly); Redirect all of the standard input output to/dev/null open ("/dev/nulL ", O_RDWR);        Since all file descriptors were previously closed, the newly opened value bit 0,1,2 open ("/dev/null", O_RDWR);                   ChDir ("/tmp");                        Modify the main directory umask (0);         Reset file Mask signal (sigchld,sig_ign); Process subprocess Exit Openlog (PName, log_pid, facility); Connect with the waiting process, plus the process number, the file name return;         } int main (int argc,char *argv[]) {FILE *fp;         time_t ticks; Init_daemon (Argv[0],log_kern);  Execute the Wait process function while (1) {sleep (1); Ticks=time (NULL);  Reads the current time syslog (Log_info, "%s", Asctime (LocalTime (&ticks)));  Write Log Message}}


NEXT

Inter-process communication-pipelines

Linux asynchronous signal Processing mechanism


Reprint Please specify source: http://blog.csdn.net/suool/article/details/38419983, thank you!

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.