当前位置: 首页 > news >正文

wordpress政企网站郴州市北湖建设局网站

wordpress政企网站,郴州市北湖建设局网站,商丘网络,以百度云做网站空间什么是进程替换? 我们的可执行程序,在运行起来的时候就上一个进程 一个进程就会有他的内核数据结构代码和数据 把一个已经成型的进程的代码和数据替换掉,这就叫进程替换 也就是可以通过系统调用把当前进程替换位我们需要的进程 那么替换…

什么是进程替换?

我们的可执行程序,在运行起来的时候就上一个进程

一个进程就会有他的内核数据结构+代码和数据

把一个已经成型的进程的代码和数据替换掉,这就叫进程替换

也就是可以通过系统调用把当前进程替换位我们需要的进程

那么替换后,会创建一个新进程吗?

不会,只是在旧进程的壳子执行新进程;替换进程后,之前的代码不会执行,因为已经被替换了

进程怎样替换?

进程替换是需要接口函数的,总不能什么都没有直接替换吧

来看看都有什么:

上图的【int execl(const char *pfin,“const char *arg, ...);】这种后面的省略号,是指参数可变

来举个栗子捏:

test1.c

#include<stdio.h>
#include<unistd.h>int main()
{printf("test1.c ... begin!\n");execl("/usr/bin/ls", "ls", "-l", "-a", NULL);printf("test1.c ... end!\n");return 0;
}

makefile:

test1.out:test1.cgcc -o $@ $^
.PHONY:clean
clean:rm -f test1.out

解释一下:就是把我们本来的代码通过execl来执行execl引用的程序,成为替换的新进程

替换的过程?

而execl的返回值我们并不关心,因为一旦替换成功,就不会向后继续运行旧进程了

而只要继续运行旧进程,那就一定是替换失败了

所以我们的替换接口函数只有失败返回值,没有成功返回值

替换的过程本质上是把这个新程序加载到内存上

一个程序怎样加载到内存上呢? 

别忘了exec*!它类似一种Linux上的加载函数,做的是从外设拷贝到内存是操作系统的活
 

多进程版的进程替换

将代码改成多进程版就是fork创建子进程,让子进程自己替换,父进程只需要等待就好了

