长沙网站,张店网站制作,wordpress主题少儿教育类,寮步网站建设高性能在 Windows 平台下#xff0c;我们可以通过双击运行可执行程序#xff0c;让这个可执行程序成为一个进程#xff1b;而在 Linux 平台#xff0c;我们可以通过 ./ 运行#xff0c;让一个可执行程序成为一个进程。但是#xff0c;如果我们本来就运行着一个程序#xff08;…在 Windows 平台下我们可以通过双击运行可执行程序让这个可执行程序成为一个进程而在 Linux 平台我们可以通过 ./ 运行让一个可执行程序成为一个进程。但是如果我们本来就运行着一个程序进程我们如何在这个进程内部启动一个外部程序由内核将这个外部程序读入内存使其执行起来成为一个进程呢这里我们通过 exec 函数族实现。exec 函数族顾名思义就是一簇函数在 Linux 中并不存在 exec() 函数exec 指的是一组函数一共有 6 个#include unistd.h
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 函数族提供了六种在进程中启动另一个程序的方法。exec 函数族的作用是根据指定的文件名或目录名找到可执行文件并用它来取代调用进程的内容换句话说就是在调用进程内部执行一个可执行文件。进程调用一种 exec 函数时该进程完全由新程序替换而新程序则从其 main 函数开始执行。因为调用 exec 并不创建新进程所以前后的进程 ID 当然还有父进程号、进程组号、当前工作目录……并未改变。exec 只是用另一个新程序替换了当前进程的正文、数据、堆和栈段进程替换。exec 函数族的 6 个函数看起来似乎很复杂但实际上无论是作用还是用法都非常相似只有很微小的差别。l(list)参数地址列表以空指针结尾。v(vector)存有各参数地址的指针数组的地址。p(path)按 PATH 环境变量指定的目录搜索可执行文件。e(environment)存有环境变量字符串地址的指针数组的地址。exec 函数族装入并运行可执行程序 path/file并将参数 arg0 ( arg1, arg2, argv[], envp[] ) 传递给此程序。exec 函数族与一般的函数不同exec 函数族中的函数执行成功后不会返回而且exec 函数族下面的代码执行不到。只有调用失败了它们才会返回 -1失败后从原程序的调用点接着往下执行。需要C/C Linux服务器架构师学习资料加qun获取资料包括C/CLinuxgolang技术NginxZeroMQMySQLRedisfastdfsMongoDBZK流媒体CDNP2PK8SDockerTCP/IP协程DPDKffmpeg等免费分享execl() 示例代码#include stdio.h
#include unistd.hint main(int argc, char *argv[])
{printf(before execnn);/* /bin/ls外部程序这里是/bin目录的 ls 可执行程序必须带上路径相对或绝对ls没有意义如果需要给这个外部程序传参这里必须要写上字符串至于字符串内容任意-a-l-h给外部程序 ls 传的参数NULL这个必须写上代表给外部程序 ls 传参结束*/execl(/bin/ls, ls, -a, -l, -h, NULL);// 如果 execl() 执行成功下面执行不到因为当前进程已经被执行的 ls 替换了perror(execl);printf(after execnn);return 0;
}运行结果如下execv()示例代码execv() 和 execl() 的用法基本是一样的无非将列表传参改为用指针数组。#include stdio.h
#include unistd.hint main(int argc, char *argv[])
{// execv() 和 execl() 的用法基本是一样的无非将列表传参改为用指针数组// execl(/bin/ls, ls, -a, -l, -h, NULL);/* 指针数组ls没有意义如果需要给这个外部程序传参这里必须要写上字符串至于字符串内容任意-a-l-h给外部程序 ls 传的参数NULL这个必须写上代表给外部程序 ls 传参结束*/char *arg[]{ls, -a, -l, -h, NULL};// /bin/ls外部程序这里是/bin目录的 ls 可执行程序必须带上路径相对或绝对// arg 上面定义的指针数组地址execv(/bin/ls, arg);perror(execv);return 0;
}execlp() 或 execvp() 示例代码execlp() 和 execl() 的区别在于execlp() 指定的可执行程序可以不带路径名如果不带路径名的话会在环境变量 PATH指定的目录里寻找这个可执行程序而 execl() 指定的可执行程序必须带上路径名。#include stdio.h
#include unistd.hint main(int argc, char *argv[])
{// 第一个参数 ls没有带路径名在环境变量 PATH 里寻找这个可执行程序// 其它参数用法和 execl() 一样execlp(ls, ls, -a, -l, -h, NULL);/*char *arg[]{ls, -a, -l, -h, NULL};execvp(ls, arg);*/perror(execlp);return 0;
}execle() 或 execve() 示例代码execle() 和 execve() 改变的是 exec 启动的程序的环境变量只会改变进程的环境变量不会影响系统的环境变量其他四个函数启动的程序则使用默认系统环境变量。execle()示例代码#include stdio.h
#include unistd.h
#include stdlib.h // getenv()int main(int argc, char *argv[])
{// getenv() 获取指定环境变量的值printf(before execUSER%s, HOME%sn, getenv(USER), getenv(HOME));// 指针数据char *env[]{USERMIKE, HOME/tmp, NULL};/* ./mike外部程序当前路径的 mike 程序通过 gcc mike.c -o mike 编译mike这里没有意义NULL给 mike 程序传参结束env改变 mike 程序的环境变量正确来说让 mike 程序只保留 env 的环境变量*/execle(./mike, mike, NULL, env);/*char *arg[]{mike, NULL}; execve(./mike, arg, env); */perror(execle);return 0;
}外部程序mike.c 示例代码#include stdio.h
#include stdlib.h
#include unistd.hint main(int argc, char *argv[])
{printf(nin the mike fun, after exec: n);printf(USER%sn, getenv(USER));printf(HOME%sn, getenv(HOME));return 0;
}运行结果如下