📜  fork()和exec()之间的区别(1)

📅  最后修改于: 2023-12-03 14:41:18.852000             🧑  作者: Mango

fork()exec() 之间的区别

在 Unix/Linux 系统中,fork()exec() 是两个非常重要的系统调用。

fork()

fork() 系统调用可以创建一个新的进程,这个新的进程是原进程的副本,也就是说,它继承了原进程的数据和代码段、堆和栈等资源。新进程有自己的进程 ID,与原进程的 ID 是不同的。同时,它有一个独立的地址空间,这个地址空间包含了原进程数据和代码的一份副本。

fork() 的返回值不同,如果返回 0,则表示当前进程是新创建出来的子进程;如果返回大于 0 的值,则表示当前进程是原来的父进程。两个进程的内存地址可以通过 getpid() 系统调用来获取。

#include<unistd.h>
pid_t fork(void);
exec()

exec() 系统调用可以用来替换当前进程的内存映像,也就是说,执行一个新的程序文件,并且将当前进程所占用的空间全部释放掉,替换成新的进程的地址空间。

在调用这个函数之前,你需要先用 fork() 创建一个新的进程,然后在这个新的进程中执行 exec() 函数。这个函数接受两个参数,第一个参数是新程序的路径名,第二个参数是一个数组,这个数组表示新程序的命令行参数。第一个参数是必须的,但是第二个参数可以为 NULL。如果要传入命令行参数,数组的最后一个元素必须为 NULL。

#include<unistd.h>
int execve(const char *filename, char *const argv[], char *const envp[]);
区别
  • fork() 用于创建一个新的进程,而 exec() 用于执行一个新的程序文件。
  • fork() 返回一个新的进程 ID,而 exec() 并不会返回。
  • fork() 只能创建出新的副本进程,而它们之间并没有共享内存,也没有什么联系。而 exec() 可以重新启动一个新的进程,它可以继承上一个进程的环境变量和其他一些变量信息,就好像它们是一个整体一样。
示例
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
    pid_t pid;
    char *const args[] = {"./hello", "world", NULL};

    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        /* 子进程 */
        if (execve(args[0], args, NULL) == -1) {
            perror("execve");
            exit(EXIT_FAILURE);
        }
    } else {
        /* 父进程 */
        printf("Parent process\n");
        exit(EXIT_SUCCESS);
    }

    return 0;
}

这个程序创建了一个子进程,并在子进程中执行了另一个程序 hello,这个程序把它的命令行参数打印出来。