zoukankan      html  css  js  c++  java
  • Linux下Fork与Exec使用

    Linux下进程的结构

      Linux下一个进程在内存里有三部分的数据,就是"代码段"、"堆栈段"和"数据段"。其实学过汇编语言的人一定知道,一般的CPU都有上述三种段寄存器,以方便操作系统的运行。这三个部分也是构成一个完整的执行序列的必要的部分。

      "代码段",顾名思义,就是存放了程序代码的数据,假如机器中有数个进程运行相同的一个程序,那么它们就可以使用相同的代码段。

      "堆栈段"存放的就是子程序的返回地址、子程序的参数以及程序的局部变量

      而数据段则存放程序的全局变量,常数以及动态数据分配的数据空间(比如用malloc之类的函数取得的空间)。

    Linux下的进程控制

    在传统的Unix环境下,有两个基本的操作用于创建和修改进程:函数fork( )用来创建一个新的进程,该进程几乎是当前进程的一个完全拷贝;函数族exec( )用来启动另外的进程以取代当前运行的进程。

      fork()

      fork在英文中是"分叉"的意思。为什么取这个名字呢?因为一个进程在运行中,如果使用了fork,就产生了另一个进程,于是进程就"分叉"了,所以这个名字取得很形象。

      调用这个fork函数时发生了什么呢?fork函数启动一个新的进程,这个进程几乎是当前进程的一个拷贝子进程和父进程使用相同的代码段子进程复制父进程的堆栈段和数据段。个人理解,还拷贝了环境变量。这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,也就是说,它们之间不再共享任何数据了。它们再要交互信息时,只有通过进程间通信来实现。

      也就是说,fork出的子进程的一切都来自父进程,包括代码、数据、堆栈、打开的文件等,就连代码的执行位置(状态)都是一样的。

       exec( )函数族

      一个进程一旦调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,并重新加载配置文件。唯一留下的,就是进程号,个人理解,还留下了拷贝自父进程环境变量和重新加载的配置文件中的内容(环境变量,函数等等)

    我们平时使用shell命令时,产生的子进程方式大体有以下两种

    第一种只使用 fork() 函数,子进程几乎是当前进程的一个拷贝,父进程中的函数、全局变量、别名以及环境变量在子进程中仍然有效。不会重新加载配置文件

      注意:子进程只是父进程的拷贝,两者并不共享,所以在子进程中改变了某个全局变量或者环境变量,不会反应到父进程中,父进程中该变量的值保持原样。同样,在子进程被创建后,在改变父进程中变量的值,也不会反应到子进程中。

     

    第二种使用 fork() 后,又使用了 exec() 函数。这样新建子进程只留下了进程ID和环境变量,及重新加载的配置文件。其余的全局变量,别名等就不存在了。相当于exce对子进程进行了格式化一样

    以新进程的方式运行脚本文件,比如bash ./test.shchmod +x ./test.sh; ./test.sh,或者在当前 Shell 中使用 bash 命令启动新的 Shell,它们都属于第二种创建子进程的方式,所以子进程除了能继承父进程的环境变量外,基本上也不能使用父进程的什么东西了,比如,父进程的全局变量、局部变量、文件描述符、别名等在子进程中都无效。

    但是,组命令、命令替换、管道这几种语法都使用第一种方式创建进程,所以子进程可以使用父进程的一切,包括全局变量、局部变量、别名等。

    为了方便两者的区别,我们称第一种为子shell,第二种为子进程。

  • 相关阅读:
    Xmind8 Pro 破解教程(序列号|破解文件)
    火狐真机绕过selenium检测
    ubuntu20.04 更新国内源,亲测有效
    superset 安装记录(win10)
    anaconda 环境切换
    创建型模式-工厂方法 (python实现 与 java实现)
    python 使用抽象基类,实现(类似java)接口(继承抽象类的方法来实现具体类)
    python 基于元类的单例
    希尔排序(python实现)
    内存操作的几个函数
  • 原文地址:https://www.cnblogs.com/gaoBlog/p/12272556.html
Copyright © 2011-2022 走看看