2.创建进程函数fork的使用,与vfork的区别

目录

1、fork函数简介

2、代码实例研究fork函数之后父子进程的关系

3、fork返回值具体情况

4、vfork函数也可以创建进程,但是与fork不同


1、fork函数简介

使用 fork 函数创建一个进程

pid_t  fork(void);

fork 函数调用成功,返回两次

返回值为0,代表当前进程是子进程

返回值是非负数,代表当前进程为父进程

调用失败,返回 -1

2、代码实例研究fork函数之后父子进程的关系

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

int main()
{
        pid_t pid;
        pid_t pid2;

        pid = getpid();
        printf("before fork: pid = %d \n",pid);

        fork();

        pid2 = getpid();
        printf("after fork: pid = %d \n",pid2);

        if(pid == pid2){
                printf("this id father print , pid = %d \n",getpid());
        }
        else{
                printf("this id child print , pid = %d \n",getpid());
        }

        return 0;
}

 结论:

一个函数在没有创建fork函数之前都是父进程在走

一旦到了fork进程之后就会出现两个进程(父进程和子进程)

fork之后具体哪个进程进程在跑不知道,由系统调度决定。但可以确定的是,父子进程都会从fork之后,走代码一遍,所以打印了两次 after fork

直到在选择语句的时候,根据条件,父子进程才根据条件各自跑

 3、fork返回值具体情况

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

int main()
{
        pid_t pid;
        pid_t pid2;
        pid_t retpid;


        pid = getpid();
        printf("before fork: pid = %d \n",pid);

        retpid = fork();

        pid2 = getpid();
        printf("after fork: pid = %d \n",pid2);

        if(pid == pid2){
                printf("this id father print , retpid = %d ,pid = %d\n",retpid,getpid());
        }
        else{
                printf("this id child print ,retpid = %d , pid = %d \n",retpid,getpid());
        }

        return 0;
}

 

 结论:

fork的返回值,大于0 的时候,代表是父进程。此时的返回值,刚好是子进程的pid号

而fork的返回值,等于0 的时候,代表的是子进程。此时的子进程的pid号其实是复制了fork大于0 的返回值。

其实意思就是:两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的ID

有点拗口,具体看代码😄吧。

4、vfork函数也可以创建进程,但是与fork不同

关键区别一:

vfork直接使用父进程的存储空间,不拷贝

关键区别二:

vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行

 

通过代码验证区别,既然vfork是直接使用父进程的储存空间,那么子进程修改的数据,父进程那边也是被修改了。

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

int main()
{
        pid_t pid;

        int cnt = 0;

        pid = vfork();

        if(pid > 0){
                while(1){
                        printf("this is father print: pid = %d \n",getpid());
                        printf("cnt = %d\n",cnt);
                        sleep(1);
                }
        }
        else if(pid == 0){
                while(1){
                        printf("this is child print: pid = %d \n",getpid());
                        cnt++;
                        if(cnt == 3){
                                exit(0);
                                //break;  不能使用,原因请看下面4.1点
                        }
                        sleep(1);
                }
        }

        return 0;
}

结论:

4.1、如果子进程不是按 exit 这个规则退出,换了其他退出,比如break,则父进程的打印的 cnt 不是 3,是一串数字

4.2、vfork是直接使用父进程的储存空间,那么子进程修改的数据,父进程那边也是被修改了。从代码结果可以看出来,子进程将cnt 改为了3,父进程打印 cnt 就为 3。

而 fork 则是,旧的说法是拷贝了一份空间(新的说法是共享,用的时候就直接调用),父子进程各不影响,各行各事。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
`fork`和`vfork`是在Unix-like操作系统中创建进程的系统调用函数,它们有一些区别。 1. 创建方式:`fork`函数创建一个与父进程几乎完全相同的子进程,包括虚拟地址空间、文件描述符、环境变量等。而`vfork`函数创建的子进程则会共享父进程的虚拟地址空间。 2. 执行顺序:在`fork`函数中,父进程和子进程的执行顺序是不确定的,取决于操作系统的调度。而在`vfork`函数中,子进程会先于父进程执行,在子进程调用`exec`或者`exit`之前,父进程会一直阻塞。 3. 父子进程间的关系:在`fork`函数中,父子进程之间是完全独立的,对彼此的操作不会相互影响。而在`vfork`函数中,子进程与父进程共享虚拟地址空间,因此对共享数据的修改可能会影响到父进程。 4. 资源消耗:由于`vfork`函数创建的子进程共享父进程的虚拟地址空间,因此在子进程调用`exec`或者`exit`之前,它不能改变父进程的虚拟地址空间,也不能创建新的进程,这可以减少资源消耗和内存拷贝的开销。 总之,`fork`函数适用于创建独立的子进程,而`vfork`函数适用于创建共享虚拟地址空间的子进程,特别是在需要快速创建进程且不涉及虚拟地址空间修改的情况下。但是现代操作系统中,由于虚拟内存管理的改进,`vfork`函数使用已经不太常见,一般推荐使用`fork`函数创建进程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枕上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值