Linux函数exec

一、概述:
当用fork函数创建新的子进程后,子进程往往要调用一种exec函数以执行另一个程序。当程序调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆段和栈段。

三、有7种不同的exec函数可供使用,它们常常被统称为exec函数。

       #include <unistd.h>extern char **environ;1.     int execl(const char *path, const char *arg, ...);
2.     int execlp(const char *file, const char *arg, ...);
3.     int execle(const char *path, const char *arg,..., char * const envp[]);
4.     int execv(const char *path, char *const argv[]);
5.     int execvp(const char *file, char *const argv[]);
6.     int execvpe(const char *file, char *const argv[],char *const envp[]);

(我们只讲其中的execl,execlp,execvp)
参数:
*path:可执行文件的路径名。
*arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路经且arg必须以NULL结束。
*file:如果参数file中包含/,则就将其视为路径名,否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件。

函数名中的字符可以帮助理解和分辨:
l表示以参数列表的形式调用
v表示以参数数组的方式调用
e表示可传递环境变量
p表示PATH中搜索执行的文件,如果给出的不是绝对路径就会去PATH搜索相应名字的文件,如PATH没有设置, 则会默认在/bin,/usr/bin下搜索。

返回值:
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。

二、exec族函数的作用
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

与一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表面上的信息仍保持原样。只有调用失败了,它们才会返回一个-1,从原程序的调用点接着往下执行。

三、实例1:在执行文件execl.c过程中调用execl,从而执行echoarg.c。

文件:echoarg.c

#include <stdio.h>int main(int argc,char *argv[])
{int i = 0;for(i = 0; i < argc; i++){printf("argv[%d]: %s\n",i,argv[i]);}return 0;
}

只编译运行echoarg.c结果如下:

文件:execl.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("./echoarg","file1","file2",NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

注:perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr)。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量errno的值来决定要输出的字符串。

若调用execl失败,返回-1,然后开始执行 printf(“after execl\n”);(打印"after execl")。
若成功则不执行 printf(“after execl\n”);(不打印"after execl")。

四、实例2:
我们都知道ls命令是linux下最常用的命令之一,用来列出目录下的文件。我们也可以调用execl来执行ls的命令。

ls指令运行结果:

我们可以通过whereis ls 指令来获得ls的文件路径。

