linux fork函数与vfork函数

man vfork:

NAME
vfork - create a child process and block parent

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

pid_t vfork(void);

DESCRIPTION
Standard description
(From POSIX.1) The vfork() function has the same effect as fork(2), except that the behav‐
ior is undefined if the process created by vfork() either modifies any data other than a
variable of type pid_t used to store the return value from vfork(), or returns from the
function in which vfork() was called, or calls any other function before successfully
calling _exit(2) or one of the exec(3) family of functions.

Linux description
vfork(), just like fork(2), creates a child process of the calling process. For details
and return value and errors, see fork(2).

vfork() is a special case of clone(2). It is used to create new processes without copying
the page tables of the parent process. It may be useful in performance-sensitive applica‐
tions where a child is created which then immediately issues an execve(2).

vfork() differs from fork(2) in that the calling thread is suspended until the child ter‐
minates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal
signal), or it makes a call to execve(2). Until that point, the child shares all memory
with its parent, including the stack. The child must not return from the current function
or call exit(3), but may call _exit(2).

As with fork(2), the child process created by vfork() inherits copies of various of the
caller‘s process attributes (e.g., file descriptors, signal dispositions, and current
working directory); the vfork() call differs only in the treatment of the virtual address
space, as described above.

Signals sent to the parent arrive after the child releases the parent‘s memory (i.e.,
after the child terminates or calls execve(2)).

创建一个新进程的方法只有由某个已存在的进程调用fork()或vfork(),当然某些进程如init等是作为系统启动的一部风而被内核创建的。

一、fork
1. 调用方法
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);
正确返回:在父进程中返回子进程的进程号,在子进程中返回0
错误返回:-1

子进程是父进程的一个拷贝。即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存;而对于只读的代码段,通常使用共享内存的方式访问。fork返回后,子进程和父进程都从调用fork函数返回处开始执行。
     父进程与子进程的不同之处在于:fork的返回值不同——父进程中的返回值为子进程的进程号,而子进程为0
2. fork函数调用的用途
⑴ 一个进程希望复制自身,从而父子进程能同时执行不同段的代码。
⑵ 进程想执行另外一个程序

二、vfork
1. 调用方法
与fork函数完全相同
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);
正确返回:在父进程中返回子进程的进程号,在子进程中返回0
错误返回:-1

2. vfork函数调用的用途
       用vfork创建的进程主要目的是用exec函数执行另外的程序,与fork的第二个用途相同

三、fork与vfork的区别
1. fork要拷贝父进程的数据段;而vfork则不需要完全拷贝父进程的数据段,在子进程没有调用exec和exit之前,子进程与父进程共享数据段
2. fork不对父子进程的执行次序进行任何限制;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制

四、结束子进程
     结束子进程不用exit(0),而使用_exit(0)。这是因为_exit(0)在结束进程时,不对标准I/O流进行任何操作。而exit(0)则会关闭进程的所有标准I/O流。

由于子进程与父进程的运行是无关的,父进程可先于子进程运行,子进程也可先于父进程运行,所以下段程序可以有两种运行结果。

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int global=4;
int main()
{
    pid_t pid;
    int vari=5;
    printf("before fork\n");
    if((pid=fork())==0)
    {
        global++;
        vari--;
        printf("child changed\n");
    }
    else
        printf("parent did nog changed\n");

    printf("global=%d,vari=%d\n",global,vari);
    }

[email protected]:~/ms/linux/unp/unpMy/tcpcliserv# ./fork1
before fork
parent did nog changed
global=4,vari=5
[email protected]:~/ms/linux/unp/unpMy/tcpcliserv# child changed
global=5,vari=4

[email protected] src]# ./a.out
before fork
Child changed
globa = 5 vari = 4
Parent did not changde
globa = 4 vari = 5

vfork创建新进程的主要目的在于用exec函数执行另外的程序,实际上,在没调用exec或exit之前子进程的运行中是与父进程共享数据段的。在vfork调用中,子进程先运行,父进程挂起,直到子进程调用exec或exit,在这以后,父子进程的执行顺序不再有限制。

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int global=4;
int main()
{
    pid_t pid;
    int vari=5;
    printf("before fork\n");
    if((pid=vfork())==0)
    {
        global++;
        vari--;
        printf("child changed\n");
        _exit(0);
    }
    else
        printf("parent did nog changed\n");

    printf("global=%d,vari=%d\n",global,vari);
    exit(0);
 }

[email protected]:~/ms/linux/unp/unpMy/tcpcliserv# ./fork2
before fork
child changed
parent did nog changed
global=5,vari=4。

(从这里可以看出共享了数据段的。)

参考:http://blog.csdn.net/lingdxuyan/article/details/4996471

linux c 下exit(0);与_exit(0);的区别

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
if((pid=fork())==-1)
    {
    printf("error");
    }
else if(pid==0)
{
printf("ok\n");
exit(0);
}
else
{
printf("parent process,output begin\n");
printf("hello word");
_exit(0);
}
}

调试后你会发现没有

hello word

exit是退出去先把内存中的数据输出到文件中,而_exit 这个直接退出,消除内存中的数据;

printf是标准行输出,遇到“\n”或者是写入的内存满了才会标准输出;

我们可以尝试在hello word 中加入很多i,假设输入2000个吧(关于行输出自行google),再次调试发现,会有 hello 等字符,这就是溢出了。

