您的位置:首页 > 文旅 > 美景 > 云服务器租用价格表_网站一般多少钱一年_站内推广的方法_百度竞价推广联系方式

云服务器租用价格表_网站一般多少钱一年_站内推广的方法_百度竞价推广联系方式

2025/2/23 20:46:39 来源:https://blog.csdn.net/2301_79499548/article/details/143081678  浏览:    关键词:云服务器租用价格表_网站一般多少钱一年_站内推广的方法_百度竞价推广联系方式
云服务器租用价格表_网站一般多少钱一年_站内推广的方法_百度竞价推广联系方式




在这里插入图片描述



相关知识储备:

exec系列函数详细介绍:【Linux】exec系列函数详细介绍-CSDN博客




        进程程序替换(Process Replacement)是指在操作系统中,一个进程可以用另一个程序来替换其当前正在执行的程序。这一操作通常发生在进程执行 exec 系列函数时,如 execl, execv, execle, execlp, execvp 等。当一个进程调用 exec 函数时,它将用新的程序替换掉当前进程的正文段,但不改变进程的标识符(PID)和其他资源(如打开的文件描述符)。


一、进程程序替换的过程与原理


  1. 调用 exec 系列函数
    • 进程调用 exec 函数,该函数会用新的程序替换当前进程的程序映像。这意味着当前进程的代码段、数据段、堆和栈都会被新的程序占用的空间所替换。原有的程序指令和数据不再存在于进程的地址空间内。
  2. 替换正文段
    • 操作系统加载新程序的正文段,并准备执行新程序的入口点。
  3. 保持资源不变
    • 进程的标识符(PID)保持不变。
    • 进程的用户标识符(UID)和组标识符(GID)保持不变。
    • 打开的文件描述符(如标准输入、输出和错误)保持不变。
    • 进程的工作目录(cwd)和环境变量(environ)等属性保持不变。
  4. 执行新程序
    • 新程序开始执行,从其 main 函数开始运行。


二、进程程序替换 图解说明

下面是一个简单的"文字"图解来说明进程程序替换的过程:

--------------------------------------
|                                     
|       原始进程 A                    
|                                     
|   PID: 1234                        
|   程序: /bin/echo                  
|   参数: "Hello World"              
|                                     
|   文件描述符:                      
|   stdin, stdout, stderr            
|                                    
|   工作目录: /home/user                     
|   环境变量表: environ[]   
|    
-------------------------------------exec("/bin/cat")     :  进程 A 调用 exec("/bin/cat") 函数,请求用新程序/bin/cat 替换当前进程正文段
--------------------------------------
|                                     
|       替换后的新进程 B              
|                                    
|   PID: 1234 (保持不变)              
|   程序: /bin/cat                    
|                                     
|   文件描述符:                      
|   stdin, stdout, stderr (保持不变) 
|                                     
|   工作目录: /home/user (保持不变)   
|   环境变量表: environ[] (保持不变)  
|                                      
--------------------------------------该程序将从 新程序 /bin/cat 的 main 函数开始运行开始执行


三、示例代码

下面的 C 语言程序,展示如何使用 exec 函数替换新程序进来:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main() {// 使用 execlp 调用 /bin/echoexeclp("/bin/echo", "echo", "Hello", "World", (char *)NULL);// 如果执行到这里,说明 execlp 调用失败if (errno == ENOENT) {fprintf(stderr, "Executable not found.\n");} else {perror("Error executing command");}return EXIT_FAILURE;
}

在这个示例中,当前进程使用 execlp 函数,通过路径 /bin/echo ,找到对应可执行文件 /bin/echo ,替换原进程的正文段,并传递参数 "Hello""World"echo 命令。

新程序会将原进程中的正文段的程序全部替换,因此如果 execlp 调用成功,上面的 C 语言程序中的 if/else 肯定不会执行;否则 如果 execlp 调用失败,程序将执行 if/else 输出错误信息。



四、小结

        进程程序替换是操作系统中的一项重要功能,它允许进程动态地用另一个程序替换当前正在执行的程序,同时保留重要的资源和属性。这一机制广泛应用于 shell 脚本、守护进程和其他需要动态执行不同程序的场景



五、✨进程程序替换的应用:命令行解释器 shell 的运行原理✨


1、命令行解释器 shell 会创建子进程执行命令


