简述网站建设方案类型,wordpress 导航站模板下载地址,设计师培训内容,购物商城名字大全0.引入创建子进程的目的是什么#xff1f;就是为了让子进程帮我执行特定的任务让子进程执行父进程的一部分代码如果子进程想执行一个全新的程序代码呢#xff1f; 那么就要使用进程的程序替换为什么要有程序替换#xff1f;也就是说子进程想执行一个全新的程序代码#xff…0.引入创建子进程的目的是什么就是为了让子进程帮我执行特定的任务让子进程执行父进程的一部分代码如果子进程想执行一个全新的程序代码呢 那么就要使用进程的程序替换为什么要有程序替换也就是说子进程想执行一个全新的程序代码这份代码看似是子进程的代码其实也是父进程的代码只是父进程通过id的值进行判断让子进程运行。1.替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。 2.替换函数其实有六种以exec开头的函数,统称exec函数: 使用man手册查看相关exec函数execl最后的...参数表示可变参数列表可以给C函数传递任意的参数execlint execl(const char *path, const char *arg, ...);path新程序的路径和名称。arg0 ~ argn新程序的命令行参数列表以 NULL 结尾。arg0 表示新程序的名称arg1 ~ argn 表示新程序的各个参数。为什么只看到了begin()... end...为什么不显示呢执行程序替换新的代码和数据都被加载了后续的代码属于老代码直接被替换了没机会执行了并且程序替换是整体替换不能局部替换ls是磁盘上的可执行程序execl调用了ls-la把当前的代码和数据从execl到磁盘中进行替换问题进程的程序替换有没有创建新的进程呢没有为什么呢很简单因为我只是把一个新的程序加载到我们当前进程所对应的代码和数据段我就让CPU去调度当前进程就可以跑起来了。其中我们并没有创建新的进程。当前的进程PID没有变化这是站在进程的角度来看的那么站在程序的角度呢? -- 这个程序被加载到内存里了所以我们也可以说execl是加载器问题当创建进程的时候先加载进程数据结构还是先加载代码和数据在创建进程时操作系统通常会先创建进程数据结构然后再加载代码和数据。这里代码子进程里的execl替换代码会影响父进程吗不会程序替换只会影响调用进程进程具有独立性子进程加载新程序的时候是需要进行程序替换的发生写时拷贝(子进程执行的可是全新的程序新的代码写时拷贝在代码区也可以发生)execl函数调用失败会发生什么我们写一个代码让程序故意发生错误父进程获取子进程退出码接下来开始熟悉所有的接口execv int execv(const char *path, char *const argv[]);execv() 函数接受两个参数。第一个参数是要执行的程序的路径第二个参数是传递给新程序的命令行参数。这些参数以一个字符串数组的形式传递给函数。注意当execv调用失败的话程序继续执行execlpint execlp(const char *file, const char *arg, ...);其中file 参数表示要执行的可执行文件的名称arg 参数表示传递给该可执行文件的命令行参数最后的参数为可变参数列表表示该命令行参数以 NULL 结束。execlp 函数会在 PATH 环境变量指定的路径中查找可执行文件因此无需指定可执行文件的完整路径。如果 PATH 环境变量中有多个路径则 execlp 函数会按照路径的顺序查找可执行文件。execlp(ls,ls,-a,-l,-n,NULL);这里的两个ls分别是什么意思第一个是系统环境变量路径ls第二个是ls指令等同于以下代码execle int execle(const char *path, const char *arg,..., char * const envp[]);该函数接收以下参数path要执行的程序的路径名。arg0新程序的第一个参数通常是新程序的名称。arg1~argn新程序的参数列表。envp新程序的环境变量数组。该函数的返回值是一个整数如果成功执行则永远不会返回。如果出现错误则会返回-1并设置errno来指示错误的类型。envp[]数组是自定义环境变量execvp函数原型如下int execvp(const char *file, char *const argv[]);该函数会在PATH环境变量指定的路径中搜索指定的可执行文件并在找到文件后将当前进程替换为该可执行文件。其中file参数是一个字符串指定要执行的可执行文件的路径和文件名。argv参数是一个指向字符串数组的指针其中第一个字符串表示可执行文件的名称后面的字符串表示传递给可执行文件的命令行参数。execvpe函数原型如下int execvpe(const char *file, char *const argv[], char *const envp[]);file 参数是要执行的可执行文件的路径argv 参数是一个指向参数列表的指针数组envp 参数是一个指向环境变量列表的指针数组。execvpe 函数首先会搜索 PATH 环境变量中指定的目录找到可执行文件后它会用新的进程替换当前进程并开始执行新的程序。在新的进程中参数和环境变量都被设置成 argv 和 envp 中指定的值。execvpe 函数和其他 exec 系列函数的主要区别在于它会搜索 PATH 环境变量中指定的目录来查找可执行文件并且可以设置环境变量。execve函数原型如下int execve(const char *filename, char *const argv[], char *const envp[]);filename 参数是要执行的可执行文件的路径argv 参数是一个指向参数列表的指针数组envp 参数是一个指向环境变量列表的指针数组。execve 函数会用新的进程替换当前进程并开始执行新的程序。在新的进程中参数和环境变量都被设置成 argv 和 envp 中指定的值。execve 函数不会搜索 PATH 环境变量中指定的目录来查找可执行文件它只会使用 filename 参数中指定的路径来查找可执行文件。如果指定的文件路径不是一个可执行文件那么该函数会返回一个错误。事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve,所以execve在man手册第2节,其它函数在man手册第3节。这些函数之间的关系如下图所示。下图exec函数族 一个完整的例子:3.调用自定义程序上面都是执行命令。能否执行我自己写的程序呢用C语言调用C写的可执行程序可以发现PID是一模一样的替换了C程序没有创建新的进程接下来尝试在C程序中获取环境变量获取环境变量。C的cout如果环境变量不存在就什么都不会打印所以要进行判断如果没有就打印NULL修改下C程序在C程序中自定义环境变量表使用execle函数问题C语言调用C可以调用到环境变量吗修改下C代码获取环境变量C自己写的里有PATH但没有环境变量观察下C语言的C语言调用的有MYENV 但是没有PATH调用的环境变量是覆盖式写入会覆盖老的环境变量PATH所以看不到PATH传系统环境变量C语言提供的环境变量表二级指针environ此时MYENV就没有了系统的环境变量出现了系统环境变量和自定义环境变量同时传递利用putenv添加到系统环境变量里依赖头文件#includestdlib.hputenv将MYENV传到系统变量里这样调用系统变量就可以将自定义和系统变量一块传递给替换程序环境变量具有全局属性可以被子进程继承下去 就是通过execle函数传递的环境变量使用export MYENV You can see me 也可以4.exec函数解释1.这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。 2.如果调用出错则返回-1 3.所以exec函数只有出错的返回值而没有成功的返回值。 5.命名理解 这些函数原型看起来很容易混,但只要掌握了规律就很好记。 l(list) : 表示参数采用列表 v(vector) : 参数用数组 p(path) : 有p自动搜索环境变量PATH e(env) : 表示自己维护环境变量 exec调用举例如下: #include unistd.h
int main()
{char *const argv[] {ps, -ef, NULL};char *const envp[] {PATH/bin:/usr/bin, TERMconsole, NULL};execl(/bin/ps, ps, -ef, NULL);// 带p的可以使用环境变量PATH无需写全路径execlp(ps, ps, -ef, NULL);// 带e的需要自己组装环境变量execle(ps, ps, -ef, NULL, envp);execv(/bin/ps, argv);// 带p的可以使用环境变量PATH无需写全路径execvp(ps, argv);// 带e的需要自己组装环境变量execve(/bin/ps, argv, envp);exit(0);
}