exec函数族

fork之后open   父子进程各自有各自打开的文件信息,先写的可能被后写的覆盖

fork之前open   父子进程影响同一个offset值

exec函数族----启动运行一个新的程序

exec族
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),
子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的
用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建
新进程,所以调用exec前后该进程的id并未改变

1.execl函数

函数作用:加载一个进程, 通过 路径+程序名 来加载。
头文件:#include <unistd.h>
函数原型:int execl(const char *path, const char *arg, …);
函数参数:
  path:绝对路径+程序名—(exec函数族的这个参数是可以加载自己写的程序的)
  arg1:命令的第一个单词
  …这后面的依次跟着的命令行的第二个、第三个等单词(若有的话)…以NULL结尾
返回值:成功:无返回;失败:-1
例如:
  execl(“/bin/ls”, “ls”, “-l”, “-F”, NULL); 使用参数1给出的绝对路径搜索。

2,execlp函数

函数作用:加载一个进程,借助PATH环境变量
头文件:#include <unistd.h>
函数原型:int execlp(const char *file, const char *arg1, …);
函数参数:
  file:要加载的程序的名字
  arg1:命令的第一个单词
  …这后面的依次跟着的命令行的第二个、第三个等单词(若有的话)…以NULL结尾
返回值:成功:无返回   失败:-1
注意:
  该函数需要配合PATH环境变量来使用,当PATH中所有目录搜索后没有参数1则出错返回。
  该函数通常用来调用系统程序。如:ls、date、cp、cat等命令。
例如:
execlp(“ls”, “ls”, “-l”, “-F”, NULL); 使用程序名在PATH中搜索。

3.execle函数

函数作用:
  加载一个进程, 通过 路径+程序名 来加载。
头文件:
  #include <unistd.h>
函数原型:
  int execle(const char *path, const char *arg, …);
函数参数:
  path:绝对路径+程序名
  arg1:命令的第一个单词
  …这后面的依次跟着的命令行的第二个、第三个等单词(若有的话)…以NULL结尾
返回值:
  成功:无返回
  失败:-1

4,execv函数

函数作用:
  加载一个进程, 通过 路径+程序名 来加载。
头文件:
  #include <unistd.h>
函数原型:
  int execv(const char *path, char *const argv[]);
函数参数:
  path:绝对路径+程序名
  argv:命令+参数
返回值:
  成功:无返回
  失败:-1

5.execvp函数

函数作用:
  加载一个进程,借助PATH环境变量
头文件:
  #include <unistd.h>
函数原型:
  int execvp(const char *file, const char *argv[]);
函数参数:
  file:要加载的程序的名字,通过环境变量
  argv:命令参数
返回值:
  成功:无返回;
  失败:-1
例如:
  char *argv[] = {“ls”, “-l”, “-a”, NULL};
   execvp(“ls”, argv);

6,execve函数

函数作用:
  加载一个进程, 通过 路径+程序名 来加载。
头文件:
  #include <unistd.h>
函数原型:
  int execve(const char *path, char *const argv[], char *const envp[]);
函数参数:
  path:绝对路径+程序名
  argv:命令参数
  envp:传递的环境变量
返回值:
  成功:无返回;
  失败:-1

exec函数一旦调用成功即执行新的程序,不返回。只有失败才返回,错误值-1。所以通常我们直接在exec函数调用后直接调用perror()和exit(),无需if判断。
  l (list)    命令行参数列表
  p (path)    搜索file时使用path变量
  v (vector)   使用命令行参数数组
  e (environment)  使用环境变量数组,不使用进程原有的环境变量,设置新加载程序运行的环境变量

进程结束

当程序执行到 exit() 函数或者 _exit() 函数时候,进程 会 无条件停止剩下的所有操作,清除各种数据结构,并终止本进程的运行。但是,这两函数还是有区别的,

  return 表示的是把程序流程从被调函数转向主调函数并把表达式的值带回主调函数,实现函数值的返回,返回时可附带一个返回值,由return后面的参数指定。

 return:函数结束,是函数级别的结束,而 exit() 和 _eixt() 是系统级别的结束。
    但是需要注意的是,在main函数中执行return语句,则整个进程结束。

  _exit() 函数的作用是直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构;而 exit() 函数则在这些基上做了一些包装,在执行退出之前加了若于道工序。

  exit() 函数与 _exit() 函数最大的区别就在于 exit() 函数在终止当前进程之前要检查该进程打开了哪些文件,并把文件缓冲区中的内容写回文件,就是图中的“清理IO缓冲”的表述。

1.exit     库函数
    退出状态,终止的进程会通知父进程,自己使如何终止的。    
    如果是正常结束(终止),则由exit传入的参数。
    如果是异常终止,则有内核通知异常终止原因的状态。
    任何情况下,父进程都能使用wait,waitpid获得这个状态,以及资源的回收。
    void exit(int status) 
    exit(1);
    功能:
        让进程退出,并刷新缓存区
    参数:
        status:进程退出的状态
2._exit    系统调用
    void _exit(int status);
    功能:
        让进程退出,不刷新缓存区
    参数:
        status:进程退出状态
    3.atexit

    int atexit(void (*function)(void));
    功能:
        注册进程退出前执行的函数
    参数:  

        function:函数指针
            指向void返回值void参数的函数指针
    返回值:
        成功返回0
        失败返回非0

    当程序调用exit或者由main函数执行return时,所有用atexit
    注册的退出函数,将会由注册时顺序倒序被调用

注意:
   a. 是exit函数调用时,会调atexit函数 
      _exit函数调用时,不会调到atexit
   b. atexit 程序正常结束
      (1).main 返回 //exit 
      (2).exit()        
   c.atexit函数 可以多次注册 
   d.最后"退出清理函数"的调用顺序,与注册顺序相反。
    
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值