插件窝 干货文章 linux中fork和exec有什么区别

linux中fork和exec有什么区别

进程 执行 程序 fork 769    来源:    2025-05-03

在 Linux 系统中,fork()exec() 是进程管理的两个核心系统调用,它们的区别和协作关系如下:


1. fork()

  • 作用:创建一个当前进程的子进程(复制父进程)。
  • 关键特性
    • 复制父进程:子进程获得父进程的代码、数据、堆栈、文件描述符等资源的副本(写时复制,COW)。
    • 独立执行:子进程从 fork() 返回处开始执行,与父进程并发运行。
    • 返回值
    • 父进程收到子进程的 PID(>0)
    • 子进程收到 0
    • 失败时返回 -1(如资源不足)。
  • 典型用途:多进程服务(如 Web 服务器)、并行计算。

示例

pid_t pid = fork();
if (pid == 0) {
    printf("Child process (PID: %d)\n", getpid());
} else {
    printf("Parent process (Child PID: %d)\n", pid);
}

2. exec() 系列函数

  • 作用替换当前进程的地址空间,加载并执行一个新程序。
  • 关键特性
    • 不创建新进程:仅替换当前进程的代码、数据、堆栈等。
    • 原进程终止:执行成功后,原进程的代码不再存在(被新程序覆盖)。
    • 函数变体:如 execl(), execv(), execvp() 等(参数传递方式不同)。
  • 典型用途:启动其他程序(如 Shell 执行命令)。

示例

execl("/bin/ls", "ls", "-l", NULL);  // 替换为 `ls -l`
printf("This line is never reached!"); // 除非 exec 失败

核心区别

特性 fork() exec()
进程创建 创建新进程(子进程) 不创建进程,替换当前进程
资源复制 复制父进程资源 完全替换为新程序的资源
执行流 父子进程并发执行相同代码 原进程代码被新程序替代
典型用途 多进程并发 启动外部程序

协作关系

通常结合使用 fork() + exec() 来启动新程序: 1. fork():创建子进程。 2. exec():在子进程中替换为新程序。 3. 父进程:可能通过 wait() 等待子进程结束。

示例

pid_t pid = fork();
if (pid == 0) {
    execl("/bin/ls", "ls", "-l", NULL);  // 子进程执行 ls
    perror("exec failed");              // 仅当 exec 失败时执行
    exit(1);
} else {
    wait(NULL);  // 父进程等待子进程结束
}

常见问题

  • Q: 为什么需要先 fork()exec()
    A: fork() 提供并发能力,exec() 允许执行不同程序。直接调用 exec() 会终止原进程。

  • Q: fork() 的性能开销?
    A: 写时复制(COW)技术减少了内存复制的开销。

  • Q: 如何避免僵尸进程?
    A: 父进程需调用 wait() 或使用信号处理(如 SIGCHLD)。


通过理解 fork()exec() 的区别与协作,可以更灵活地控制 Linux 进程的行为。