小阳同学嵌入式学习日记-创建进程中的fork( )和vfork( )

目录

一、fork( )

二、vfork( ) 

三、 fork( )和vfork( )的区别      

 四、 fork( )和vfork( )的使用时机


一、fork( )

   fork()是一个系统调用,用于创建一个新的进程,新进程称为子进程,而调用fork()的进程称为父进程。在调用fork()之后,操作系统会复制父进程的所有资源(包括内存、文件描述符等),然后将复制的资源分配给子进程。

         具体来说,fork()函数的原型为:

#include <unistd.h>

pid_t fork(void);
  • 返回值:在父进程中,fork()返回新创建的子进程的进程ID(PID),在子进程中,返回0。如果出错,返回-1
  • 参数:fork()函数不接受任何参数。

        下面是一个简单的例子,演示了fork()函数的基本用法: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;

    pid = fork();

    if (pid == -1) {
        perror("fork error");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程执行的代码
        printf("This is the child process, PID: %d\n", getpid());
        exit(EXIT_SUCCESS); // 子进程退出
    } else {
        // 父进程执行的代码
        printf("This is the parent process, child PID: %d\n", pid);
        exit(EXIT_SUCCESS); // 父进程退出
    }

    return 0;
}

         在这个例子中,调用fork()创建了一个子进程。在子进程中,fork()返回0,因此打印了子进程的PID,并且子进程执行了exit()函数退出。在父进程中,fork()返回子进程的PID,因此打印了子进程的PID,并且父进程也执行了exit()函数退出。

        运行结果如下 :

This is the parent process, child PID: [子进程的PID]
This is the child process, PID: 0

        其中,[子进程的PID]会被实际的子进程的PID值所替代。这是因为在父进程中,fork()返回的是子进程的PID,而在子进程中,fork()返回0。因此,父进程会打印出子进程的PID,而子进程会打印出自己的PID0

二、vfork( ) 

        vfork()是另一个创建新进程的系统调用,但与fork()不同,vfork()通常用于创建一个新进程,而不会复制父进程的地址空间。它与fork()类似,但有一些重要的区别和限制。

         vfork()函数的原型如下:

#include <unistd.h>

pid_t vfork(void);
  • 返回值:在父进程中,vfork()返回新创建的子进程的进程ID(PID),在子进程中,返回0。如果出错,返回-1
  • 参数:vfork()函数不接受任何参数。

         以下是一个简单的示例,演示了vfork()函数的基本用法:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    pid_t pid;

    pid = vfork();

    if (pid == -1) {
        perror("vfork error");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程执行的代码
        printf("This is the child process, PID: %d\n", getpid());
        _exit(EXIT_SUCCESS); // 子进程调用_exit()函数退出
    } else {
        // 父进程执行的代码
        printf("This is the parent process, child PID: %d\n", pid);
        // 父进程继续执行
    }

    return 0;
}

         运行此程序会得到与fork()类似的结果,但使用vfork()时需要特别注意子进程在调用exec()exit()之前不会对父进程的内存空间产生影响。

        运行结果如下:

This is the child process, PID: 12345
This is the parent process, child PID: 12345

        其中,12345是实际子进程的PID值。这是因为在父进程中,vfork()返回的是子进程的PID,而在子进程中,vfork()返回0。因此,父进程会打印出子进程的PID,而子进程会打印出自己的PID

三、 fork( )和vfork( )的区别      

         fork()vfork()都是用于创建新进程的系统调用,但它们之间有一些重要的区别:

地址空间:

  • fork()会创建一个新的子进程,并复制父进程的地址空间到子进程中。子进程会有自己独立的地址空间,对地址空间的修改不会影响到父进程。
  • vfork()创建的子进程会共享父进程的地址空间。子进程在调用exec()exit()之前,必须立即执行一个新的程序或者退出,以避免对父进程地址空间的修改。

性能:

  • vfork()fork()更高效,因为它不需要复制整个地址空间。vfork()只是在父进程的地址空间上创建一个新的进程,直到子进程调用exec()exit()之后才会复制地址空间。这使得vfork()更适合于创建子进程并立即执行一个新程序的情况。

父子进程的行为:

  • fork()中,父进程和子进程的执行是独立的,它们各自拥有自己的地址空间和资源。子进程可以修改它自己的地址空间,而不会影响父进程。
  • vfork()中,子进程会共享父进程的地址空间,因此在调用exec()exit()之前,子进程不能修改任何共享的内存数据。此外,在子进程调用exec()exit()之前,父进程会阻塞,直到子进程调用这些函数。

返回值:

  • fork()在父进程中返回新创建的子进程的PID,在子进程中返回0。
  • vfork()在父进程中返回新创建的子进程的PID,在子进程中也返回0。

 四、 fork( )和vfork( )的使用时机

         fork()vfork()的使用时机取决于你的需求和情况。以下是一些适合使用每种方法的情况:

适合使用 fork() 的情况:

  • 当父进程和子进程需要在执行期间共享一些数据,但是又需要在某些情况下独立运行时,可以使用fork()。因为fork()会复制父进程的地址空间,所以父进程和子进程各自拥有独立的内存空间,可以互不影响地进行修改。
  • 当需要创建子进程执行一些并行任务,并且这些任务不会立即执行新的程序或者退出时,可以使用fork()。因为fork()创建的子进程在创建后会立即复制父进程的地址空间,所以可以在创建后独立运行。

适合使用 vfork() 的情况:

  • 当子进程需要立即执行一个新的程序,而且不需要对父进程的地址空间进行修改时,可以使用vfork()。因为vfork()会共享父进程的地址空间,所以子进程可以直接在父进程的地址空间中执行新的程序,而不需要等到复制地址空间后再执行。
  • 当需要创建子进程来执行一个新的程序,但是不希望额外的内存复制开销时,可以使用vfork()。因为vfork()不会立即复制父进程的地址空间,所以可以减少额外的内存开销,提高性能。

        总的来说,如果需要创建一个新的子进程来执行一个新的程序,并且这个新程序会立即执行,那么vfork()是一个更好的选择。但是如果子进程需要修改父进程的地址空间,或者需要在创建后独立运行一段时间,那么fork()可能更适合。

 

做大做强,再创辉煌! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值