这是最常见的做法,尤其是在命令行解释器如Bash中。
(还有一种不常见的做法:直接替换shell本身,这里暂不解释)

具体步骤如下:

  1. 读取输入:命令行解释器 shell 读取用户输入的命令。(在你的Linux终端上输入命令被获取)
  2. 解析命令:解释器解析命令,提取命令名和参数。
  3. 创建子进程:使用 fork() 系统调用来创建一个子进程。
  4. 子进程执行命令:子进程调用exec系列函数(如execve)来执行命令。
  5. 父进程等待子进程结束:父进程通过waitwaitpid等待子进程的完成,并收集其退出状态。
  6. 返回提示符:命令执行完毕后,命令行解释器返回提示符,等待下一个命令。


看完运行步骤你是不是明白了程序替换 exec 函数的巨大用途,我们平时在Linux系统的命令行窗口或图形化界面,输入的命令或启动的应用程序,其实基本都是 shell 这个父进程创建一个子进程通过 exec 程序替换来执行用户输入的命令。

在Linux系统中,大多数程序都是通过fork()创建子进程,然后在子进程中使用exec()系列函数来执行新程序的!!



2、fork + exec 的程序运行模式的优点:


  1. 资源隔离:子进程与父进程共享相同的资源(如文件描述符),但也有自己的独立资源(如内存空间),这有助于隔离和保护父进程不受子进程的影响。

  2. 保持解释器运行:父进程可以继续运行,等待下一个命令,而子进程则专门用来执行当前命令,保证命令行解释器的持续运行。

  3. 错误隔离:如果子进程出现错误或异常,只会影响子进程本身,而不会影响到父进程

    (用于执行某可执行程序的子进程因为该可执行程序有问题,就不会影响到父进程(即命令行解释器shell))。

  4. 并发执行:使用子进程可以更容易地支持并发执行多个命令。



3、命令行解释器 shell 是如何实现在一个shell进程中不断 fork + exec 来执行多条程序?


实际上,命令行解释器(如Shell)通常通过一个无限循环来不断读取用户输入的命令,并通过fork()和exec()来执行这些命令。


这是一段命令行解释器的工作步骤,本身就是通过死循环实现不断读取命令+运行的

int main()
{while(1){// 1、形成并打印命令行提示符// 2、获取用户输入命令// 3、解析用户输入命令// 4、执行用户输入命令}
}


如果你理解了上面的程序替换,理解了命令行解释器工作原理,就大概可以自己实现一个简易的 shell,这是我实现的,感兴趣可以看一下:【Linux】自制简易shell的实现日志-CSDN博客



4、命令行解释器 运行图解(清晰明了)


        用下图的时间轴来表示事件的发生次序。其中时间从左向右。命令行解释器 `shell ` 由标识为 `bash ` 的方块代表,它随着时间的流逝从左向右移动。shell从用户读入字符串"ls"。`shell` `fork` 建立一个新的进程,在那个进程中运行 `ls` 程序并等待那个进程结束。 接着 `shell` 读取新的一行输入,建立一个新的进程,运行并等待新进程 `ps`

在这里插入图片描述

就这样循环往复的进行,命令获取–>命令解释–>fork+exec 创建替换并运行子进程–>等待子进程退出



【证明】程序替换不会创建新进程


进程替换不等于创建新进程,进程 = 该进程的PCB+代码数据

使用exec系列函数时,当前进程的内容(代码段和数据段)被新程序的内容替换,但进程标识符(PID)和大部分资源(如打开的文件描述符、环境变量等)保持不变。

这些操作本质上不创建新的PCB,复用当前进程的PCB
(一个进程只有代码数据改变,PCB大体不变,则不构成新的进程)



我们以一个例子证明

使用另一个程序 test.c 替换 code.c 程序,两者代码中的 printf 都会打印的 pid ,最终结果:两条 printf 打印的 pid 一样

这证明了程序替换没有创建新进程 (每个进程有其唯一的 pid,pid 不变表示进程不变)


在这里插入图片描述

运行结果
在这里插入图片描述


【证明】自己 exec 替换自己会死循环(死递归?🤣)


#include<stdio.h>
#include<unistd.h>int main(int argc, char* argv[]){printf("我是code.exe程序, pid: %d\n", getpid());execl("./code", "code", NULL);  // 指定路径: ./code return 0;
}

在这里插入图片描述


版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com