Linux系统编程(vfork和fork)

news/2024/7/7 20:14:23

文章目录

  • 前言
  • 一、vfork讲解
  • 二、vfork使用
  • 三、exit和_exit
    • 1.exit和_exit对比
    • 2.在vfork中的使用
  • 四、vfork和fork区别
  • 总结


前言

本篇文章讲解vfork和fork创建进程的区别。

一、vfork讲解

vfork 是一个在类Unix操作系统中的系统调用,它创建一个新进程,且该进程与父进程共享内存空间。Vfork系统调用的目的是为了在子进程中执行一个新的程序,通常是通过调用exec系列函数来实现。

vfork 的函数原型如下:

#include <unistd.h>

pid_t vfork(void);

vfork 函数返回一个正值给父进程,返回0给子进程,或者返回一个负值表示创建失败。父进程和子进程之间的主要区别在于在子进程调用 exec 函数之前,它会挂起父进程的执行。这样,子进程可以直接执行一个新的程序,而不需要复制父进程的地址空间。

使用 vfork 创建的子进程与父进程共享同一个地址空间,这意味着子进程可以直接访问父进程的变量、函数和堆栈等。由于父进程被挂起,直到子进程调用 exec 函数或 _exit 函数终止,父进程在子进程运行期间是阻塞的。

需要注意的是,由于子进程与父进程共享同一份地址空间,因此在子进程中修改父进程的变量和数据可能会导致不可预期的行为,因此要小心使用。一般来说,vfork 主要用于创建一个新进程,并在该进程中立即调用 exec 函数来加载一个新程序。这样可以避免复制父进程的大型地址空间,提高创建子进程的效率。

总结一下,vfork 是一个在类Unix操作系统中的系统调用,用于创建一个新进程,并与父进程共享地址空间。子进程通过调用 exec 函数来执行一个新程序。父进程在子进程调用 exec 函数之前会被挂起,直到子进程结束或调用 _exit 函数。使用 vfork 可以避免复制父进程的地址空间,从而提高创建子进程的效率。但要小心在子进程中修改父进程的变量和数据,以避免不可预期的结果。

在这里插入图片描述

二、vfork使用

这里使用vfork创建了进程:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

#define EXE "test"

int main(void)
{
    int pid = 0;

    char* argv[3] = {EXE, "world", NULL};

    printf("begin\n");

    printf("now pid : %d\n", getpid());

    if((pid = vfork()) != 0)
    {
        //父进程
    }
    else
    {
        //子进程
        execve(EXE, argv, argv);
        _exit(0);
    }  

    printf("end\n");

    return 0;
}

三、exit和_exit

1.exit和_exit对比

_exit 和 exit 是两个在C语言中常用的函数,用于进程的终止。它们的主要区别在于以下几点:

头文件不同:_exit 函数在 <unistd.h> 头文件中声明,而 exit 函数在 <stdlib.h> 头文件中声明。

执行清理函数的行为:_exit 函数会直接终止进程,不会执行任何清理操作,包括清理注册的函数(比如通过 atexit 注册的函数)。而 exit 函数在终止进程之前会执行这些清理函数,包括文件的关闭、内存的释放、缓冲区的刷新等。这使得 exit 函数更适合用于正常的进程终止,可以确保资源被正确释放。

返回值的意义不同:_exit 函数的返回值作为进程的终止状态,可以被父进程通过 wait 系统调用获取到。而 exit 函数的返回值通常被忽略,它会被用作状态码传递给父进程,父进程可以通过相关的方式读取该状态码,例如在 shell 中使用 $? 来获取。

缓冲区刷新:_exit 函数不会刷新缓冲区,这意味着通过 printf 等函数输出的内容可能不会立即显示出来。而 exit 函数会刷新缓冲区,确保所有的输出都被写入对应的文件或在屏幕上显示出来。

2.在vfork中的使用

vfork 创建的子进程通常只能调用 _exit 函数,而不应该调用 exit 函数。这是因为 vfork 在创建子进程时会共享父进程的地址空间,包括栈、堆和全局变量等。子进程在调用 exec 或 _exit 函数之前不能修改父进程地址空间中的任何数据,否则会导致不可预测的行为。

exit 函数在执行时会进行一系列的清理工作,包括关闭文件描述符、释放动态分配的内存、刷新缓冲区等。这些操作可能会影响到父进程状态和资源的正确释放,而且在共享地址空间的情况下,子进程对这些资源的修改会影响到父进程。

为了避免这种混乱和不确定性,vfork 子进程应该尽量快速地调用 _exit 函数来终止自己。_exit 函数直接终止进程,不进行任何清理,并且不会影响到父进程的状态或资源。

总结起来,vfork 创建的子进程应该使用 _exit 函数来终止自己,而不应该调用 exit 函数。这样可以避免对父进程地址空间中的数据和资源产生不可预测的影响,确保子进程的终止操作不会影响到父进程。