回到前面,为什么开始没有hello,虽然hello word 在_exit前,但是你查看汇编会发现,他只是讲数据存在内存中。没有讲数据真正输出。当我们把_exit去掉 hello word就能显示了。为什么呢?这个就是编译器自己加的了。

从图中可以看出,_exit 函数的作用是:直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _exit() 函数的最大区别在于exit()函数在调用exit  系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是图中的“清理I/O缓冲”。

所需头文件: exit:   #include<stdlib.h>

_exit: #include<unistd.h>

函数原型:exit:  void exit(int  status)

_exit:  void  _exit(int  status)

函数传入值:status 是一个整型的参数,可以利用这个参数传递进程结束时的状态。一般来说,0表示正常结束;其他的数值表示出现了错误,进程非正常结束。在实际编程时,父进程可以利用wait 系统调用接收子进程的返回值,从而针对不同的情况进行不同的处理

参考:http://blog.csdn.net/lwj103862095/article/details/8640037

时间: 2024-10-14 18:09:25

linux fork函数与vfork函数的相关文章

Linux学习之“vfork函数”

为什么使用vfork()? 希望父子进程执行不同的代码.例如: 网络服务程序中,父进程等待客户端的服务请求,当请求达到时,父进程调用fork,使子进程处理该次请求,而父进程继续等待下一个服务请求到达. vfork与fork的函数原型相同,用于创建新进程,而该新进程的目的是exec一个新程序(执行一个可执行的文件). 由于新程序将有自己的地址空间,因此vfork函数并不将父进程的地址空间完全复制到子进程中. 注意以下两点: 1.子进程在调用exec或exit之前,在父进程的地址空间中运行. 2.v

Linux系统编程——vfork() 函数详解

所需头文件: #include <sys/types.h> #include <unistd.h> pid_t vfork(void); 功能: vfork() 函数和 fork() 函数(fork()如何使用,请点此链接)一样都是在已有的进程中创建一个新的进程,但它们创建的子进程是有区别的. 参数: 无 返回值: 成功:子进程中返回 0,父进程中返回子进程 ID.pid_t,为无符号整型. 失败:返回 -1. fork() 与 vfock() 都是创建一个进程,那它们有什么区别呢

4进程原语:fork()函数,getpid()函数和getppid()函数,getuid()函数,getgid()函数,vfork()

 1fork()函数 子进程复制父进程的0到3g空间和父进程内核中的PCB,但id号不同.fork调用一次返回两次,有以下特点: A:父进程中返回子进程ID B:子进程中返回0 C:读时共享,写时复制 2fork()依赖的头文件 #include <unistd.h> 3fork()函数说明: pid_tfork(void); 通过该函数创建一个子进程 4案例说明: 总结: A因为读时共享和写时复制,子进程会复制父进程的代码,但是从fork下开始执行.但是,当在fork前定义父子进程都用到

linux编程中接收主函数返回值以及错误码提示

程序A创建子进程,并调用进程B,根据不调用的不同情况,最后显示结果不同. #include <stdio.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <errno.h> int main() { pid_t pid, rpid; int stat; if ((pid = fork()) < 0) { perror("for

(疑问)进程控制(五)---vfork 函数

vfork 函数和 fork 函数类似,也可以用来创建子进程,但是和 fork 创建的子进程有以下几点不同: fork 创建的子进程和父进程之间的执行顺序是不确定的,取决的调度算法的实现.而 vfork 函数创建的子进程 一定是先于父进程执行的,父进程会阻塞到当子进程中调用了 exec 或者 exit函数后,才会被唤醒开始执行. fork 创建的子进程和父进程是各自独立的地址空间,而 vfork 创建出的子进程在子进程调用 exec 或者 exit函数之前都是和父进程共享地址空间的. vfork

curses不是linux里默认的C函数库

今天在调试一个贪吃蛇程序时,出现如下错误: [[email protected] c++]$ g++ snack.cpp -o snack/tmp/ccCuZ3Jm.o:在函数‘playgame(int, int)’中:snack.cpp:(.text+0xce):对‘erase’未定义的引用snack.cpp:(.text+0xed):对‘mvprintw’未定义的引用snack.cpp:(.text+0x140):对‘mvprintw’未定义的引用snack.cpp:(.text+0x166

linux 下getch()函数实现

//调用 //char *ptr = (char *)malloc(sizeof(char) * 128); //ptr = get_passwd(); //printf("\n"); #include<stdio.h> #include<termios.h> #include<unistd.h> #include<assert.h> #include<string.h> #include <stdlib.h> i

linux下c++filter查看函数修饰名

c++函数在linux系统下编译之后会变成类似下面的样子: _ZNK4Json5ValueixEPKc 在linux命令行使用c++filter: [email protected]:~ $ c++filt _ZNK4Json5ValueixEPKc Json::Value::operator[](char const*) const 这样就得到函数的原始名称 如果没有安装c++filter, 可以自行搜索.linux下c++filter查看函数修饰名,布布扣,bubuko.com

Linux系统调用--getrlimit()与setrlimit()函数详解

http://www.cnblogs.com/niocai/archive/2012/04/01/2428128.html 功能描述:获取或设定资源使用限制.每种资源都有相关的软硬限制,软限制是内核强加给相应资源的限制值,硬限制是软限制的最大值.非授权调 用进程只可以将其软限制指定为0~硬限制范围中的某个值,同时能不可逆转地降低其硬限制.授权进程可以任意改变其软硬限制.RLIM_INFINITY的 值表示不对资源限制. 用法: #include <sys/resource.h>int getr