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

怎样建网站买东西深圳网站建设知了网络

怎样建网站买东西,深圳网站建设知了网络,免费域名申请方法,微信营销手机网站模板#x1f3ac; 个人主页#xff1a;谁在夜里看海. #x1f4d6; 个人专栏#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出#xff0c;万山无阻 目录 #x1f4d6;一、进程程序替换 1.替换的演示 ❓替换与执行流 ❓程序替换≠进程替换 2.替换的原理 … 个人主页谁在夜里看海. 个人专栏《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出万山无阻 目录 一、进程程序替换 1.替换的演示 ❓替换与执行流 ❓程序替换≠进程替换 2.替换的原理 系统调用exec 进程控制块 (PCB) 内存管理 3. 替换的函数 execl execv execp exece 本质  二、命令行解释器shell 1.shell的本质 2.shell的模拟实现 头文件 宏定义 全局变量 获取信息 交互式命令行输入 字符串分割 内置命令 普通命令 main函数 一、进程程序替换 上一篇博客我们讲到了进程的诞生过程父进程调用fork创建子进程子进程执行父进程相同的程序。但是很多时候我们希望子进程执行另一个程序此时就要用到exec函数调用子进程中调用exec函数之后该程序就会被调用的程序代替这就是程序替换 1.替换的演示 #includestdio.h #includeunistd.h int main() {int a 0;a;execl(/usr/bin/pwd, pwd, NULL);printf(%d\n, a); } 此时程序执行结果 我们可以看到原先的程序执行结果应该是打印变量a但是被替换成了pwd指令指令本身也是一个可执行程序这就是程序替换的过程当进程调用exec函数时该进程的代码和数据完全被新程序替换从新程序的启动例程开始执行。 ❓替换与执行流 int main() {int a 0;printf(Before: %d\n,a);execl(/usr/bin/pwd, pwd, NULL);printf(After: %d\n, a); }不对呢不是说程序替换之后原来的代码和数据都会被替换吗那为什么这里还会显示原程序的打印信息呢下面进行分析 ✅虽然进程调用exec函数后会发生程序替换原程序的代码和数据会被覆盖但在调用 exec 函数之前执行流还是要经过原来的步骤的上述代码中在调用execl之前执行流先执行printf函数代码由于以“\n”结尾输出缓冲区的数据会被刷新到终端所以我们能看到“Before: 0” 修改一下代码结尾不加“\n” 此时数据会被保留在输出缓冲区当中后面又因为发生程序替换缓冲区的内容被清除了所以最终终端不会显示Before: 0内容 int main() {int a 0;printf(Before: %d,a);execl(/usr/bin/pwd, pwd, NULL);printf(After: %d\n, a); }❓程序替换≠进程替换 程序替换会改变进程的执行内容但它不会改变进程的进程ID也就是说进程还是原来的进程程序替换并不是进程替换且看下面示例 先写一个可执行程序test2源代码为 #includestdio.h #includeunistd.hint main() {// 打印当前pidppidprintf(After: pid %d, ppid %d\n,getpid(),getppid()); } 另一个可执行程序test源代码为 #includestdio.h #includeunistd.hint main() {// \n结尾直接打印当前内容printf(Before: pid %d, ppid %d\n,getpid(),getppid());// 程序替换成test2execl(/home/ywh/linux_gitee/test_excel/test2, test2, NULL); }test执行结果 我们可以看到程序替换前后都是同一个进程结论exec并不创建新进程。 2.替换的原理 系统调用exec exec 系列函数如 execl, execv, execve 等是用来将当前进程的内存空间、程序代码段、数据段等替换成一个新的程序。该系统调用不会创建新进程而是直接用新程序替换当前进程的内容。 具体来说exec 调用会 ①清空当前进程的代码段、数据段、堆栈等。 ②加载并执行新程序的代码段、数据段、堆栈等。 ③保留当前进程的进程 ID (PID)、父进程标识符 (PPID)、文件描述符等。 进程控制块 (PCB) 操作系统通过 进程控制块 (PCB) 来管理进程每个进程都有一个独立的 PCB包含了进程的各种状态信息比如进程的 PID、父进程 ID、程序计数器、堆栈指针等。 当调用 exec 时进程的 PCB 中的状态信息并没有被改变操作系统只会根据 exec 调用的参数加载新的程序内容代码段、数据段等并且更新程序计数器和堆栈指针等信息。 内存管理 操作系统中的内存管理模块负责为进程分配内存。当进程调用 exec 时操作系统会 ①释放原进程的内存代码段、数据段、堆栈。 ②加载新程序的内存从磁盘例如 ELF 文件或其他可执行文件中加载新的程序到内存包括新的代码段、数据段等。 ③更新堆栈和堆的布局准备新程序的运行环境。 3. 替换的函数 其实有六种以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[]); 为了便于理解我们可以把exec后面出现的 l、p、e、v 看作exec的四个选项下面我们依次介绍这些选项 execl l(list) : 参数采用列表  path表示要执行的程序路径 arg表示程序本身的参数第一个是程序本身的名称后续为程序的参数传递系统指令时参数就是指令的选项必须以NULL结尾。 示例 execl(/bin/ls, ls, -l, (char *)NULL);execv v(vector) : 参数用数组 path表示要执行的程序路径 argv参数列表程序的参数以数组的形式传递数组内部也必须以NULL结尾。 示例 execv(/bin/ls, (char *[]){ls, -l, NULL});execp p(path) : 自动搜索环境变量PATH 它可以通过环境变量 PATH 来查找可执行文件而不需要提供绝对路径。 示例 execlp(ls, ls, -l, (char *)NULL);exece e(env) : 表示自己维护环境变量  execle 允许显式地传递一个 环境变量数组而不是继承当前进程的环境变量。通过 execle你可以自定义新进程的环境变量。 示例 char *const envp[] {PATH/bin:/usr/bin, TERMconsole, NULL}; execle(ps, ps, -ef, NULL, envp); 本质  事实上只有execve才是真正的系统调用而其他四个函数最后都会调用execve 二、命令行解释器shell 我们在linux学习过程中离不开shellshell是命令行解释工具是用户与内核之间的工具提供了一个接口通过它我们可以执行命令、启动程序等与操作系统进行交互。shell解析用户输入的命令返回执行结果。 ❓shell的本质是什么呢 1.shell的本质 ✅shell本质其实是一个进程 当我们启动一个终端或打开一个命令行窗口的时候相当于启动了一个shell进程也叫bash进程这个进程会等待用户输入的命令并将命令通过系统调用传递给内核内核执行相应的操作后返回给shell。 shell的工作原理就是循环以下操作 1️⃣获取命令行 -- 2️⃣解析命令行 -- 3️⃣fork创建子进程  -- 4️⃣execve替换子进程 -- 5️⃣wait等待子进程退出 -1️⃣ 根据这些思路我们可以模拟实现一个shell 2.shell的模拟实现 实现一个简化版的shell需要执行以下功能 ① 获取当前工作目录、用户名、主机名。 ② 解析用户输入的命令行并执行命令。 ③ 内置支持一些常见命令如cd、echo、export等。 ④ 创建子进程来执行普通命令并支持基本的命令分割和管道处理。 头文件 #include stdio.h #include stdlib.h #include string.h #include assert.h #include unistd.h #include sys/types.h #include sys/wait.h这些头文件提供了标准输入输出、字符串处理、系统调用等功能。unistd包含与进程相关的函数如forkexit 宏定义 #define LEFT [ #define RIGHT ] #define LABLE # #define DELIM \t #define LINE_SIZE 1024 #define ARGC_SIZE 32 #define EXIT_CODE 44 LEFT、RIGHT、LABLE用于命令行提示符的格式化 DELIM用于命令行字符串的分隔符 LINE_SIZE、ARGC_SIZE定义了命令行和参数的缓冲区大小 EXIT_CODE用于子进程异常退出的返回值。 全局变量 int lastcode 0; int quit 0; extern char **environ; char commandline[LINE_SIZE]; char *argv[ARGC_SIZE]; char pwd[LINE_SIZE]; char myenv[LINE_SIZE];lastcode保存上一个命令的退出码 quit用于控制shell是否退出 commandline存储用户输入的命令行字符串 argv存储解析后的命令和参数 pwd保存当前工作目录 myenv存储自定义的环境变量。 获取信息 const char *getusername() {return getenv(USER); }const char *gethostname() {return getenv(HOSTNAME); }void getpwd() {getcwd(pwd, sizeof(pwd)); }getusername获取用户名 gethostname获取主机名 getpwd获取当前工作目录 交互式命令行输入 void interact(char *cline, int size) {getpwd();printf(LEFT%s%s %sRIGHTLABLE , getusername(), gethostname(), pwd);char *s fgets(cline, size, stdin);assert(s);(void)s;cline[strlen(cline)-1] \0; }interact函数显示格式化的提示符并等待用户输入命令。输入命令存储在cline中输入的命令符末行换行符替换成终止符 \0。 字符串分割 int splitstring(char cline[], char *_argv[]) {int i 0;argv[i] strtok(cline, DELIM);while(_argv[i] strtok(NULL, DELIM));return i - 1; }splitstring函数使用strtok将输入的命令行字符串按空格和制表符分割成多个命令或参数存储在指针数组argv中。 内置命令 int buildCommand(char *_argv[], int _argc) {if(_argc 2 strcmp(_argv[0], cd) 0) {chdir(argv[1]);getpwd();sprintf(getenv(PWD), %s, pwd);return 1;}else if(_argc 2 strcmp(_argv[0], export) 0) {strcpy(myenv, _argv[1]);putenv(myenv);return 1;}else if(_argc 2 strcmp(_argv[0], echo) 0) {if(strcmp(_argv[1], $?) 0) {printf(%d\n, lastcode);lastcode0;}else if(*_argv[1] $) {char *val getenv(_argv[1]1);if(val) printf(%s\n, val);}else {printf(%s\n, _argv[1]);}return 1;}if(strcmp(_argv[0], ls) 0) {_argv[_argc] --color;_argv[_argc] NULL;}return 0; }提供了几个内置命令 cd改变当前目录 export设置一个新的环境变量 enho打印变量值或退出码 普通命令 队友普通命令的执行需要调用exec程序替换成目标命令的程序 void NormalExcute(char *_argv[]) {pid_t id fork();if(id 0) {perror(fork);return;}else if(id 0) {execvp(_argv[0], _argv);exit(EXIT_CODE);}else {int status 0;pid_t rid waitpid(id, status, 0);if(rid id) {lastcode WEXITSTATUS(status);}} }NormalExcute使用fork创建子进程子进程调用execvp替换当前程序父进程等待子进程结束。 main函数 int main() {while(!quit) {interact(commandline, sizeof(commandline));int argc splitstring(commandline, argv);if(argc 0) continue;int n buildCommand(argv, argc);if(!n) NormalExcute(argv);}return 0; }main函数进入循环不断接收用户输入的命令并解析执行。 如果命令是内置命令则在当前进程中执行如果是普通命令通过程序替换在子进程中执行。 以上就是【剧幕中的灵魂更迭探索Shell下的程序替换】的全部内容欢迎指正~   码文不易还请多多关注支持这是我持续创作的最大动力
http://www.pierceye.com/news/884357/

