基础文章3:进程基础之fork函数

本文详细介绍了Linux中的fork函数,它是创建进程的唯一方法。通过fork,系统为新进程分配资源并复制父进程的大部分状态,使得父子进程共享代码空间但拥有独立的数据空间。fork成功后,两个进程执行顺序不确定,且根据返回值执行不同代码,实现各自功能。重点在于共享程序空间和数据空间的独立性以及父子进程执行顺序的不确定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.序
1.基础内容介绍
     1)进程的组成:  
     2)fork函数调用后,系统所做工作:
2.函数详细介绍
     1)函数原型
     2)作用
     3)描述
3.总结:
0.序
     fork函数是Linux中创建进程的函数,也是唯一一个创建进程的函数。因此学好fork函数时基础中的基础。0.序
1.基础内容介绍
      1)进程的概述:
       进程简单的说就是一个程序一次执行的过程,它是一个动态的概念。按照教科书上的定义,进程是程序执行的实例,是linux的基本调度单位。 
     对于程序员来说,最重要的就是要区分进程和程序的区别,程序是指一段完成功能的代码,或者说是一个工具,它是一个静态的概念,而进程,它是动态的,比如,linux的vi编辑器,它就是一段在linux下用于文本编辑的工具,那么它是一个程序,而我们在linux终端中,可以分别开启两个vi编辑器的进程。一旦提到进程,我们的脑子里就应该产生——程序从代码的第一句动态的执行到最后一句这样的一个思路。 
一个进程由如下元素组成: 
1.> 进程的当前上下文,即进程的当前执行状态; 
2.> 进程的当前执行目录 
3.> 进程访问的文件和目录 
4.> 进程的访问权限,比如它的文件模式和所有权 
          5.> 内存和其他分配给进程的系统资源 
  
        fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
       2)fork函数调用后,系统所做工作:
               一个进程调用fork()函数后,
                    (1)系统先给新的进程分配资源,例如存储数据和代码的空间。
                    (2)然后把原来的进程的所有值都复制到新的新进程中,只有少数值(这部分少数值在man fork中有详细说明)与原来的进程的值不同。相当于克隆了一个自己。
2.函数详细介绍
      1)函数原型
SYNOPSIS
       #include <unistd.h>

       pid_t fork(void);
      2)作用
          创建一个子进程。是进程不是线程。
      3)描述
         ( 1)通过复制调用进程(即父进程)来创建一个子进程。
               所谓复制:子进程会与父进程共享代码空间,但是其数据空间是相互独立的。子进程的数据空间是从父进程完成拷贝下来的,刚创建完子进程时里面的取值都与父进程一样,但是由于其数据空间是相互独立的,因此数据空间中的数据会随着子进程的进行,而发生改变,从而与父进程不再一样。
               fork函数的作用是在其进程中创建一个新的进程,这个新的进程不会取代原来的进程,而是以当前进程的一个子进程而存在的。这个子进程会有一个新的进程标识符pid。并且这个子进程会继承父进程的一切! 
           什么是叫继承父进程的一切呢?就是克隆父进程的所有,包括父进程的 代码父进程正在执行的状态父进程的工作目录父进程的所有资源等等,一切的一切,fork系统调用会全部的复制下来。
        
               举例:
/*可以用于说明父子进程间数据空间是相互独立的*/
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>


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


int main()
{
    int var;
    pid_t pid;

    var = 88;


    fprintf(stderr, "%s", buf);

    printf("before fork\n");

    if(( pid = fork() ) < 0 )
    {
        fprintf(stderr, "fork error\n");
    }
    else if(pid == 0)
    {

        glob++;
        var++;
        printf("child process\n");
printf("pid = %d getpid = %d, father pid = %d, glob = %d, var = %d\n",pid, getpid(), getppid(), glob, var);
        exit(0);
    }
    else
    {
        var += 20;
        glob += 20;
        printf("begin into father process\n");
        sleep(2);
        printf("father process\n");
        printf("pid = %d, father pid = %d, glob = %d, var = %d\n", getpid(), getppid(), glob, var);
    }


    return 0;
}
运行结果
a write to stdout/nbefore fork
begin into father process
child process
pid = 0 getpid = 4039, father pid = 4038, glob = 7, var = 89
father process
pid = 4038, father pid = 3317, glob = 26, var = 108

           (2)创建新进程成功后,系统中出现两个基本完全相同的进程, 这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略
           (3)当创建完毕后,可以想象,两个进程一直同时进行,而且步调一致,在fork之后,他们分别做不同的工作,也就是分岔了,这就是为什么叫fork的原因. fork执行完毕后,出现两个进程。
                    根据1)中所述,父子进程共享代码空间,因此二者代码相同。又根据1)中所述,二者数据空间相互独立,根据fork在父进程与子进程的返回值的不同,父子进程将会执行不同的代码段,从而实现不同的功能。

          4)特别重要的一点:fork是把进程当前的情况拷贝一份。切记是当前的情况拷贝一份,而不是代码中原始数据的拷贝。这一点通过下面的代码最能体现。
#include <unistd.h> 
#include <stdio.h> 
int main(void) 

   int i=0; 
   printf("i son/pa ppid pid  fpid\n"); 
   //ppid指当前进程的父进程pid 
   //pid指当前进程的pid, 
   //fpid指fork返回给当前进程的值 
   for(i=0;i<2;i++){ 
       pid_t fpid=fork(); 
       if(fpid==0) 
           printf("%d child  %4d %4d %4d\n",i,getppid(),getpid(),fpid); 
       else 
           printf("%d parent %4d %4d %4d\n",i,getppid(),getpid(),fpid); 
   } 
   return 0; 
}  

  其运行结果
 
i son/pa ppid pid  fpid
0 parent 3317 4096 4097
1 parent 3317 4096 4098
 1 child     1 4098    0
0 child     1 4097    0
1 parent    1 4097 4099
1 child     1 4099    0

        之所以运行结果的顺序与http://blog.youkuaiyun.com/jason314/article/details/5640969 文中不同,我想就是因为 这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。    
3.总结:
          fork()函数通过系统调用创建了一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事(因为共享代码空间),但是由于fork函数的返回值的不同,会产生不同的功能(fork返回值不同,会去执行不同代码段,又因为数据空间是相互独立,故数据互不影响)。
          重点记住两点:1)共享程序空间,数据空间相互独立
                                   2)父子进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。

http://coolshell.cn/articles/7965.html 一个fork的面试题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值