说是exec系统调用
,实际上在Linux中,并不存在一个exec()的函数形式,exec指的是一组函数,一共有6个,分别是:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
其中只有execve是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
与
一般情况不同,exec函数族的函数执行成功后不会返回,因为调用进程的实体,包括代码段,数据段和堆栈等都已经被新的内容取代,只留下进程ID等一些表
面上的信息仍保持原样,颇有些神似"三十六计"中的"金蝉脱壳"。看上去还是旧的躯壳,却已经注入了新的灵魂。只有调用失败了,它们才会返回一个-1,从
原程序的调用点接着往下执行。
现在我们应该明白了,Linux下是如何执行新程序的,每当有进程认为自己不能为系统和拥护做出任何
贡献了,他就可以发挥最后一点余热,调用任何一个exec,让自己以新的面貌重生;或者,更普遍的情况是,如果一个进程想执行另一个程序,它就可以
fork出一个新进程,然后调用任何一个exec,这样看起来就好像通过执行应用程序而产生了一个新进程一样。
事实
上第二种情况被应用得如此普遍,以至于Linux专门为其作了优化,我们已经知道,fork会将调用进程的所有内容原封不动的拷贝到新产生的子进程中去,
这些拷贝的动作很消耗时间,而如果fork完之后我们马上就调用exec,这些辛辛苦苦拷贝来的东西又会被立刻抹掉,这看起来非常不划算,于是人们设计了
一种"写时拷贝(copy-on-write)"技术,使得fork结束后并不立刻复制父进程的内容,而是到了真正实用的时候才复制,这样如果下一条语句
是exec,它就不会白白作无用功了,也就提高了效率。
返回值
如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
大家在平时的编程中,如果用到了exec函数族,一定记得要加错误判断语句。因为与其他系统调用比起来,exec很容易受伤,被执行文件的位置,权限等很多因素都能导致该调用的失败。最常见的错误是:
1.找不到文件或路径,此时errno被设置为ENOENT;
2.数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT;
3.没有对要执行文件的运行权限,此时errno被设置为EACCES。
l表示以参数列表的形式调用
v表示以参数数组的方式调用
e表示可传递环境变量
p表示PATH中搜索执行的文件,如果给出的不是绝对路径就会去PATH搜索相应名字的文件,如PATH没有设置,则会默认在/bin,/usr/bin下搜索。
另:调用时参数必须以NULL结束。原进程打开的文件描述符是不会在exec中关闭的,除非用fcntl设置它们的“执行时关闭标志(close on exec)”而原进程打开的目录流都将在新进程中关闭。
例子:
#include <unistd.h>
int main(int argc, char *argv[])
{
char *envp[]={"PATH=/tmp", "USER=lei", "STATUS=testing", NULL};
char *argv_execv[]={"echo", "excuted by execv", NULL};
char *argv_execvp[]={"echo", "executed by execvp", NULL};
char *argv_execve[]={"env", NULL};
if(fork()==0) {
if(execl("/bin/echo", "echo", "executed by execl", NULL)<0)
perror("Err on execl");
}
if(fork()==0) {
if(execlp("echo", "echo", "executed by execlp", NULL)<0)
perror("Err on execlp");
}
if(fork()==0) {
if(execle("/usr/bin/env", "env", NULL, envp)<0)
perror("Err on execle");
}
if(fork()==0) {
if(execv("/bin/echo", argv_execv)<0)
perror("Err on execv");
}
if(fork()==0) {
if(execvp("echo", argv_execvp)<0)
perror("Err on execvp");
}
if(fork()==0) {
if(execve("/usr/bin/env", argv_execve, envp)<0)
perror("Err on execve");
}
}
分享到:
相关推荐
1.exec函数族 exec 为 execute(执行),exec 函数族用来替换调用进程所执行的程序,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行,替换前后进程的 PID 不会改变。 exec函数族中包括6个...
在Linux操作系统中,进程执行是通过系统调用来完成的,其中`exec`函数族就是一组用于替换当前进程映像的函数。这些函数允许程序在不退出的情况下加载并执行新的程序。在本压缩包中,包含的`execl.c`和`helloexec.c`...
在Linux系统编程中,进程替换是一种重要的技术,它允许一个正在运行的进程用新的程序来替代自身,这个过程通常涉及到`exec`函数族。`exec`函数族包括多个成员,如`execl`, `execlp`, `execle`, `execv`, `execvp`, ...
exec函数和shell_exec函数都可以用来执行Linux命令,但它们获取命令执行结果的方式不同。exec函数只能获取命令的最后一行输出,而shell_exec函数可以获取命令的所有输出。具体来说,当需要执行的命令返回多行结果时...
### 基于exec函数族分析Linux初始化进程运行环境的过程 #### 一、Linux内存管理简介 Linux操作系统采用了一种高效的虚拟内存管理机制,其中主要包括分页管理技术。这一技术的核心在于将物理内存划分为固定大小的块...
5. **进程与线程**:Linux提供了一套丰富的系统调用来管理进程和线程,如fork()创建新进程,exec()系列函数执行新的程序,pthread_create()创建线程,pthread_join()等待线程结束等。 6. **信号处理**:通过...
此外,针对Linux系统,书中还详细讲解了与系统交互的函数,如fork用于创建子进程,exec系列函数用于执行新的程序,以及socket函数用于网络通信等。这些都是Linux开发中不可或缺的部分,对于理解和编写系统级程序至关...
Linux进程和线程编程(exec) 在Linux操作系统中,进程和线程编程是非常重要的概念,exec函数族...exec函数族是Linux中非常重要的进程创建函数,了解exec函数族的使用和特点对我們编写高效、可靠的Linux程序非常重要。
4. **进程操作篇**:讨论了如何在Linux中创建、管理、通信和调度进程,如fork()、exec()、wait()和signal()函数,这些都是实现并发编程的基础。 5. **文件权限控制篇**:讲解如何使用chmod、chown、chgrp等命令,...
《Linux C函数库中文手册》是一本针对Linux操作系统下C语言编程的重要参考资料,它详尽地阐述了在Linux环境中常用C函数的用法,并且配备了丰富的实例,便于读者理解和掌握。这本书采用CHM(Microsoft Compiled ...
在Linux系统中,C语言是核心开发语言,它提供了丰富的函数库来支持各种操作和功能。本篇文章将深入探讨Linux C函数大全中的关键知识点,帮助读者掌握这些基础但至关重要的编程工具。 一、标准库函数 Linux C函数...
- 进程控制:fork()、exec()、wait()系列函数。 - 线程管理:pthread_create()、pthread_join()等。 以上是C语言在Linux环境下的一些核心知识点,本书“Linux C函数详解”会详细讲解这些概念并提供丰富的实例,...
例如,`open`函数用于打开一个文件或设备,`read`和`write`则用于从文件或向文件传输数据,而`fork`和`exec`则涉及进程的创建和执行新的命令。掌握这些系统调用的使用,可以让开发者更深入地理解操作系统如何工作,...
这展示了exec函数如何在不返回的情况下执行新程序的能力。 **2. fork函数** `fork`函数用于创建子进程。当调用`fork`成功时,它会在调用进程(父进程)中返回子进程ID,在子进程中返回0。实验中,我们观察到父进程...
《Linux C 函数全集》这本书深入介绍了Linux环境下C语言的各种库函数,帮助程序员更好地理解和利用这些功能强大的工具。本文将依据标题和描述,详细探讨Linux C库函数的相关知识点。 1. **标准C库函数**:C语言的...
Linux C 函数使用手册是C语言开发者在Linux环境下不可或缺的参考资料。CHM(Compiled Help Manual)格式是一种由微软开发的帮助文档格式,它将文本、图片等信息编译成单一的二进制文件,便于快速检索和查看。在这个...
在Linux操作系统中,进程是程序执行的实例。本篇文章主要探讨了几个与进程管理相关的函数:atexit、execl、execlp以及execv。这些函数允许程序员在程序执行的不同阶段进行控制,如设置程序结束前要调用的函数,或者...
6. **系统调用**:如`fork`用于创建子进程,`exec`系列函数用于执行新的程序,`wait`和`waitpid`用于等待子进程结束。这些是进行进程控制的关键。 7. **错误处理**:`perror`函数将错误代码转化为人类可读的错误...
Linux提供了丰富的进程控制函数,如`fork` 创建子进程,`exec` 家族函数替换当前进程执行新的程序,`wait` 和 `waitpid` 用于父进程等待子进程结束。 7. **线程操作**: 在多线程编程中,`pthread_create` 创建新...
7. **进程控制**:`fork`创建子进程,`exec`系列函数替换当前进程执行新的程序。`wait`和`waitpid`用于等待子进程结束。 8. **信号处理**:`signal`函数用于注册信号处理器,`raise`发送信号给进程。 9. **网络...