相关文章:

  • 网站开发需要的编程软件有哪些海门住房和城乡建设局网站
  • 南宁上林网站建设交换链接是什么
  • 什么网站做简历好api模式网站开发
  • 网站建设与管理专业好吗网络推广seo培训班
  • 常用网站架构辽宁建设工程信息网审计报告
  • 绿色大气网站模板坪山网站建设公司
  • 网站建设动态wordpress禁止自动升级
  • 网站建设网站建设平台网站建设费计入什么科目比较好
  • 豪圣建设项目管理网站公司网站设计与管理
  • 网站开发很难么交互网站图
  • 做网站用什么语音网站开发绪论
  • 中国建设银行徐州分行网站网站如何做视频教程
  • 烟台建站服务荥阳市建设局 网站
  • 网站备案登记推广网站案例
  • 企业网站设计论文摘要怎么写网络广告是什么意思
  • 自建站服务快应用 小程序
  • 上海网站建设过程邯郸网站建设推荐咨询
  • 公司有网站域名 如何做网站wordpress 字段
  • 做网站的类型东莞网页设计制作公司
  • 有品质的网站推广公司网站建设彩铃语
  • wordpress提示更新网站页面seo
  • 建设全国科技中心网站郑州百姓网官网
  • 漂亮网站wordpress 文章统计
  • 广西建设厅培训中心兰州seo网站排名
  • 布吉医院网站建设鞍山市网络销售平台
  • 开发一个网站系统报价wordpress文章摘要
  • 做脚本从网站引流外贸网站建设不可缺少的灵活性
  • 网站开发用linux好吗网站公司网站搭建
  • 网站数据库如何导入全自动引流推广软件app
  • 企业微网站案例响应式模板