也就是说这里被替换的是子进程捏,父进程还在等待

 test1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main()
{pid_t id = fork();if(id == 0){printf("exec begin\n");//进程替换execl("/usr/bin/ls", "ls", "-al", NULL);printf("exec end\n");exit(0);}int rid = waitpid(id, NULL, WUNTRACED);if(rid > 0){printf("wait success\n");}return 0;
}

makefile:

test1.out:test1.cgcc -o $@ $^
.PHONY:clean
clean:rm -f test1.out

解释一下:我们在if(rid==0)分支里,先打印了一下,然后进入我们的接口,接口里是我们的ls命令,我们ls命令也是文件,也是C语言写的,我们平时执行命令也是执行该程序,所以可以在接口里替换为ls命令

这样就是替换成功了

我们刚刚说了替换失败会继续执行原进程,来看看吧:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{printf("test1.c ... begin!\n");pid_t id = fork();if (id == 0){sleep(2);execl("/usr/bin/lsss", "lsss", "-l", "-a", NULL);printf("替换失败捏");exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){printf("father wait success,child exit code:%d\n",WEXITSTATUS(status));}printf("test1.c ... end!\n");return 0;
}

你看,没执行execl里面的程序

以前创建子进程让它完成任务,是让子进程执行父进程代码的一部分,现如今可以让子进程执行一个全新的程序

进程有对应的数据和代码,创建子进程会有新的地址空间和页表;替换本身就是覆盖,子进程在数据部分进行写时拷贝,当执行新程序的时候新程序也要进行写时拷贝,所以此后父子间几乎完全独立(本来数据和代码是继承父进程的,现在是全新的了)

来仔细介绍一下我们的替换接口函数:

这些函数的前四个字母都是exec,后面跟着的:

 p: 表示自动搜索路径e: 表示自己维护环境变量l:表示采用列表传参v:表示采用数组传参

execl

int execl(const char *path, const char *arg, ...);

l就是list(列表),传参数列表

剩下的...带选项,在命令行中怎样写命令的参数,就怎么写(下图有例子捏)结束时传NULL

路径表明我们想要执行谁后面的选项表示我们想要怎样执行

execv

v是vector的意思,动态数组

int execv(const char *path, char *const argv[]);

前面的参数是路径,后面的参数是指针数组,execl的是可变参数,execv的传参需要传指针数组指针数组是自己写的

 execvp
带p的意思就是用户可以不用传要执行文件的路径(但要传文件名)

char *const argv[] = {"ps", "-ef", NULL};
execvp("ps", argv);

那它是怎么做到的呢?

别忘了p是可以自己搜路径,在环境变量里搜路径

execlp
就是采用列表传参,但是不用输路径

execlp("ps", "ps", "-ef", NULL);
execvpe

execvpe
带e的需要自己组装环境变量

int execvp(const char *file, char *const argv[], char *const envp[]);

以替换  "ls -al" 为例,示例一下剩余接口:

//l代表传参数列表,分成一个个字符串传
execl("/usr/bin/ls", "ls", "-al", NULL);//p表示系统会去PATH环境变量中找
execlp("ls", "ls", "-al", NULL);//v代表传数组,把命令分成字符串,放进字符串数组里,一起传
char* argv[] = {"ls", "-al", NULL};
execv("/usr/bin/ls", argv);

 替换自己写的进程

刚刚我们引用了系统的进程,我们也可以引用我们自己写的程序

下面就来替换段C++代码(文件后缀: .cpp , .cc ,.cxx)

来先写一个自己的程序:

#include<iostream>using namespace std;int main()
{cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;return 0;
}

然后再也一个父进程:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{printf("test1.c ...begin!\n");pid_t id = fork();if (id == 0){sleep(2);execl("./mypragma", "mypragma", NULL);exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){printf("father wait success,child exit code:%d\n", WEXITSTATUS(status));}printf("test1.c ... end!\n");return 0;
}

tips:别忘了makefile默认是从上到下形成可执行程序,所以第一个要是主程序,其他的依赖程序依次往下排哦

.PHONY:all
all:testexec mypragmamypragma:mypragma.ccg++ -o $@ $^ -std=c++11testexec:testexec.cgcc -o $@ $^
.PHONY:clean
clean:rm -f testexec mypragma

来看看:

程序替换并未形成新进程,我们来验证一下:

test1.c:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{printf("test1.c ...begin!\n");pid_t id = fork();if (id == 0){ printf("i am a process,pid:%d\n",getpid());sleep(2);execl("./mypragma", "mypragma", NULL);exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){printf("father wait success,child exit code:%d\n", WEXITSTATUS(status));}printf("test1.c ... end!\n");return 0;
}

mypragma.cpp

#include<iostream>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;int main()
{printf("i am a new process,pid:%d\n",getpid());cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;return 0;
}

看,这两个进程pid是一样的

自己组装环境变量

我们刚刚说环境变量可以自己组装,来引用

看看吧:

test1.c:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>int main()
{printf("test1.c ...begin!\n");pid_t id = fork();if (id == 0){sleep(2);char *const argv[] = { (char*)"mypragma",NULL };char* const envp[] = { (char*)"LIKE=521",(char*)"LOVE=1314",NULL };execvpe("./mypragma", argv, envp);exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){printf("father wait success,child exit code:%d\n", WEXITSTATUS(status));}printf("test1.c ... end!\n");	return 0;
}

mypragma.cpp:

#include<iostream>using namespace std;int main(int argc,char *argv[],char *env[])
{int i = 0;for (; argv[i]; i++){printf("argv[%d]: %s\n", i, argv[i]);}printf("-------------------------------\n");for (i = 0; env[i]; i++){printf("env[%d]: %s\n", i, env[i]);}printf("-------------------------------\n");cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;cout << "hello C++!" << endl;return 0;
}

哦?

父进程本身自己的环境变量,来自于父进程的父进程:bash

你也可以用全新的环境变量,也可以用修改后的环境变量:使用putenv()

往进程加环境变量: putenv() ,程序替换不会替换环境变量,我们可以通过带e的接口函数(例如execpe())设置新的环境变量,这会覆盖原本的环境变量。

用法:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
int main(){char *p;if((p = getenv("USER")))printf("USER =%s\n", p);putenv("USER=test");printf("USER+5s\n", getenv("USER"));}

这些都是:

#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[]);

tips:只有execve是真正的系统调用,其它五个函数最终都调用 execve(execve在man手册第2节,其它函数在man手册第3节)

http://www.yayakq.cn/news/436592/

相关文章:

  • 网站建设创新互联网站性能优化方案
  • 网站后台数据库下载许昌做网站优化
  • 网站开发需要20万免费行情网站大全搜狐网
  • 网站广告做的好的企业案例分析做网络推广怎么收费
  • 专业做网站机构营销类网站设计 要点
  • 重庆网站建设公司费用怎么查网站的icp备案
  • 台州网站公司那里好做网站最小的字体是多少钱
  • 百度高级搜索入口企业网站seo诊断工具
  • 网站怎么收费的如何优化搜索引擎
  • 网站空间和服务器的区别优秀网站设计赏析怎么写
  • 承接网站网站建设wordpress更新翻译
  • 乡镇做电器网站能不能营运千万不要学电子信息工程
  • 软件最全的网站花钱做网站不给部署
  • 全国有名的网站建设公司网推一手单渠道
  • 怎么做公司网站的二维码百度云搜索引擎入口 百度网盘
  • 做配电柜在哪个网站发布信息云匠网可能会遇到哪些问题
  • 心雨在线高端网站建设专业公司注册地址租赁
  • 合肥建设银行招聘网站网站首页的psd怎么做
  • 网站开发的技术可行性公众平台安全助手官网
  • 网站申请qq网站开发与维护介绍
  • 网站怎么添加滤镜功能吗wordpress时尚英文站
  • 网站做好了每年都要续费吗服务器网站部署
  • 武义网站建设软件开发工具也叫什么工具
  • 做行程规划的旅行网站做电子书网站
  • 如何简述网站建设流程wordpress使用自己主页
  • 养生网站设计自贸区网站建设
  • 紫竹桥网站建设dw网页制作作业
  • 公司怎么在百度做网站绍兴seo排名公司
  • 站长之家网页模板现实有有哪里学做网站的
  • asp网站防注入代码 天堂资源帝