Linux C:fork函数和vfork函数

 fork函数用来创建子进程。

/* Clone the calling process, creating an exact copy.
   Return -1 for errors, 0 to the new process,
   and the process ID of the new process to the old process.  */
extern __pid_t fork (void) __THROWNL;

 上图是Linux C库里面的unistd.h 中fork 函数的原型和相关注释。用我比较垃圾的英文水平进行一下翻译:将调用此函数的进程进行克隆,创建一个新的副本。返回-1表示error,0表示进入到子进程(new process),一个正整数表示返回子进程的pid给父进程(old process)。

fork函数早期是把父进程的所有存储空间全部复制给子进程,不过如今都使用写时拷贝,就是只在进程使用到的时候才拷贝某些需要的内容。如果父进程中有某些变量,在子进程中修改了,父进程中的值是不会变的。

使用场景:常常用于服务器(比如sokect)中服务器(server)接入客户端(client),主进程创建子进程给新的客户端运行接下来的程序,然后主进程继续检测是否有新的客户端接入。

 demo.c:

#include 
#include 
#include 

int main()
{
    pid_t pid1;
    pid_t pid2;
    pid1 = getpid();   
    printf("原进程:%d\n", pid1);
    pid2 = fork();
    if(pid2 == -1)
    {
        printf("Fork error.\n");
    }
    else if (pid2 == 0)
    {
        printf("-----------------------------\n");
        printf("这是子进程打印。\n");
        printf("子进程:%d\n",getpid());
        printf("fork函数返回:%d\n",pid2);
        printf("-----------------------------\n");
    }
    else
    {
        printf("-----------------------------\n");
        printf("这是父进程打印。\n");
        printf("父进程:%d\n",getpid());
        printf("fork函数返回:%d\n",pid2);
        printf("-----------------------------\n");
    }

    return 0;
}

Linux C:fork函数和vfork函数_第1张图片

 上面的demo可以看到fork函数的返回逻辑,创造一个新进程,在原进程中返回新进程的pid,在新进程中返回0。

再来介绍一下vfork函数,和fork函数比较相似:

/* Clone the calling process, but without copying the whole address space.
   The calling process is suspended until the new process exits or is
   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
   and the process ID of the new process to the old process.  */
extern __pid_t vfork (void) __THROW;

浅翻译一下:克隆调用该函数的进程,但是不复制整个地址区间。调用函数的进程会被暂停直到新进程退出或者被调用的execve函数替换。返回-1表示失败,0表示进入新的进程,一个pid_t的整数表示从新进程退出回到原进程,这个整数就是被开辟的新进程。

看完这个定义我就有了一个疑惑:既然复制地址区间,意思应该就是在父进程的内存空间上进行操作,那么子进程会改变父进程的变量等数据呢?写个代码验证一哈。

demo3.c

#include 
#include 
#include 

int main()
{
    int num = 0;
    pid_t pid1;
    pid_t pid2;

    printf("The original process: %d\n", pid1);
    pid2 = vfork();
    if(pid2 = -1)
    {
        printf("vfork error.\n");
    }
    else if (pid2 = 0)
    {
        printf("------------------------------\n");
        printf("This is child process: %d\n",getpid());
        printf("vfork return: %d\n", pid2);
        num++;
        printf("num in child process: %d\n", num);
        printf("------------------------------\n");
    }
    else
    {
        printf("------------------------------\n");
        printf("This is parent process: %d\n",getpid());
        printf("vfork return: %s\n", pid2);
        num++;
        printf("num in parent process: %d\n", num);
        printf("------------------------------\n");
    }

    return 0;
}

验证如下:会改变父进程中的数值。

Linux C:fork函数和vfork函数_第2张图片

 但是发现运行到后面段错误了,可能是子进程的返回不对,我再试试

 修改方法就是在子进程中加上exit()函数就可以了。

 21         printf("------------------------------\n");
 22         printf("This is child process: %d\n",getpid());
 23         printf("vfork return: %d\n", pid2);
 24         num++;
 25         printf("num in child process: %d\n", num);
 26         printf("------------------------------\n");
 27         exit(pid2);

可以继续验证子进程总是在父进程前运行,只要加上while循环验证就行了。

 

你可能感兴趣的:(Linux学习,linux,c语言)