四、vfork和fork区别

vfork 和 fork 是两个在类Unix操作系统中常用的系统调用,用于创建新的进程。它们之间的主要区别如下:

1.地址空间的复制方式:vfork 创建的子进程与父进程共享地址空间,而 fork 创建的子进程会复制父进程的地址空间。这意味着在 vfork 的子进程中,对地址空间的修改会影响到父进程,而在 fork 的子进程中,修改则是独立的。

2.父进程的行为:vfork 创建的子进程会共享父进程的资源(如文件描述符、堆栈等),并且父进程会在子进程调用 exec 或 _exit 函数之前挂起。而 fork 创建的子进程会复制父进程的资源,并且父进程和子进程可以同时运行。

3.子进程的返回值:在 vfork 中,子进程的返回值是通过函数返回值方式返回的,即在子进程中直接返回,而在父进程中可以通过获取子进程的返回值。而在 fork 中,子进程的返回值为0,父进程中可以通过获取子进程的PID来区分父进程与子进程。

4.父进程的阻塞:在 vfork 中,父进程会在子进程调用 exec 或 _exit 函数之前一直被阻塞,直到子进程终止或执行了新的程序。而在 fork 中,父进程和子进程可以并发执行,它们的执行顺序取决于操作系统的调度算法。

综上所述,主要的区别在于地址空间的复制方式、父进程的行为、子进程的返回值以及父进程的阻塞方式。vfork 创建的子进程与父进程共享地址空间,并且父进程会被阻塞;fork 创建的子进程复制父进程的地址空间,父子进程可以同时执行。选择使用哪个系统调用取决于具体的需求和场景。一般而言,fork 是更常用的方式,而 vfork 则用于特定的情况,例如在子进程中立即执行 exec 函数。

总结

本篇文章讲解了vfork的具体操作和内部含义,并且将vfork和fork进行了对比。


http://lihuaxi.xjx100.cn/news/1274213.html

相关文章

Linux——进程地址空间,写时拷贝,进程独立性

Linux进程内存分布 验证地址空间排布 结论&#xff1a;堆区向地址增大的方向增长&#xff0c;栈区向地址减少的方向增长。局部变量通常保存在栈上&#xff0c;先定义的先入栈&#xff0c;地址是比较高的&#xff0c;后定义的则地址小。 static变量 作用域不变&#xff0c;生命…

Linux之tar安装

目录 Linux之tar安装 定义 工作过程 语法格式 参数及用法 使用源代码安装软件的优点 注意&#xff1a;源代码编译环境 操作流程 解包 —— tar 配置 —— ./configure 编译 —— make 安装 —— make install 案例 --- 安装Apache服务 1.获取安装包地址并下载 2…

word文档批量生成工具(附免费软件)(按Excel表格内容自动替换内容生成文档)

批量生成word文档是让人无比厌恶但有时又不得不做的事情。比如学校要给拟录取的学生发通知书&#xff0c;就可能需要批量生成一批只有“姓名”、“学院”和“专业”不同&#xff0c;其他内容都相同的word文档以供打印&#xff08;事实上直接生成pdf是更好的选择&#xff0c;这个…

Windows10host文件修改方法

1、首先打开“此电脑”&#xff0c;定位到&#xff1a; C:\Windows\System32\drivers\etc 2、使用鼠标右键单击“hosts”&#xff0c;弹出来的菜单中选择“属性” 3、弹出“文件属性”窗口后单击“上方的”安全“栏”。 选中“ALL APPLICATON PACKAGES”后单击“编辑” 4、同…

“破解求职之谜:应届生如何应对职场场景挑战?

今天&#xff0c;我想与你分享一个关于应届生面试的故事。这是一个真实且令人深思的故事&#xff0c;也是我个人在求职过程中的一次经历&#xff0c;这也是对尚未面试者的警醒对已面试者的勉励。 在暑期还未开始之前&#xff0c;我充满着憧憬和期待地投递了许多简历&#xff0c…

【瑞萨RA_FSP】WiFi——ESP8266模块通讯

文章目录 一、Wifi模块简介二、ESP8266功能介绍1. 通用输入/输出接口&#xff08;GPIO&#xff09;2. 使用UART与WIFI通讯3. ESP8266工作模式介绍 三、AT指令四、实验&#xff1a;STA模式测试1. 文件结构2. 宏定义函数3. ESP8266-STA功能函数4. 中断回调函数5. hal_entry入口函…

【深度学习笔记】神经网络概述

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。刚兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a;https://mo…

【MySQL】表的内外连接

目录 一、内连接&#xff08;表1 inner join 表2 on&#xff09; 1、显示SMITH的名字和部门名称 二、外连接 1、左外连接&#xff08;表名1 left join 表名2 on&#xff09; 1.1查询所有学生的成绩&#xff0c;如果这个学生没有成绩&#xff0c;也要将学生的个人信息显示出…