execl.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("/bin/ls","ls",NULL,NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

编译运行结果如下:

ls -l则会把详细列表打印出来:

可以尝试在execl函数的第三个参数写为“-l”:
execl.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("/bin/ls","ls","-l",NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

编译运行结果如下:

五、实例3:获取日期和时间
Linux指令date 可以用来显示或设定系统的日期与时间

我们也可以调用execl函数来获取日期和时间(原理同实例2相同)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("/bin/date","date",NULL,NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

编译运行结果如下:

六、在前面几个实例中调用函数execl第一个参数需要给出绝对路径,而函数execlp通过环境变量PATH查找到可执行文件(如实例6的“date”)。

实例6:execlp.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execlp\n");if(execlp("date","date",NULL,NULL) == -1){printf("execlp failed!\n");perror("why");}printf("after execlp\n");return 0;
}


实例7.execvp.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execvp\n");char *argv[] = {"data",NULL,NULL};if(execvp("date",argv) == -1) {printf("execvp failed!\n");perror("why");}printf("after execvp\n");return 0;
}

与execlp不同,execvp以参数数组的方式调用。

七、前面在讲函数fork和vfork中我们提到:
fork有以下两种用法。
(1) 一个父进程希望复制自己,使父进程和子进程同时执行不同的代码段。这在网络服务进程中是常见的—父进程等待客户端的服务请求。当这种请求到达时,父进程调用fork,使子进程处理此请求。父进程则继续等待下一个服务请求。
(2) 一个进程要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从返回后立刻调用exec。

所以我们可以把fork和exec配合使用。

实例8:通过调用fork创建子进程来对文件进行更改。
TEST.config

SPEED=3
LENG=9
SCORE=9
LEVEL=0

change.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main(int argc,char *argv[])
{int  fdsrc;char *readbuf=NULL;if(argc!=2){printf("param error\ni");exit(-1);}fdsrc=open(argv[1],O_RDWR);int size=lseek(fdsrc,0,SEEK_END);lseek(fdsrc,0,SEEK_SET);readbuf=(char *)malloc(sizeof(size)+8);int n_read=read(fdsrc,readbuf,size);char *p=strstr(readbuf,"LENG=");if(p==NULL){printf("not found\n");exit(-1);}p=p+strlen("LENG=");*p='5';lseek(fdsrc,0,SEEK_SET);int n_write=write(fdsrc,readbuf,strlen(readbuf));close(fdsrc);return 0;
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>int main()
{pid_t pid;int data = 0;while(1){printf("please input a data\n");scanf("%d",&data);if(data==1){pid=fork();if(pid>0){wait(NULL);}if(pid==0){execl("./change","change","TEST.config",NULL);}}else{printf("wait...\n");}}return 0;
}


demo.c中调用当输入data = 1时,函数fork创建子进程,子进程调用execl来执行change(可执行文件),在change中对TEST.config进行更改。
文件TEST.config中"LENG"被修改成 了9。

Linux函数exec相关推荐

  1. linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)

    原文链接:https://blog.csdn.net/u014530704/article/details/73848573 exec族函数函数的作用: 我们用fork函数创建新进程后,经常会在新进程 ...

  2. linux函数的阻塞与非阻塞IO及错误处理

    linux函数的阻塞与非阻塞IO及错误处理 1.阻塞是指进程等待某一个事件的发生而处于等待状态不往下执行,如果等待的事件发生了则会继续执行该进程.调用系统阻塞函数可能会导致进程阻塞进入睡眠状态. 2. ...

  3. 在Linux使用exec执行命令时报的哪些错

    问题1:find: paths must precede expression [root@localhost data]# find /oracle/backup/exp/data -name ex ...

  4. 中文在线Linux函数参考手册

    Linux函数 http://www.iteedu.com/os/ http://net.pku.edu.cn/~yhf/linux_c/ linux命令 http://www.iteedu.com/ ...

  5. linux:exec族函数, exec族函数配合fork使用,system 函数,popen 函数

    1.exec族函数 精彩博文: https://blog.csdn.net/u014530704/article/details/73848573 ​ ​ ​ path:   比如说 ./a.out ...

  6. linux进程---exec族函数(execl, execlp, execv, execvp, )解释和配合fork的使用

    exec族函数函数的作用:         exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件.这里的可执行文件既可以是二 ...

  7. linux 进程函数替换,Linux使用exec函数实现进程替换的代码分享

    这篇文章主要介绍了Linux 进程替换(exec函数)实现代码的相关资料,需要的朋友可以参考下 Linux 进程替换(exec函数)实现代码# include #include #include #i ...

  8. Linux进程—exec族函数 execl, execlp, execle, execv, execvp

    exec族函数的作用: 我们用fork函数创建新进程后,经常会在新进程中调用exec族函数去执行新的程序:当该进程调用exec族函数时,该进程被替代为新程序,因为exec族函数并不创建新进程,所以前后 ...

  9. Linux进程 exec族函数(execl,execlp,execle,execv,execvp,execcvpe)

    exec族函数的作用 我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序.当进程调用exec函数时,该进程被完全替换为新程序.因为调用exec函数并不创建新进程,所以前 ...

最新文章

  1. MicroPython支持图形化编辑了:Python Editor带你轻松玩转MicroPython
  2. 计算两个日期间隔天数(距离(2024-7-7)间隔:1999天)
  3. mkdir: 无法创建目录“/home/lj/.tldr“: 文件已存在
  4. 移动端采用Flexible将PX转换REM适配及开发中Retina屏1px边框的两种解决方案
  5. linux可配置哪些服务,不可不知 十大热门Linux服务器配置
  6. openerp 常见问题 OpenERP在哪储存附件?(转载)
  7. 工欲善其事必先利其器——MySQL数据库(2),查询操作
  8. python的字典合并有相同的_将列表中的重复项合并到python字典中
  9. python学习第十弹:宝可梦数据分析-平民最强
  10. windows 7计算机用户名和密码忘了,w7笔记本忘记开机密码怎么办_win7笔记本电脑忘记登录密码解决方法-系统城...
  11. 纸黄金投资之道――积小胜为大胜(就是别贪)
  12. 测试员,面对自己30岁后的下坡路,我们该何去何从?
  13. install在python里什么意思_python setup.py install是什么意思
  14. jq点击图片展示预览效果
  15. turtle 绘画实例1 画圆
  16. 类似Confluence的软件有哪些
  17. 三角波发生器电路图分析
  18. w ndows 10关机,Win10设置定时开关机休眠唤醒的方法
  19. INCREMENTAL BACKUP
  20. Urban Airship Android Client - Google GCM Push

热门文章

  1. NOIP2009 普及组 复赛 poly 多项式输出
  2. B站有哪些可以推荐的学习 up 主?
  3. 博主联系方式汇总(非诚勿扰)
  4. 什么是百度转码?如何禁止网站百度转码?
  5. 一心多用多线程-Thread的api探险
  6. 如何理解柯里化|函数式编程
  7. 浅析计算机信息管理系统任务书,计算机工程系学生就业信息管理系统任务书
  8. Yolo v3的学习
  9. 【黑马程序员西安中心】 css布局
  10. useradd 与adduser的区别