When a process calls one of exec functions, the process is completely replaced by the new program, and the new program starts executing from the main function. exec merely replaces the current process, text, data, heap and stack segments while retaining the process ID.
System Definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h
......
/* Replace the current process, executing PATH with arguments ARGV and
environment ENVP. ARGV and ENVP are terminated by NULL pointers. */
extern int execve (const char *__path, char *const __argv[],
char *const __envp[]) __THROW __nonnull ((1, 2));
......
/* Execute PATH with arguments ARGV and environment from `environ'. */
extern int execv (const char *__path, char *const __argv[])
__THROW __nonnull ((1, 2));
/* Execute PATH with all arguments after PATH until a NULL pointer,
and the argument after that for environment. */
extern int execle (const char *__path, const char *__arg, ...)
__THROW __nonnull ((1, 2));
/* Execute PATH with all arguments after PATH until
a NULL pointer and environment from `environ'. */
extern int execl (const char *__path, const char *__arg, ...)
__THROW __nonnull ((1, 2));
/* Execute FILE, searching in the `PATH' environment variable if it contains
no slashes, with arguments ARGV and environment from `environ'. */
extern int execvp (const char *__file, char *const __argv[])
__THROW __nonnull ((1, 2));
/* Execute FILE, searching in the `PATH' environment variable if
it contains no slashes, with all arguments after FILE until a
NULL pointer and environment from `environ'. */
extern int execlp (const char *__file, const char *__arg, ...)
__THROW __nonnull ((1, 2));
......
If the execution file is not executable, then it will launch /bin/sh to run against the file.
If we don't pass the environment variable then it will use global variable "environ" of the current process.
For each file descriptor of current process, if its FD_CLOEXEC flag is on, it will be closed after running the exec, otherwise it will keep open.
Real user id and real group id will keep same, but the effective user id and effective group id will depend on the "set_user_id", "set_group_id" flag of executable file.
Only execve is the system call, the calling relationship of different functions:
execlp -(build argv)-> execvp
execl -(build argv)-> execv
execle -(build argv)-> execve
execvp->execv->execve(system call)
2. Example
echoall.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc, char* argv[])
{
int i;
char **ptr;
for(i = 0; i < argc; i++)
printf("argv[%d]: %s\n", i, argv[i]);
for(ptr = __environ; *ptr != 0; ptr++)
printf("%s\n", *ptr);
exit(0);
}
shell:
ubuntu@ip-172-31-23-227:~$ ./echoall.out Hello world
argv[0]: ./echoall.out
argv[1]: Hello
argv[2]: world
XDG_SESSION_ID=60
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=67.243.178.100 50301 22
SSH_TTY=/dev/pts/0
USER=ubuntu
......
proc.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
char *env_init[]={"USER=unknown", "PATH=/tmp", NULL};
int main(int argc, char* argv[])
{
pid_t pid;
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if (pid == 0) {
// Note: we have to convert 0 to (char*), if in current system
// memory usage for int and pointer are different, then it would
// cause error
if(execle("./echoall.out", "First Arg", "Second Arg", (char*)0, env_init) < 0) {
printf("execle error!\n");
exit(3);
}
exit(0);
}
// Wait for the child process finish firstly
if(waitpid(pid, NULL, 0) < 0) {
printf("waitpid error!\n");
exit(2);
}
if((pid = fork()) < 0) {
printf("fork error!\n");
exit(1);
}
else if (pid == 0) {
if(execlp("echoall.out", "First Arg", "Second Arg", (char*) 0) < 0) {
printf("execlp error!\n");
exit(3);
}
}
// Wait for the child process finish firstly
if(waitpid(pid, NULL, 0) < 0) {
printf("waitpid error!\n");
exit(2);
}
exit(0);
}
shell:
Note:
If running the program from the shell, the shell will put first argument as the program name automatically. In this case ,we just provide the "First Arg", "Second Arg" as two arguments, so we can't see the program name as argument.
ubuntu@ip-172-31-23-227:~$ ./proc.out
argv[0]: First Arg
argv[1]: Second Arg
USER=unknown
PATH=/tmp
argv[0]: First Arg
argv[1]: Second Arg
XDG_SESSION_ID=60
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=67.243.178.100 50301 22
SSH_TTY=/dev/pts/0
USER=ubuntu
......
No comments:
Post a Comment