1. Exec replacement process image
On Process Creation, Unix adopts a unique method, which separates Process Creation from loading a new process image. The advantage is that there is more room to manage the two operations. After we create a process, we usually replace the child process with a new process image. This can be done using exec functions. Of course, the exec series functions can also replace the current process.
2. Exec Associated Function Group
Include header file <unistd. h>
The exec function can be used to replace the current process with a new process. Exec is a complete series composed of multiple associated functions. The header file <unistd. h>
Prototype
Int execl (const char * path, const char * Arg ,...);
Int execlp (const char * file, const char * Arg ,...);
Int execle (const char * path, const char * Arg,
..., Char * const envp []);
Int execv (const char * path, char * const argv []);
Int execvp (const char * file, char * const argv []);
Int execvpe (const char * file, char * const argv [],
Char * const envp []);
Parameters
The path parameter indicates that the name of the program to be started includes the path name.
Arg parameter indicates the parameter included in the Startup Program
Return Value: 0 is returned for success, and-1 is returned for failure.
The number of parameters for execl, execlp, and execle (all with "L") is variable, and the parameter ends with a null pointer.
The second parameters of execv, execvp, and execvpe are a string array. When the new program starts, it will pass the given parameters in the argv array to main
The function with the name "p" searches for the PATH environment variable to find the executable file of the new program. If the executable file is not in the path defined by path, the absolute file names including subdirectories must be passed as a parameter to these functions.
The function with the last letter "e" can set environment variables.
These functions are usually implemented using execve. This is a conventional practice, and it is not necessary.
Int execve (const char * filename, char * const argv [], char * const envp []);
Note that the first six functions are all c-library functions, while execve is a system call.
Example program:
To demonstrate the function of self-set environment variables, write a small program to output the environment variables of the system.
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
/*************************************** ********************************** > File name: pid_env.c > Author: Simba > Mail: dameng34@163.com > Created time: Sun 24 Feb 2013 07:52:09 pm CST **************************************** ********************************/# Include <stdio. h> # Include <unistd. h> Extern char ** environ; Int main (void) { Printf ("Hello pid = % d \ n", getpid ()); Int I; For (I = 0; Environ [I]! = NULL; I ++) Printf ("% s \ n", Environ [I]); Return 0; } |
Here, Environ is a global variable but is not declared in the header file. Therefore, you need to declare it externally before use. The output is as follows:
Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/process $./pid_env
Hi pid = 5597
Term = VT100
Shell =/bin/bash
Xdg_session_cookie = 0ba97773224d90f8e6cd57345132dfd0-1368605430.130657-1433620678
Ssh_client = 192.168.232.1 8740 22
Ssh_tty =/dev/pts/0
User = Simba
......................
That is, some variables in the system environment are output. If there are many variables, the output is omitted.
When we talk about the fcntl function, we didn't talk about how to set the file descriptor flag when the CMD parameter is f_setfd. The following describes how to use the exec series functions:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
/*************************************** ********************************** > File name: Process _. c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) /* These database functions call the execve system call */ Int main (INT argc, char * argv []) { Char * const ARGs [] = {"ls", "-l", null }; Printf ("entering Main... \ n "); // Execlp ("ls", "ls", "-l", null); // search path with P // Execl ("/bin/ls", "ls", "-l", null); // Variable Parameter with L // Execvp ("ls", argS); // Pass The args array parameter to main // Execv ("/bin/ls", argS );
Int ret; // Ret = fcntl (1, f_setfd, fd_cloexec ); /* Fd_closexec is set to 1 (when the file is opened, the log is set to o_cloexec ), * When execve is executed, the standard output file descriptor is disabled, * The pid_env Program replaced below will not output information on the screen. */ // If (ret =-1) // Perror ("fcntl error ");
Char * const envp [] = {"AA = 11", "BB = 22", null }; Ret = execle ("./pid_env", "pid_env", null, envp); // you can bring environment variables with E. // Execvpe ("ls", argS, envp ); If (ret =-1) Perror ("Exec error "); Printf ("exiting main... \ n "); Return 0; } |
We use exec functions to replace process images. The program to be replaced by the execle function that is not commented out is the one that outputs system environment variables, however, because execle can set its own environment variables, the environment variables output by the replaced process are not those of the system but self-set. The output is as follows:
Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/process $./exec
Entering main...
Hi pid = 5643
AA = 11
BB = 22
If we open the comment of the above fcntl function, that is, set to disable the file descriptor of the standard output (FD = 1) when the exec operation is executed, that is to say, the pid_env Program replaced below will not output information on the screen.
If the process replacement image is successful, it will be executed directly on the main of the replacement process and will not be returned, so the exiting main...
Iii. system functions
Function: the system () function calls "/bin/sh-C command" to execute a specific command and blocks the current process until the command is executed.
Prototype: INT system (const char * command );
Return Value:
If the shell cannot be started to run the command, system will return 127; if there are other errors that cannot be called by system,-1 will be returned. If the system runs smoothly, return the exit code of the command. During system function execution, fork, execve, waitpid, and other functions are called.
We can implement a my_system function by ourselves, as shown below:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
/*************************************** ********************************** > File name: Process _. c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h> # Include <sys/Wait. H># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) Int my_system (const char * command ); Int main (INT argc, char * argv []) { /* Is equivalent to calling/bin/sh-c ls-L | WC-W */ // System ("ls-L | WC-W "); My_system ("ls-L | WC-W "); Return 0; } Int my_system (const char * command) { Pid_t PID; Int status; If (command = NULL) Return 1; If (pid = fork () <0) Status =-1; Else if (pid = 0) { Execl ("/bin/sh", "sh", "-c", command, null ); Exit (127 ); } Else { While (waitpid (PID, & status, 0) <0) { If (errno = eintr) Continue; Status =-1; Break; } } Return status; } |
It should be noted that in the while loop, if the waitpid returns a-1 error, you also need to determine whether it is interrupted by the signal processing function. If yes, continue to wait. Otherwise, the loop jumps out. MAN 7 signal has the following explanations:
If a signal handler is invoked while a system call or library function call is blocked, then either:
* The call is automatically restarted after the signal handler returns; or
* The call fails with the error eintr.
Reference: apue