Sometimes we need to start another program (process) in our own program to help us do some work, so how do we start other processes in our own process? There are a number of ways to do this in Linux, and here's a description of the differences between these methods. First, the system function calls the prototype of the system function:
[CPP]View Plaincopyprint?
- #include <stdlib.h>
- int system (const char *string);
Its purpose is to run the command passed to it as a string parameter and wait for the command to complete. The execution of the command is like executing a command in the shell: sh-c string. If the shell cannot be started to run this command, the system function returns error code 127, or 1 if it is a different error. Otherwise, the system function returns the exit code for the command. Note: The system function call uses a shell to start the program that you want to execute, so you can put the program in the background to execute, where the system function call will return immediately. The following example can be first, the source file is NEW_PS_SYSTEM.C, the code is as follows:
[CPP]View Plaincopyprint?
- #include <stdlib.h>
- #include <stdio.h>
- &NBSP;&NBSP;
- int main ()
- {
- printf (
- //ps process is finished before returning. To continue execution of the following code
- system (// 1
- printf ( "ps done\n");
- exit (0);
- }&NBSP;&NBSP;
The program calls the PS program to print all processes related to this user, and finally prints PS done. The results of the operation are as follows: If you change the statement of note 1 to system ("PS Au &"), the system function returns immediately without waiting for the PS process to end to execute the following code. So you see the output, PS done may not appear in the last line, but in the middle. In general, using the system function is not an ideal way to start other processes because it must use a shell to start the required program, that is, to start a shell before starting the program, and to have a high dependency on the environment of the shell, so it is inefficient to use the system function. Second, replace the process image--using the EXEC series function The EXEC series function consists of a set of related functions, which differ in how the process is started and how the program parameters are expressed. But the EXEC series function has a common way of working, is to replace the current process with a new process, that is, you can use the EXEC function to switch the execution of the program from one program to another, after the new program starts, the original program is no longer executed, The new process is specified by the path or file parameter. The EXEC function is more efficient than the system function. The types of EXEC series functions are:
[CPP]View Plaincopyprint?
- #include <unistd.h>
- Char **environ;
- int execl (const Char *path, const char *arg0, ..., (char*) 0);
- int EXECLP (const Char *file, const char *arg0, ..., (char*) 0);
- int execle (const Char *path, const char *arg0, ..., (char*) 0, char *const envp[]);
- int Execv (const Char *path, char *const argv[]);
- int EXECVP (cosnt char *file, char *const argv[]);
- int Execve (const Char *path, char *const argv[], char *const envp[]);
This type of function can be divided into two categories, execl, EXECLP, and execle parameters are mutable, ending with a null pointer, and the second argument of Execv, EXECVP, and Execve is an array of strings, which, when invoking a new process, argv the parameters of the main function of the new process. ENVP can be used as the environment variable for the new process, passing it to the new process, thereby making the variable its available environment variables. Take the previous example, if you want to use the Exec system function to start the PS process, then the 6 different functions of the call statement is: NOTE: arg0 is the name of the program, so in this example is all PS.
[CPP]View Plaincopyprint?
- char *Const ps_envp[] = {"Path=/bin:usr/bin", "Term=console", 0};
- char *Const ps_argv[] = {"PS", "Au", 0};
- Execl ("/bin/ps", "PS", "au", 0);
- EXECLP ("PS", "PS", "au", 0);
- Execle ("/bin/ps", "PS", "au", 0, PS_ENVP);
- Execv ("/bin/ps", PS_ARGV);
- EXECVP ("PS", PS_ARGV);
- Execve ("/bin/ps", PS_ARGV, PS_ENVP);
Below I give a complete example, the source file name is NEW_PS_EXEC.C, the code is as follows:
[CPP]View Plaincopyprint?
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
-
Li class= "alt" > int main ()
- {
- printf ( "running ps with execlp\n") ;
- execlp ( "PS", "au", (char*) 0);
- printf (
- exit (0);
- }
The result of the operation is as follows: Careful words, you can find that the last PS done has no output, is it accidental? Not, because we did not return to the program New_ps_exec.exe again, because when the EXECLP function is called, the New_ps_exec.exe process is replaced by the PS process, and when the PS process is finished, the entire program ends and does not return to the original New_ps_ On the Exec.exe process, the original process New_ps_exec.exe no longer executes, so the statement printf ("PS done") does not have a chance to execute at all. Note that in general, the EXEC function is not returned unless an error returns 1, a new process initiated by exec inherits many of the attributes of the original process, and the file descriptor opened in the original process will remain open in the new process, but any directory streams that have been opened in the original process will be closed in the new process. Third, copy process image--fork function 1, the application of the fork function exec calls to replace the currently executing process with a new process, and we can also use fork to copy a new process, the new process is almost identical to the original process, the execution of the code is identical, but the new process has its own data space, Environment and file descriptors. The prototype of the fork function is:
[CPP]View Plaincopyprint?
- #include <sys/type.h>
- #include <unistd.h>
- pid_t Fork ();
Note: In the parent process, fork returns the PID of the new child process, and the fork in the subprocess returns 0, which we can use to judge the parent and child processes, and if the fork call fails, it returns-1. Inherit the above example, below I give an example of calling PS, the source file name is NEW_PS_FORK.C, the code is as follows:
[CPP]View Plaincopyprint?
- #include <unistd.h>
- #include <sys/types.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main ()
- {
- pid_t pid = fork ();
- switch (PID)
- {
- case-1:
- Perror ("fork failed");
- Exit (1);
- Break ;
- Case 0:
- //This is called EXECLP Switch to PS process in child process
- printf ("\ n");
- EXECLP ("PS", "PS", "au", 0);
- Break ;
- Default:
- //This is the output related message in the parent process
- printf ("Parent, PS done\n");
- Break ;
- }
- Exit (0);
- }
The output is: we can see, before the 2nd did not appear in PS done is printed out, but the order is a bit wrong, this is because the parent process before the subroutine execution, so the first output of the parent, PS done, there is no way to let it output after the child process, of course, is to use the wait and WAITPID functions. Note that, in general, the parent process has no relation to the child process's life cycle, and even if the parent process exits, the child process can still function correctly. 2. Wait for a process the prototype of the wait function and the Waitpid function is:
[CPP]View Plaincopyprint?
- #include <sys/types.h>
- #include <sys/wait.h>
- pid_t Wait (int *stat_loc);
- pid_t waitpid (pid_t pid, int *stat_loc, int options);
Wait is used to invoke in the parent process, let the parent process pause execution waiting for the end of the child process, return the PID of the subprocess, and if Stat_loc is not a null pointer, the state information will be written to the location pointed to by Stat_loc. Waitpid the end of a child process that waits for a process ID of PID (PID is-1, which returns information for any child process), the Stat_loc parameter behaves the same as the wait function, and options is used to change the behavior of the Waitpid, which has an important option Wnohang, Its role is to prevent the execution of waippid callers from suspending. If the child process does not end or terminates unexpectedly, it returns 0, otherwise the PID of the subprocess is returned. The changed program is saved as the source file new_ps_fork2.c, the code is as follows:
[CPP]View Plaincopyprint?
- #include <unistd.h>
- #include <sys/types.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main ()
- {
- pid_t pid = fork ();
- int stat = 0;
- switch (PID)
- {
- case-1:
- Perror ("fork failed");
- Exit (1);
- Break ;
- Case 0:
- //This is called EXECLP Switch to PS process in child process
- printf ("\ n");
- EXECLP ("PS", "PS", "au", 0);
- Break ;
- Default:
- //This is in the parent process, waiting for the child process to end and outputting the relevant prompt information
- PID = Wait (&stat);
- printf ("Child has Finished:pid =%d\n", PID);
- //Check the exit status of the child process
- if (wifexited (stat))
- printf ("Child exited with code%d\n", Wexitstatus (stat));
- Else
- printf ("Child terminated abnormally\n");
- printf ("Parent, PS done\n");
- Break ;
- }
- Exit (0);
- }
The output is: you can see that this output is finally normal, the parent output is also after the output of the child process. Summary--Comparison of three ways to start a new process first is the simplest system function, which needs to start a new shell and execute a child process in the new shell, so it is much more dependent on the environment and less efficient. At the same time, the system function waits for the child process to return to execute the following statement. The EXEC system function replaces the original process with a new process, which is more efficient, but it does not return to the original process, meaning that the code is not executed after the EXEC function unless the EXEC call fails. However, the new process initiated by exec inherits many of the characteristics of the original process, and the file descriptor opened in the original process remains open in the new process, but it is important to note that any directory streams that have been opened in the original process will be closed in the new process. Fork is to use the current process to replicate a new process, the new process is the same as the original process, the execution of the same code is identical, but the new process has its own data space, environment variables and file descriptors, we usually based on the return value of the fork function to determine whether the current process is a child process or a parent process, That is, it does not return as exec does, but returns a pid_t value for judgment, and we can continue to execute the code behind the fork. Feel the fork and Exec series functions can create a lot of required processes
Several methods and comparisons of Linux starting a new process [go]