fork() vfork()

1.fork()

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

返回值:子进程返回0,父进程返回子进程id,fork失败返回-1.
没有一个函数使得一个进程可以获得其所有子进程的ID。
子进程只有一个父进程,可以通过函数getppid()获得父进程ID。

在这里插入图片描述
写时复制是说当父进程或者子进程试图对共享的区域进行修改时才将修改区域复制一份。

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

int glob = 6;
char buf[] = "a write to stdout\n";

int main(){
    int var;    //variable on the stack
    pid_t pid;

    var = 88;
    if(write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
        fprintf(stderr, "write error");
    printf("before fork\n");

    if((pid = fork()) < 0){
        fprintf(stderr, "fork error");
    }
    else if(pid == 0){
        glob++; //child
        var++;
    }
    else{
        sleep(2);//parent
    }

    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
    exit(0);
    return 0 ;
}

执行./8_1fork
输出:

a write to stdout
before fork
pid = 8646, glob = 7, var = 89
pid = 8645, glob = 6, var = 88

子进程将glob和var改变,说明子进程中的全局区与栈是和父进程独立的,不然在父进程再次执行的时候输出的glob应该是7.

如果执行:

./8_1fork > tmp
cat tmp

则输出:

a write to stdout
before fork
pid = 8762, glob = 7, var = 89
before fork
pid = 8761, glob = 6, var = 88

这里发现before fork 输出了两次,分别是子进程和父进程输出的,这是由于行缓冲与全缓冲的区别造成的,详见标准I/O缓冲:全缓冲、行缓冲、无缓冲 .

1、全缓冲 。全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。
2、行缓冲 。在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。
3、无缓冲 。无缓冲指的是标准IO库不对字符进行缓冲存储;注意,标准出错流stderr通常是无缓冲的。

其次介绍一下几个退出函数:
1、exit ()。调用exit函数之后,它首先会执行一系列的清理处理,包括调用执行各终止处理程序,关闭所有标准IO流等,然后进入内核。
2、_exit ()。与exit不同的是,它不进行清理工作而直接进入内核。此函数由POSIX.1说明,放在unistd.h里面。
3、_Exit ()。同样,它也不进行清理工作而直接进入内核。此函数跟exit一样由ISO C说明,放在stdlib.h里面。

在这里插入图片描述

  • 上例中将标准输出重定向到文件,所以是全缓冲,父进程在printf("before fork\n");后,before fork\n进入父进程的缓冲区;
  • 在fork后,子进程复制了父进程的缓冲区,所以子进程的缓冲区中也有before fork\n
  • 然后子进程输出printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
  • 子进程结束exit(0);将子进程缓冲区的内容清理,输出至文件;
  • 然后父进程在sleep(2)之后继续运行printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
  • 父进程结束,将父进程缓冲区中的内容输出至文件。
    fork用法

2.vfork()

在这里插入图片描述
vfork()产生的子进程在父进程的空间中运行,只有在调用exec或者exit之后才会复制。

// File Name: 8_2vfork.c
// Author: princeteng

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

int glob = 6;//global data

int main(){
    int var;    //variable on stack
    pid_t pid;

    var = 88;
    printf("before vfork\n");
    if((pid = vfork()) < 0){
        fprintf(stderr, "vfork err");
    }
    else if(pid == 0){
        glob++;     //child 
        var++;      //modify parent's variable
        _exit(0);   //child terminates
    }

    //parent continues
    printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
    return 0 ;
}

输出:

before vfork
pid = 9475, glob = 7, var = 89

可以看出子进程修改了父进程中的全局变量以及栈中的变量。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值