Linux进程地址空间第三讲

在这里插入图片描述
至今为止, 我们所学到的大多数的知识, 包括语言, 数据结构, 动静态库等等的 都是在下面这3G, 也就是用户空间里的(进程等待, 信号之类的与内核有关的是在上面那1G里的)

所以对于我们来说, 我们并没有怎么接触上面的这些部分。

上面这部分(1G)映射的是操作系统的代码和数据

用户级页表和内核级页表

用户空间通过用户级页表映射到自己的代码和数据, 而内核空间通过内核级页表映射到操作系统的代码和数据

对于每一个进程 每个进程都需要有自己的用户级页表, 而内核级页表只有1份所以, 每一个进程的内核级空间对应的数据是一样的, 所以进程在切换的时候内核空间的内容其实是不变的

在这里插入图片描述
解释一下第三句话, 第三句话的意思就是 操作系统如果想执行自己的代码, 可以通过进程的PCB找到进程的地址空间然后执行对应的代码, 因为操作系统中一定有正在运行的进程。

操作系统的本质: 是一个基于时钟中断的一个死循环。

操作系统中有一个时钟芯片, 他会每隔很短很短的时间向计算机发送时钟中断, 而一旦被CPU接受到, 就会根据中断向量表去执行对应的方法, 这个方法就可能是操作系统中的某个方法。

举个例子:

我们CPU在调度进程的时候, 如果此时接收到了时钟中断, 就会将该进程剥离下来, 接着执行下一个进程。

用户态和内核态

CPU里面有一个CR3寄存器, 它里面存放的是用户级页表的地址(物理地址)
在这里插入图片描述
CPU里面还有一个寄存器ecs 他的低两位表示CPU当前的工作模式
在这里插入图片描述
其中 00 表示内核态 11 表示用户态

所以我们来个总结
内核态: 允许你访问操作系统的代码和数据
用户态: 只能访问你自己的代码和数据
我们在调用系统调用的时候, 我们的操作系统会吧ecs的低2位设为00, 然后在仅此地址空间里的内核空间找到对应的代码然后执行就可以了。

信号的检测和处理的流程图

在这里插入图片描述

在这里插入图片描述

那么我们就有个问题, 如何我们的代码全是自己写的内容, 没有系统调用呢? 此时怎么进行信号的检测和处理呢?

由于我们的进程是在被不断的调度的, 当我们的进程被调度的时候, 操作系统会把进程的PCB 地址空间, 页表等等拿到CPU上, 此时肯定是内核态的, 然后开始执行代码时 又是用户态的, 所以这之间一定存在 内核态向用户态的转变, 也就一定会进行信号的检测和处理。

所以 不仅仅是系统调用会让进程从用户态变成内核态

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Linux 中打开可执行文件的进程映射虚存空间需要使用 exec 系列函数,其中最常用的是 execve 函数。execve 函数会替换当前进程的映像,即将当前进程的代码段、数据段等全部替换为可执行文件的映像。以下是一个简单的例子: ```c #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { char *args[] = {"/path/to/executable", NULL}; if (execve(args[0], args, NULL) == -1) { perror("execve"); exit(EXIT_FAILURE); } return 0; } ``` 其中,"/path/to/executable" 是可执行文件的路径。在调用 execve 函数时,第一个参数是可执行文件的路径,第二个参数是传递给可执行文件的参数,第三个参数是环境变量,这里我们传入 NULL 表示使用当前环境变量。 当调用 execve 函数时,如果成功,当前进程的映像就会被替换为可执行文件的映像,并从可执行文件的入口点开始执行。如果失败,函数会返回 -1,并设置 errno 变量来指示错误的原因。在上面的例子中,我们使用 perror 函数来输出错误信息。 ### 回答2: 在Linux中,我们可以使用exec()系列函数来打开可执行文件的进程映射虚存空间。 首先,通过exec()函数所在的库函数(比如execl()、execv()、execle()等)来调用操作系统的execve()系统调用函数。execve()函数能够执行指定可执行文件,并将其加载到当前进程的虚存空间中。 调用execve()函数时,我们需要传入以下参数: 1. 可执行文件的路径:指定要打开的可执行文件的路径。 2. 命令行参数数组:以NULL结尾的字符串数组,用于将命令行参数传递给被执行的可执行文件。 3. 环境变量数组:以NULL结尾的字符串数组,用于将环境变量传递给被执行的可执行文件。 执行execve()函数后,操作系统将加载指定的可执行文件,并将其映射到当前进程的虚存空间中。然后,操作系统会将控制权交给新的程序,从新程序的入口点开始执行。 当执行execve()函数成功时,原进程的虚存空间会被新的程序覆盖,原进程的代码、数据等内容会被替换为新程序的代码、数据等内容。 总结来说,要在Linux中打开可执行文件的进程映射虚存空间,可以使用exec()系列函数中的任意一个,将可执行文件路径、命令行参数和环境变量传递给execve()系统调用函数,然后操作系统会执行相应的操作,将可执行文件加载到当前进程的虚存空间中。 ### 回答3: 在Linux中,要打开可执行文件的进程映射虚存空间,可以使用exec函数族中的execve函数。execve函数用于执行一个新的程序,并将新程序的代码和数据加载到当前进程的虚拟内存空间中。 首先,需要包含头文件unistd.h。 接下来,需要准备一个字符串数组,用于存储可执行文件的路径和参数。数组的第一个元素是可执行文件的路径,接下来的元素可以是命令行参数,最后一个元素必须是NULL来标识参数列表的结束。 然后,可以使用execve函数调用打开可执行文件并将其映射到当前进程的虚拟内存空间中。execve函数的调用形式如下: int execve(const char *filename, char *const argv[], char *const envp[]); 其中,filename是可执行文件的路径,argv是参数列表,envp是环境变量列表。 execve函数执行成功后,当前进程的代码和数据将被替换为可执行文件的代码和数据,可执行文件的入口函数将被调用。 需要注意的是,execve函数只会加载可执行文件的内容到当前进程的虚拟内存空间,而不会创建新的进程。因此,在调用execve函数后,当前进程的PID不会改变。 这是一种在已有进程中运行一个新的程序的方法,适用于需要在当前进程中加载新的可执行文件的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值