永远不要用同一只手,同时去按修饰键(如 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 进行系统调用获得,即使在代码里创建了一个全局变量也不可以,因为全局变量是一个进程内的所有函数可以共用,但不同进程之间依然是独立的,如果子进程尝试通过修改全局变量的值(改为自己的退出码),这个时候是会触发写时拷贝的,然后就变成父子进程各有一个这样的全局变量,而且父进程无法访问子进程刚刚由写时拷贝新创建的全局变量(进程隔离)
也就是正常情况下,所有进程之间的交互必须通过系统调用才能完成;
getpid,getppid也是通过系统调用完成的,因为父子进程要访问对方的PCB才能获取对方的pid
9、当前工作目录与环境变量PWD的区别
:
chdir函数实际上只修改了系统内核中对应进程的当前工作目录这个属性,而不会去修改PWD这个环境变量,而我们执行cd的时候,之所以,当前工作目录和PWD都得到了修改,是因为shell对cd命令做了封装,使它同时完成了chdir()和修改PWD环境变量两个事情。
有三个,一是内核中的当前工作目录,二是环境变量PWD,三是命令行提示符上显示的那个工作目录