//我们平常所说的地址 都是逻辑地址 所以父进程和子进程所用的地址是一样的 但他们的物理地址不同 所以他们打印的值不同
//逻辑地址 程序运行的时候 代码所使用的虚拟地址 仅在进程自身的"虚拟地址空间"中有效
// 使用者 应用程序开发者(写代码时用到的变量地址,函数地址等),cpu(执行指令时先处理逻辑地址)
// 空间范围 由操作系统分配 与物理内存无关
// 稳定性 程序重启时 同一变量的逻辑地址可能不变 但相对的物理地址通常变化 稳定性不高
//物理地址 物理内存(内存条)实际的硬件地址 是真实存在的地址线编号(如 0x00000,0xfffff) 地址存储是按1 2 8 的大小分
// 使用者 内存控制器 内存管理单元
// 空间范围 等于物理硬件内存容量
//稳定性 物理地址是硬件固定的 仅随硬件的配置进行变化
//早期计算机确实是直接使用物理地址 但有三个缺点
//1 内存冲突 多个进程访问同一物理地址时 会导致数据覆盖
//2 内存浪费 程序需要连续的内存块存放数据 若内存中有碎片(小块的内存空间) 即使总空间空间足够 也无法分离
//3 安全性低 程序可以访问物理地址 可能恶意修改其他程序或操作系统的内存数据
//逻辑地址 如何解决如上问题
//逻辑地址 通过"地址空间隔离"和 '动态映射'解决问题
//1 每个进程拥有独立的"虚拟地址空间"(逻辑地址范围) 进程间无法直接访问对方的逻辑地址 避免冲突
//2 逻辑地址无需对应连续的物理地址 操作系统可将分离的物理内存碎片拼接起来成连续的逻辑地址 利用碎片
//3 地址转换过程中加入权限检查(只读,只执行),防止越权访问物理内存
// 逻辑地址不能直接访问物理地址 ,必须通过内存管理单元进程转换 核心是依赖页表机制
//步骤
//1 前提 内存分页
//操作系统将逻辑地址空间和物理地址空间均划分大小固定的页(page)比如4kb一页 4kb==2的12次方
//逻辑地址转换为逻辑页 每个逻辑页有对应编号 (VPN)
//物理地址->物理页 每个物理页有唯一的'物理页编号(PFN)'
//32位逻辑空间(4GB)按4K分页 可分为4G/4k=1048476逻辑页 每个逻辑页的页号(VPN)占20位,页内偏移占12位
// cpu会分解该逻辑地址
// 例如 int a = 0x1234 ;(逻辑地址是0x12345678),32位系统上,分页是4K一页
//MMU (内存管理单元 ) 会使用VPH查表 比如查出页表是0x12345(PFN)
//就会拼接物理地址 使用PFN和页内偏移拼接 0x12345000(物理地址)
//内存控制器将访问0x12345000将0x1234写入该地址
// 逻辑地址 物理地址
// 本质 进程虚拟地址空间的地址软件层面的地址 物理内存硬件地址
//作用范围 仅在当前进程有限 全系统唯一
//依赖关系 需要MMU+页表转化为物理地址 无需转换 可直接被内存控制器识别
//与硬件的关系 32位系统逻辑空间大小为4G 16GB 的内存条 对应16GB大小的地址串
//典型的场景 在进程编译时,用到逻辑地址 在内存控制器访问时的实际地址
//简单来说 逻辑地址是给程序看的 物理地址 是给硬件看的
//逻辑地址什么时候确定 编译完成时确定了逻辑地址
//chmod + 777 修改文件的权限
//文件描述符是open还是打开文件后的返回值 用来描述一个打开的文件
//文件描述符从0开始 逐渐递增 上限是文件表的最大值
// 键盘 0 标准输入 stdio
// 屏幕 1 标准输出 stdin
// 2 标准错误输出 stderr
// struct file
// r w count=5
// pos=?(文件偏移)
//函数 lseek 可以自动设置该偏移量
// strtok() 字符串分割函数 可以按照规定的方式分割字符串 cp 1.c 2.c
//进程的替换 替换进程 会使原本的进程实体被释放 进程号不变 且该进程的父子关系还存在
// execl execlp execle execv execvp 库函数
// execve 系统调用函数
//制造属于自己的bash
//在自己运行的进程中,创建一个子进程 替换该子进程
//set nonu 取消行号