企业网站建设知识,连云港优化推广,白狐网站建设,新乡商城网站建设哪家好#x1f941;作者#xff1a; 华丞臧. #x1f4d5;专栏#xff1a;【LINUX】 各位读者老爷如果觉得博主写的不错#xff0c;请诸位多多支持(点赞收藏关注)。如果有错误的地方#xff0c;欢迎在评论区指出。 推荐一款刷题网站 #x1f449; LeetCode刷题网站 文… 作者 华丞臧. 专栏【LINUX】 各位读者老爷如果觉得博主写的不错请诸位多多支持(点赞收藏关注)。如果有错误的地方欢迎在评论区指出。 推荐一款刷题网站 LeetCode刷题网站 文章目录一、进程替换1.1 替换原理1.2 替换函数二、exec函数2.1 execl2.2 execv2.3 execlp2.5 execle2.4 execvp2.5 execve补充快捷键批量化注释批量化取消注释一、进程替换 前面我们学习了如何创建子进程也知道了子进程执行的是父进程的代码片段那么如果我们想让创建出来的子进程执行全新的程序呢这时候就需要进程的程序替换。 一般在Linux编程的时候需要子进程做两类事情
让子进程执行父进程的代码片段服务器代码让子进程执行磁盘中的一个全新的程序如shell可以让客户端执行其他人写的代码。
1.1 替换原理
用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
程序替换原理总结 将磁盘中的程序加载到内存结构重新建立页表映射谁执行程序替换就重新建立谁的页表映射效果让我们的父进程和子进程彻底分离并让子进程执行一个全新的程序。 注意在程序替换的过程中没有创建新的进程这个过程指的是程序替换的过程此时子进程已经创建好了不算新创建的进程。
1.2 替换函数
Linux中有六种exec开头的函数统称exec函数 以下六种函数都可以用来进程替换。
#include unistd.hint 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[]);函数解释
这些函数如果调用成功则加载新的程序从启动代码开始执行不再返回如果调用出错则返回-1。所以exec函数只有出错的返回值而没有成功的返回值。
命名理解 这些函数原型看起来很容易混,但只要掌握了规律就很好记。
llist表示参数采用列表vvector参数用数组ppath有p自动搜索环境变量PATHeenv表示自己维护环境变量
函数名参数格式是否带路径是否使用当前环境变量execl列表不是是execlp列表是是execle列表不是不是必须自己组装环境变量execv数组不是是execvp数组是是execve数组不是不是须自己组装环境变量
二、exec函数
接下来我们挑几个exec函数来说明其使用方式。
2.1 execl
int execl(const char *path, const char *arg, ...);说明
path程序所在的路径。arg替换的程序名。...可变参数列表这个我们在使用printf和scanf的时候见过。execl函数替换失败返回-1
首先使用exec函数之前我们需要知道如果想执行一个全新的程序需要做下面两件事
找到执行程序路径程序可能携带选项进行执行也可以不携带
这里我们可以参照Linux上的命令行是如何使用的如下 Linux中的指令本质上就是程序所以命令行怎么写我们程序携带选项时传参就怎么写。既然Linux中的指令也是程序我们首先来试试用指令来替换我们写的程序代码如下
#include stdio.h
#include unistd.hint main()
{printf(进程pid%d\n, getpid());// arg表示目标程序名而...参数列表必须以NULL结尾execl(/usr/bin/ls, ls, NULL); //不带参数//execl(/usr/bin/ls, ls, -al, NULL); //带参数printf(进程替换成功\n);return 0;
}不带参数的如下图 带参数的如下图 观察上述两幅图片我们发现代码中execl下面的那句 printf并没有执行这是因为一旦替换成功会将当前进程的代码和数据全部替换了因此执行完execl函数进程中的代码和数据已经全部被替换了。 程序替换函数也有返回值为int类型这个返回值不需要判断一旦进程替换成功就不会有返回值而替换失败必然会继续向后执行这个返回值最多让我们知道是什么原因导致替换失败。 使用fork创建子进程再将子进程进行程序替换会不会影响父进程呢 答案是不会下面我们来实验其过程。 #include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());execl(/usr/bin/ls, ls, -al, NULL);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}可以看到子进程进行程序替换不会影响父进程因为进程具有独立性在数据层面发生写时拷贝当程序替换的时候可以理解为代码和数据都发生了写时拷贝完成了父子进程的分离。
2.2 execv
int execv(const char *path, char *const argv[]);函数说明
path目标程序的路径argv数组用来传参替换失败返回-1其中v表示数组vector。
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());// 使用argv进行传参数组中第一个元素argv[0]必须为目标程序名//argv也必须以NULL结尾//char *const myenv[] {// (char*)ls,// (char*)-a,// (char*)-l,// NULL//};char *const myenv[] {(char*)pwd,NULL};//execv(/usr/bin/ls, myenv);execv(/usr/bin/pwd, myenv);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}2.3 execlp
int execlp(const char *file, const char *arg, ...);函数说明
file目标程序名arg参数传目标程序名...可变参数列表函数命名带p表示可以不带路径只需要说明目标程序名系统会通过环境变量PATH查找。替换失败返回-1。
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid()); // 使用execlp可以不带路径// 其中两个ls含义不同// 第一个为供系统查找后面一个加上选项表示如何执行execlp(ls, ls, -a, NULL);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}2.5 execle
int execle(const char *path, const char *arg, ...,char *const envp[]);函数说明
path目标程序所在路径arg参数传目标程序名...可变参数列表envp用户传给目标程序的环境变量失败返回-1。
使用exec函数也可以替换用户自己写的程序
//replace.c
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());char *const env_[] {(char*)MYPATHHELLOWORLD,NULL};execle(./mytest, mytest, NULL, env_);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}//mytest.cpp
#include iostream
#include stdlib.husing namespace std;int main()
{cout PATH: getenv(PATH) endl;//cout MYPATH: getenv(MYPATH) endl;cout hello world1 endl;cout hello world2 endl;cout hello world3 endl;cout hello world4 endl;cout hello world5 endl;return 0;
}如上图当直接使用execle函数时进程替换成功了但是运行时进程崩溃了可以看到此时进程中找不到PATH这个环境变量那么MYPATH(这是execle函数的传参)呢 因此可以得出结论带e的exec函数会添加环境变量给目标进程执行的是覆盖式的。
//这里是使用execl替换代码片段
if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());execl(./mytest, mytest, NULL);exit(1);}使用execl函数PATH环境变量可以正常打印。
如果想要将系统的环境变量保存并且也可以使用用户自己的环境变量可以使用export指令添加环境变量
//命令行
export MYPATHHELLO WORLD2.4 execvp
int execvp(const char *file, char *const argv[]);函数说明
file目标程序名argv按照命令行参数格式统一将程序名和选项字符串放入数组中命名带p表示会使用环境变量PATH。
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());char *const myenv[] {(char*)ls,(char*)-a,(char*)-l,NULL};execvp(ls, myenv);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}2.5 execve
与其他的exec函数不同的是execve函数是系统调用接口。
int execve(const char *path, char *const argv[], char *const envp[]);前面学习的那些exec函数基本都是对系统调用接口直接或者间接的封装适应与不同的适用场景。
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.hint main()
{printf(进程pid%d\n, getpid());pid_t id fork();if(id 0){//childprintf(这是子进程pid%dppid%d\n, getpid(), getppid());char *const myenv[] {(char*)ls,(char*)-a,(char*)-l,NULL};char *const env_[] {(char*)MYPATHHELLOWORLD,NULL};execve(./mytest, myenv, env_);exit(1);}//parentprintf(这是父进程pid%dppid%d\n, getpid(), getppid());pid_t ret waitpid(id, NULL, 0);if(ret 0) printf(子进程回收成功,ret:%d\n, ret);return 0;
}补充快捷键
批量化注释
ctrl v按一次即可从需要注释的第一行开始然后使用HJKL上下左右键选中区域如果vim被配置过键盘上的箭头上下左右功能可能改变因此建议使用HJKL。 切换大写输入I输入//再按下Esc就可以完成批量化注释。
批量化取消注释 ctrl v按一次即可从需要取消注释的第一行开始然后使用HJKL上下左右键选中区域 输入d就可以完成批量化取消注释。 文章转载自: http://www.morning.cypln.cn.gov.cn.cypln.cn http://www.morning.tgnr.cn.gov.cn.tgnr.cn http://www.morning.jybj.cn.gov.cn.jybj.cn http://www.morning.fnzbx.cn.gov.cn.fnzbx.cn http://www.morning.sqtsl.cn.gov.cn.sqtsl.cn http://www.morning.fbjqq.cn.gov.cn.fbjqq.cn http://www.morning.pabxcp.com.gov.cn.pabxcp.com http://www.morning.sqskm.cn.gov.cn.sqskm.cn http://www.morning.pmlgr.cn.gov.cn.pmlgr.cn http://www.morning.hsflq.cn.gov.cn.hsflq.cn http://www.morning.ckfyp.cn.gov.cn.ckfyp.cn http://www.morning.jghty.cn.gov.cn.jghty.cn http://www.morning.fjlsfs.com.gov.cn.fjlsfs.com http://www.morning.cybch.cn.gov.cn.cybch.cn http://www.morning.sprbs.cn.gov.cn.sprbs.cn http://www.morning.dansj.com.gov.cn.dansj.com http://www.morning.jgcyn.cn.gov.cn.jgcyn.cn http://www.morning.nhgfz.cn.gov.cn.nhgfz.cn http://www.morning.syssdz.cn.gov.cn.syssdz.cn http://www.morning.prprj.cn.gov.cn.prprj.cn http://www.morning.junmap.com.gov.cn.junmap.com http://www.morning.nrddx.com.gov.cn.nrddx.com http://www.morning.xxgfl.cn.gov.cn.xxgfl.cn http://www.morning.rlrxh.cn.gov.cn.rlrxh.cn http://www.morning.lxjcr.cn.gov.cn.lxjcr.cn http://www.morning.qzzmc.cn.gov.cn.qzzmc.cn http://www.morning.lpzqd.cn.gov.cn.lpzqd.cn http://www.morning.gcysq.cn.gov.cn.gcysq.cn http://www.morning.rdzlh.cn.gov.cn.rdzlh.cn http://www.morning.hkgcx.cn.gov.cn.hkgcx.cn http://www.morning.krgjc.cn.gov.cn.krgjc.cn http://www.morning.pkmcr.cn.gov.cn.pkmcr.cn http://www.morning.wphfl.cn.gov.cn.wphfl.cn http://www.morning.wspyb.cn.gov.cn.wspyb.cn http://www.morning.krfpj.cn.gov.cn.krfpj.cn http://www.morning.dnwlb.cn.gov.cn.dnwlb.cn http://www.morning.mcwrg.cn.gov.cn.mcwrg.cn http://www.morning.qkqgj.cn.gov.cn.qkqgj.cn http://www.morning.dybth.cn.gov.cn.dybth.cn http://www.morning.ylmxs.cn.gov.cn.ylmxs.cn http://www.morning.nwtmy.cn.gov.cn.nwtmy.cn http://www.morning.jnbsx.cn.gov.cn.jnbsx.cn http://www.morning.pgmyn.cn.gov.cn.pgmyn.cn http://www.morning.woyoua.com.gov.cn.woyoua.com http://www.morning.dtcsp.cn.gov.cn.dtcsp.cn http://www.morning.deanzhu.com.gov.cn.deanzhu.com http://www.morning.hclplus.com.gov.cn.hclplus.com http://www.morning.nydtt.cn.gov.cn.nydtt.cn http://www.morning.fbnsx.cn.gov.cn.fbnsx.cn http://www.morning.wmmjw.cn.gov.cn.wmmjw.cn http://www.morning.gtcym.cn.gov.cn.gtcym.cn http://www.morning.gcszn.cn.gov.cn.gcszn.cn http://www.morning.nyqnk.cn.gov.cn.nyqnk.cn http://www.morning.ypktc.cn.gov.cn.ypktc.cn http://www.morning.drnfc.cn.gov.cn.drnfc.cn http://www.morning.xwbwm.cn.gov.cn.xwbwm.cn http://www.morning.zlcsz.cn.gov.cn.zlcsz.cn http://www.morning.ryspp.cn.gov.cn.ryspp.cn http://www.morning.jnptt.cn.gov.cn.jnptt.cn http://www.morning.ptwzy.cn.gov.cn.ptwzy.cn http://www.morning.ltbwq.cn.gov.cn.ltbwq.cn http://www.morning.bktzr.cn.gov.cn.bktzr.cn http://www.morning.thntp.cn.gov.cn.thntp.cn http://www.morning.bwkzn.cn.gov.cn.bwkzn.cn http://www.morning.srky.cn.gov.cn.srky.cn http://www.morning.pmdnx.cn.gov.cn.pmdnx.cn http://www.morning.pzrrq.cn.gov.cn.pzrrq.cn http://www.morning.fpqq.cn.gov.cn.fpqq.cn http://www.morning.tgts.cn.gov.cn.tgts.cn http://www.morning.pljdy.cn.gov.cn.pljdy.cn http://www.morning.wbqk.cn.gov.cn.wbqk.cn http://www.morning.fcqlt.cn.gov.cn.fcqlt.cn http://www.morning.gkmwx.cn.gov.cn.gkmwx.cn http://www.morning.hzqjgas.com.gov.cn.hzqjgas.com http://www.morning.rbxsk.cn.gov.cn.rbxsk.cn http://www.morning.kwblwbl.cn.gov.cn.kwblwbl.cn http://www.morning.dskmq.cn.gov.cn.dskmq.cn http://www.morning.wfspn.cn.gov.cn.wfspn.cn http://www.morning.khcpx.cn.gov.cn.khcpx.cn http://www.morning.mjtft.cn.gov.cn.mjtft.cn