
永远不要用同一只手同时去按修饰键如 Ctrl/Alt和字母键。操作系统的管理先描述再组织。1.感叹号 问题在Linux中有特殊含义可以用来调用历史命令即使在双引号里面也是会被认为是这种特殊含义要想让系统认为他是个字符要用单引号。2.关于结构体内部变量相对地址大小栈和堆地址变化和大小端问题结构体内部变量地址是递增的前面的地址小后面的大计算相对地址时注意栈的地址是从大到小的堆的是逐渐变大的大小端涉及的是单个多字节变量的存储问题所以结构体内部变量不受这个影响3、全局与局部变量c中static就是全局变量和全局变量放在同一个区域只不过其作用域仅限于函数所在域并且有初始化的全局变量在内存中会优先创建const修饰的常变量是和代码放在同一个区域的。4、父子进程所谓指向同一个数据和代码空间父进程在创建子进程的时候是把自己的页表拷贝了一个给子进程所以两个的虚拟内存地址是一样的而一旦其中有一个进程修改某个变量系统就会在开辟一个空间将这个变量拷贝一份让其在新开辟的空间上对这个拷贝的变量进行修改同时将这个变量虚拟内存空间中存储的物理内存地址改成现场这个拷贝变量的地址而且这个新开辟的地址是以页为单位的而不是单纯开辟一个变量大小的地址。5、虚拟内存中的空间管理在虚拟内存空间中除了通过记录不同功能区的起点和终点这种大的划分外由于功能区内部也有动态管理空间的需求所以有引入了结构体vm_area_struct链表进行空间管理.即使在虚拟内存空间中也不是单纯的用几个起点和终点记录把空间划分为代码区数据区栈堆....区域在同一个功能区内部也需要再用链表管理各个区域比如堆不同的变量会申请不同的空间如果单纯用一个起点和终点把整个堆的空间划出来那么这些不同变量所申请的堆就无法管理所以用哪个链表管理每一个变量申请的空间都写在一个结构体vm_area_struct内部然后进行管理除了这种情况外还有类似权限的管理同一个功能区内部的不同区域可访问权限可能是不同的也需要进一步划分所以也需要链表而不继续使用固定起点终点进行更细的划分是因为这种区域内的进一步划分的需求是动态的比如变量申请堆空间不一定是几个变量申请还有多线程也不确定会有几个。6、写时拷贝是如何触发的首先父进程创建子进程的时候子进程会将父进程的页表拷贝一份然后内核会将父子进程的页表上的读写权限全部改成只读之后如果有其中某一个进程想要修改数据的话在虚拟地址转换的时候会出现非法访问只读权限要修改数据这个时候内核会介入然后发现这部分数据原本就是可以读写的只不过因为父子进程共享然后改成了只读内核会把要修改的数据所在的页在内存中拷贝一份并将对应的物理地址写入到要修改数据的进程的页表原对应页表项中如果此时原来的那份数据不在有进程共享则也改成读写权限。关于内核如何确定这个非法访问实际上是因为父子进程的共享而导致的这个过程还不知另外。下面解释中举的那个字符串的例子说明了其实在我们日常代码赋值的过程中一开始也是大家共享一个数据指向同一个内存只有当发生修改的时候然后真的去再去开辟空间复制变量有效的节省的内存。7、 \n 刷新缓冲区问题\n并没有刷新缓冲区的能力只不过有系统的行缓冲机制在就是如果你的要输出的内容是要输出的屏幕上的话那系统就执行行缓冲机制遇到 \n 就直接把缓冲区里面的内容输出到屏幕上防止太卡而如果是要把内容输出到其他比如文件之类的里面那就执行全缓冲只有当缓冲区满了或者时间到了才会进行缓冲区的刷新与 \n 本身无关。但是std::endl是包括 换行回车 和 刷新缓冲区两个功能的。8、父进程通过 wait/waitpid 获取子进程的运行结果父进程想要获取子进程的运行结果只能通过 wait/waitpid 进行系统调用获得即使在代码里创建了一个全局变量也不可以因为全局变量是一个进程内的所有函数可以共用但不同进程之间依然是独立的如果子进程尝试通过修改全局变量的值改为自己的退出码这个时候是会触发写时拷贝的然后就变成父子进程各有一个这样的全局变量而且父进程无法访问子进程刚刚由写时拷贝新创建的全局变量进程隔离也就是正常情况下所有进程之间的交互必须通过系统调用才能完成getpidgetppid也是通过系统调用完成的因为父子进程要访问对方的PCB才能获取对方的pid9、当前工作目录与环境变量PWD的区别chdir函数实际上只修改了系统内核中对应进程的当前工作目录这个属性而不会去修改PWD这个环境变量而我们执行cd的时候之所以当前工作目录和PWD都得到了修改是因为shell对cd命令做了封装使它同时完成了chdir和修改PWD环境变量两个事情。有三个一是内核中的当前工作目录二是环境变量PWD三是命令行提示符上显示的那个工作目录