BLOG

fork() 和 exec()的区别

fork() 和 exec()的区别

每个应用程序(程序)都是通过进程来执行的,进程是程序的运行实例。 进程是通过不同的系统调用创建的,最流行的是 fork() 和 exec() 。

fork()

pid_t pid = fork();

fork() 通过复制调用进程来创建一个新进程,新进程称为子进程,是调用进程(称为父进程)的完全副本,但以下情况除外:

子进程有自己唯一的进程 ID,并且这个 PID 不匹配任何现有进程组的 ID。

子进程的父进程 ID 与父进程 ID 相同。

子进程不会继承父进程的内存锁和信号量调整。

子代不会从其父代继承未完成的异步 I/O 操作,也不会从其父代继承任何异步 I/O 上下文。

fork()的返回值

成功时,父进程返回子进程的PID,子进程返回 0 。 失败时,在父进程中返回 -1 ,不创建子进程,并适当设置 errno 。

exec()

exec() 系列函数用新的进程映像替换当前进程映像。 它将程序加载到当前进程空间并从入口点运行它。

exec() 系列由以下函数组成,在下面的 C 程序中实现了 execv() ,你可以尝试练习。

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[]);

fork()和exec()的区别

fork() 启动一个新进程,该进程是调用它的进程的副本,而 exec() 用另一个(不同的)进程替换当前进程映像。

在 fork() 的情况下,父进程和子进程同时执行,而控制永远不会返回到原始程序,除非出现 exec() 错误。

示例:

// C program to illustrate use of fork() &

// exec() system call for process creation

#include

#include

#include

#include

#include

#include

int main(){

pid_t pid;

int ret = 1;

int status;

pid = fork();

if (pid == -1){

// pid == -1 means error occured

printf("can't fork, error occuredn");

exit(EXIT_FAILURE);

}

else if (pid == 0){

// pid == 0 means child process created

// getpid() returns process id of calling process

// Here It will return process id of child process

printf("child process, pid = %un",getpid());

// Here It will return Parent of child Process means Parent process it self

printf("parent of child process, pid = %un",getppid());

// the argv list first argument should point to

// filename associated with file being executed

// the array pointer must be terminated by NULL

// pointer

char * argv_list[] = {"ls","-lart","/home",NULL};

// the execv() only return if error occured.

// The return value is -1

execv("ls",argv_list);

exit(0);

}

else{

// a positive number is returned for the pid of

// parent process

// getppid() returns process id of parent of

// calling process

// Here It will return parent of parent process's ID

printf("Parent Of parent process, pid = %un",getppid());

printf("parent process, pid = %un",getpid());

// the parent process calls waitpid() on the child

// waitpid() system call suspends execution of

// calling process until a child specified by pid

// argument has changed state

// see wait() man page for all the flags or options

// used here

if (waitpid(pid, &status, 0) > 0) {

if (WIFEXITED(status) && !WEXITSTATUS(status))

printf("program execution successfuln");

else if (WIFEXITED(status) && WEXITSTATUS(status)) {

if (WEXITSTATUS(status) == 127) {

// execv failed

printf("execv failedn");

}

else

printf("program terminated normally,"\n " but returned a non-zero statusn");

}

else

printf("program didn't terminate normallyn");

}

else {

// waitpid() failed

printf("waitpid() failedn");

}

exit(0);

}

return 0;

}

运行结果:

parent process, pid = 11523

child process, pid = 14188

Program execution successful