都江堰市建设局网站搜索引擎推广试题
- 作者: 五速梦信息网
- 时间: 2026年03月21日 11:19
当前位置: 首页 > news >正文
都江堰市建设局网站,搜索引擎推广试题,建设银行个人查询余额下载,阿里巴巴与慧聪网网站建设对比目录 一、概念 二、使用 1.单进程程序替换 2.多进程程序替换 3.exec接口 4.execle 一、概念 背景 当前进程在运行的时候#xff0c;所执行的代码来自于自己的源文件。使用fork创建子进程后#xff0c;子进程执行的程序中代码内容和父进程是相同的#xff0c;如果子进…目录 一、概念 二、使用 1.单进程程序替换 2.多进程程序替换 3.exec接口 4.execle 一、概念 背景 当前进程在运行的时候所执行的代码来自于自己的源文件。使用fork创建子进程后子进程执行的程序中代码内容和父进程是相同的如果子进程想要执行其他程序的代码呢 概念 子进程通过调用一类exec接口来执行另一个程序这种操作称为程序替换。 原理 如下是一个进程的信息蓝图。 现在这个进程想要执行其他程序。 调用exec这类函数所做的工作就是将其他程序的代码和数据覆盖式的写入到之前这个程序代码和数据的物理内存空间中也可能开辟新的空间用来存储或许还会修改页表的映射关系总之这个操作的结果就是发生替换后CPU在执行这个进程的时候代码和数据已经是其他程序的。 程序替换而不是进程替换 程序替换过程中只是将程序的代码和数据做了替换并不是替换进程所以这个过程并没有创建新的进程进程的PID不会发生变化。 二、使用 程序替换过程需要从外设加载数据到内存因此程序替换这个工作一定是由操作系统来执行的所以程序替换必然会使用系统调用先介绍一下相关的接口函数。 查看man手册发现有6个接口是语言函数。 man execl EXEC(3) Linux Programmers Manual NAMEexecl, execlp, execle, execv, execvp, execvpe - execute a fileSYNOPSIS#include unistd.hextern char **environ;int execl(const char *pathname, const char arg, …/ (char *) NULL */);int execlp(const char *file, const char arg, …/ (char *) NULL */);int execle(const char *pathname, const char arg, …/, (char *) NULL, char *const envp[] */);int execv(const char *pathname, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[],char *const envp[]);在man手册中查找系统调用发现还有一个接口是系统调用。 man execve EXECVE(2) Linux Programmers Manual NAMEexecve - execute programSYNOPSIS#include unistd.hint execve(const char *pathname, char *const argv[],char *const envp[]);1.单进程程序替换 以这个函数举例 int execl(const char *pathname, const char *arg, … (char *) NULL); //第一个参数是待执行程序的路径 //第二个参数是const char * arg //第三个参数是···即可变参数 //第二个参数和第三个参数不止一个是程序的执行选项传参方式类似于命令行传参 //比如指令 ls -a -l -n //传参为 ls,-a,-l,-n //注意参数最终以NULL结尾不是NULL 编写源文件如下。 #include stdio.h #include unistd.h #include sys/types.h #include stdlib.hint main() {printf(exec Before\n);execl(/usr/bin/ls,ls,-l,-a,-n,NULL);printf(exec End\n);return 0; } exec Before 总计 36 drwxrwxr-x 2 1000 1000 4096 10月 9 16:30 . drwxrwxr-x 13 1000 1000 4096 10月 9 10:23 .. -rw-rw-r– 1 1000 1000 85 10月 9 10:23 Makefile -rwxrwxr-x 1 1000 1000 17224 10月 9 16:30 myprocess -rw-rw-r– 1 1000 1000 207 10月 9 16:15 myprocess.c疑问程序中最后一行没有打印原因是什么? 调用exec类函数完成程序替换后当前程序的剩余代码都不会再被执行因为此时执行的代码已经是另外一个程序的。 关于exec这类函数的返回值 程序替换成功则没有返回值转而执行另外的程序。只有程序替换失败时才会返回-1并且设置错误码如此调用exec函数后可以直接加一行退出程序的代码因为程序替换失败时当前程序的运行必然不合预期。 RETURN VALUEThe exec() functions return only if an error has occurred. The return value is -1, and errno is set to indicate the error. execl(/usr/bin/ls,ls,-l,-a,-n,NULL); exit(1);验证程序替换不会创建新进程 编写代码如下 utocooutocoo-virtual-machine:/Desktop/linux/241009\( ll 总计 16 drwxrwxr-x 2 utocoo utocoo 4096 10月 10 10:21 ./ drwxrwxr-x 13 utocoo utocoo 4096 10月 9 10:23 ../ -rw-rw-r-- 1 utocoo utocoo 85 10月 9 10:23 Makefile -rw-rw-r-- 1 utocoo utocoo 259 10月 10 10:21 myprocess.c//myprocess.c #include stdio.h #include unistd.h #include sys/types.h #include stdlib.hint main() {printf(exec Before\n);printf(I am process,PID:%d\n,getpid());sleep(5);execl(/usr/bin/top,top,NULL);exit(1);printf(exec End\n);return 0; } 执行如下这条指令在监视窗口观察PID。 while :; do ps ajx | head -1 ps ajx | grep myprocess | grep -v grep;sleep 1; done编译运行可执行程序myprocess监视窗口打印结果如下。 PPID PID PGID SID TTY TPGID STAT UID TIME COMMANDPPID PID PGID SID TTY TPGID STAT UID TIME COMMANDPPID PID PGID SID TTY TPGID STAT UID TIME COMMAND2295 3476 3476 2295 pts/0 3476 S 1000 0:00 ./myprocessPPID PID PGID SID TTY TPGID STAT UID TIME COMMAND2295 3476 3476 2295 pts/0 3476 S 1000 0:00 ./myprocessPPID PID PGID SID TTY TPGID STAT UID TIME COMMAND2295 3476 3476 2295 pts/0 3476 S 1000 0:00 ./myprocessPPID PID PGID SID TTY TPGID STAT UID TIME COMMAND2295 3476 3476 2295 pts/0 3476 S 1000 0:00 ./myprocessPPID PID PGID SID TTY TPGID STAT UID TIME COMMANDPPID PID PGID SID TTY TPGID STAT UID TIME COMMANDPPID PID PGID SID TTY TPGID STAT UID TIME COMMANDPID为3476但是在程序替换后捕捉不到PID了原因是可执行程序的名字发生了变化执行这条语句再来对比PID。 while :; do ps ajx | head -1 ps ajx | grep top | grep -v grep;sleep 1; donePPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 2295 3476 3476 2295 pts/0 3476 S 1000 0:00 top结果符合预期PID并未发生变化即没有创建新的进程。 创建一个进程时先创建PCB、进程地址空间、页表等内容再将磁盘中的代码和数据加载到内存中。 程序替换时由于并不需要创建新的进程所以只需要将新的程序代码和数据加载到内存中即可。于是更进一步理解操作系统在将程序的代码和数据加载到内存中时是通过程序替换完成的。 2.多进程程序替换 操作举例 编写代码如下。 int main() {pid_t id fork();if(id 0){printf(exec Before\n);printf(I am child process,PID:%d\n,getpid());sleep(3);execl(/usr/bin/ls,ls,-l,NULL);exit(1);printf(exec End\n);}sleep(1);pid_t rid waitpid(id,NULL,0);if(rid0){printf(wait success!\n);}return 0;}程序替换的场景更多的是创建子进程作程序替换原因很简单父进程可以获取到程序替换的结果。 当子进程作程序替换时此时子进程共享的还是父进程的代码数据因此发生写时拷贝不仅仅是数据发生改变代码也会发生变化。 Shell是如何运行指令的 指令即一个程序Shell正在运行时输入指令后创建一个子进程Shell等待子进程waitpid子进程此时共享Shell的代码子进程作程序替换替换的目标程序就是输入的指令执行完毕同时Shell也能获取到子进程的执行结果。 3.exec接口 前面已经说明了exec类接口中语言函数6个而系统调用只有一个不难总结出来函数内部都是封装了系统调用的。 这些接口的功能大致类似都是完成程序替换只是用法传参有所差异。 先来介绍一下6个接口函数。 int execl(const char *pathname, const char *arg, .../* (char *) NULL */); int execlp(const char *file, const char *arg, .../* (char *) NULL */); int execle(const char *pathname, const char *arg, .../*, (char *) NULL, char *const envp[] */); int execv(const char *pathname, char *const argv[]); int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[],char *const envp[]); 它们都以exec*开头只是后缀有所区别有l 、p、e、v。 在介绍函数用法之前先来区分它们后缀因为不同的后缀就表示了它们不同的用法。 l(list) : 表示参数采用列表 v(vector) : 参数用数组 p(path) : 有p自动搜索环境变量PATH e(env) : 表示自己维护环境变量 你可能对这些后缀的意义不明所以下面来看用法。 execlp int execlp(const char *file, const char *arg, ... /* (char *) NULL */); 这个函数包含两个后缀l、p。 包含p说明带环境变量在程序替换时目标程序可以只给出名字不用给出全部路径因为环境变量已经包含了一部分比如系统的指令。 list则说明需要列表式的传参。 execlp(ls,ls,-l,-a,NULL);值得一提的是前两个参数一模一样但是并不冲突二者的意义不一样第一个参数表示目标程序第二个参数不止一个表示执行目标程序的方式其他参数-l、-a含义上也是第二个参数。 execv int execv(const char *pathname, char *const argv[]); 关于argv这个指针数组这一文中Linux环境变量介绍main函数的参数时也提到了。这个数组的元素是一个个的指针每一个指针指向一个字符串这些字符串其实就是原来使用execl传参时的字符串。 char* const argv[]{(char*)ls,(char*)-l,(char*)-a,NULL}; execv(/usr/bin/ls,argv);execvp int execvp(const char *file, char *const argv[]); execvp(ls,argv); 4.execle int execle(const char *pathname, const char *arg, ... /*, (char *) NULL, char *const envp[] */); 在介绍这个函数用法之前要给出一个结论exec*类函数可以替换系统的指令也可以替换任何程序比如cpp、python、java程序。C程序的源文件后缀有.cc、.cpp、.cxx 即程序替换可能发生的情况使用C语言程序运行的进程创建子进程后子进程程序可能被替换为Java程序等等类似的情况从这一层面看程序替换的意义重大 发生上面所述情况的原因只有一个就是无论是何种语言编写的程序在运行之后都是由操作系统统一管理的进程 在替换这一层只有被区分为代码和数据的二进程内容没有语言的差异因此替换只是二进制文本被替换。 使用Makefile文件时由于make指令只生成第一个可执行程序因此想要一次编译链接多个源文件可以使用下面这样的方式。 .PHONY:all all:mytest myprocessmytest:mytest.ccg -o \) \(^ -g -stdc11 myprocess:myprocess.cgcc -o \) $^ -g -stdc99 .PHONY:clean clean:rm -f myprocess在 Linux环境变量一文中总结出环境变量可以被子进程继承环境变量具备了全局属性。 现在将这些联系起来操作系统启动Bash程序等待命令行输入命令行输入指令Bash将输入的指令字符串作为exec函数的参数然后子进程作程序替换这些参数传给了目标程序的main函数。 但是环境变量并不是通过传参这样的方式传递的。 编写代码如下子进程程序被替换为由mytest.cc生成的C程序在mytest.cc中打印环境变量得到结果符合预期。但是在替换程序时调用exec函数时并没有传环境变量的参数。 //myprocess.c程序替换时没有传环境变量的参数 execl(./mytest,mytest,NULL);//mytest.cc打印环境变量 #include iostream #include unistd.h using namespace std; int main() {for(int i 0;environ[i];i){cout environ[ i ] : environ[i] endl;}return 0; }//打印结果是有环境变量的 exec Before I am process,PID:2819 environ[0]:SHELL/bin/bash environ[1]:SESSION_MANAGERlocal/utocoo-virtual-machine:/tmp/.ICE-unix/1578,unix/utocoo-virtual-machine:/tmp/.ICE-unix/1578 environ[2]:QT_ACCESSIBILITY1 environ[3]:COLORTERMtruecolor ······ 在Linux地址分区一文中我有写到命令行参数、环境变量在虚拟地址空间中的大致位置。 一个进程的PCB信息包含着虚拟地址空间、页表等内容。当子进程由父进程创建后子进程有着自己的PCB、虚拟地址空间等而程序替换不会将物理内存中的环境变量数据替换因此子进程是通过继承虚拟地址空间的方式继承全局环境变量。 拥有自己的环境变量 当前进程myprocess想要拥有一个自己的环境变量可以用函数putenv来实现这个环境变量会被myprocess的子进程继承但是它的父进程bash则不包含这个环境变量。 在myprocess.c的源文件中添加下面一行代码用来导出环境变量。 putenv(NewENV~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~);在命令行中查看是否有环境变量NewENV打印结果说明bashmyprocess的父进程没有这个环境变量。 utocooutocoo-virtual-machine:/Desktop/linux/241009\( echo \)NewEnvutocooutocoo-virtual-machine:/Desktop/linux/241009$ 运行myprocess后做程序替换操作打印环境变量发现子进程会继承环境变量。 ······ environ[53]:LC_NUMERICzhCN.UTF-8 environ[54]:./myprocess environ[55]:OLDPWD/home/utocoo/Desktop/linux environ[56]:NewENV~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~新增环境变量会被子进程继承但不影响父进程的环境变量。 现在我们清楚的知道每一个进程的环境变量都会继承于父进程如果现在要求新建的一个子进程拥有全新的环境变量不继承父进程的环境变量要如何做呢 使用带e的exec接口。 编写代码如下。 //myprocess.c int main() {printf(I am process,PID:%d\n,getpid());sleep(3);char const env[]{(char)112,(char)223,NULL};pid_t id fork();if(id 0){printf(exec Before\n);execle(./mytest,mytest,NULL,env);exit(1);printf(exec End\n);}pid_t rid waitpid(id,NULL,0);return 0; }程序运行结果如下结果显示子进程没有继承父进程的环境变量。 utocooutocoo-virtual-machine:/Desktop/linux/241009$ ./myprocess I am process,PID:3353 exec Before environ[0]:112 environ[1]:223这就是带e的exec接口的使用场景。
- 上一篇: 洞泾做网站网站建设方案行业
- 下一篇: 都有哪些网站可以做推广山东省和住房建设厅网站首页
相关文章
-
洞泾做网站网站建设方案行业
洞泾做网站网站建设方案行业
- 技术栈
- 2026年03月21日
-
动易医院网站管理系统乌兰察布盟建设银行网站
动易医院网站管理系统乌兰察布盟建设银行网站
- 技术栈
- 2026年03月21日
-
动易学校网站上海网站建设 虹口
动易学校网站上海网站建设 虹口
- 技术栈
- 2026年03月21日
-
都有哪些网站可以做推广山东省和住房建设厅网站首页
都有哪些网站可以做推广山东省和住房建设厅网站首页
- 技术栈
- 2026年03月21日
-
都匀网站建设公司网站备案号收回
都匀网站建设公司网站备案号收回
- 技术栈
- 2026年03月21日
-
抖音网站开发编写这个网站模板要多少钱
抖音网站开发编写这个网站模板要多少钱
- 技术栈
- 2026年03月21日






