一 linux操作系统复习笔记
编译 程序需要几部分?
预处理(生成预编译文件)编译(生成汇编代码)汇编(生成目标文件)链接(生成可执行文件)
内存寻址
1.逻辑地址--->线性地址--->物理地址,线性地址是指一段连续的、不分段的、范围从0-4G的地址空间
16位段寄存器中存放的不是某个段的基地址,而是某个段的选择符(选择符=索引号+TI+RPL),所以段寄存器=端的选择符;;16位的段寄存器无法存放32的段基地址,所以段基地址存放到段描述符表中
逻辑地址(虚地址)=段标识符:指定段内相对地址的偏移量MMU把逻辑地址转换成物理地址分段基址(逻辑地址转换成线性地址)段:虚拟地址空间的基本单位总结:逻辑地址=段选择符:偏移量----->16位段寄存器=段选择符(索引号:TI:RPL)------->段描述符表------->段描述符------>32位的段基址、段的界限、------->基址和ESI,EDI等中的32有效地址相加形成32位线性地址分页机制(线性地址转换成物理地址)页表:线性地址映射到物理地址的一中数据结构页(page,线性):将线性地址划分成若干大小相等的片,叫做页,大小为4K块或页面(page frame 物理):把物理地址空间分成与页大小相等的若干存储块4G的线性地址=1M个*4K大小的页,每个页表项占4个字节;1M个页表需要4M空间(1M*4个字节);4M的页表再次分页(4M/4K)可以分成1K个页,同样每个页表项占4个字节,可以推算出页目录占1K*4个字节=4K,正好是一个页的也目录。这就是二级分页。
进程
Linux为每个进程都创建一个task_struct结构
init进程:内核启动的第一个进程,称为0号进程。init进程还负责“收养”孤儿进程。进程描述符:是一个task_struct结构,用于存放进程的属性和信息,与进程所有相关的内核信息都存储在这个结构体中。进程描述符存放在动态内存中,而不是存放在永久分配给内核的内存区。fork后的子进程和父进程有什么区别:在fork之后exec之前两个进程用的是相同的物理空间(内存区), 子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此父进程子进程有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
父进程和子进程
进程和线程区别:
进程是操作系统分配资源的最小单位;线程是操作系统调度执行的最小单位,是干活的。进程有自己的地址空间,线程使用进程的地址空间,进程的资源(堆,栈,静态存储区等)线程是有权访问的,但每个线程还拥有自己的栈,这个栈仍然使用进程的地址空间,这个栈是不可以被其他的线程所访问的。(第一个是进程的环境示意图,第二个是线程的环境示意图
进程和线程区别
内存四区
栈区(stack):存放函数的参数值,局部变量的值,堆区(heap):动态分配的值全局区/静态区(static)/常量区:初始化的全局变量,静态变量。包含常量区(常量字符串就放在这里,结束后由系统释放)代码区(code):存放二级制代码
内存四区
char*fa(){char*pa = "123456"; //pa指针在栈区,“123456”在常量区,该函数调用完后指针变量pa就被释放了char*p = NULL; //指针变量p在栈中分配4字节p=(char*)malloc(100); //本函数在这里开辟了一块堆区的内存空间,并把地址赋值给pstrcpy(p, "hello world 1234566"); //把常量区的字符串拷贝到堆区return p; //返回给主调函数fb(),相对fa来说fb是主调函数,相对main来说,fa(),fb()都是被调用函数}char*fb(){char*pstr = NULL;pstr = fa();return pstr; //指针变量pstr在这就结束}void main(){char*str = NULL;str = fb();printf("str = %sn",str);free(str); //防止内存泄露,被调函数fa()分配的内存存的值通过返回值传给主调函数,然后主调函数释放内存str = NULL; //防止产生野指针system("pause");}