现在的位置: 首页 > 综合 > 正文

三言两语linux内核

2013年01月29日 ⁄ 综合 ⁄ 共 3431字 ⁄ 字号 评论关闭
进程
linux通过slab预先分配和重复使用task_struct(进程描述符,包含了内核管理一个进程的所有信息),来避免动态分配和释放所带来的资源消耗,因此进程创建迅速)
PID存在task_struct中
1.管理一个进程的信息都存在task_struct里,系统创建了一大堆这种结构体,用链表串起来,新建进程,就取一个,把信息写进去,然后把这个结构体的地址放在内核栈的栈底(放在thread_info,这个结构体在内核栈底)。
2.进程如何运行:
把一个ELF的文件加载到内存,找个函数开始执行,大都在用户空间执行,只有涉及到系统调用(系统调用也是通过中断)或中断,才陷入内核空间
3.啥时候要系统调用或中断:
4.子进程创建流程:
fork创建task_struct,内核栈,从父进程把能继承的都拷过来,exec,另开一块内存,把ELF载入
5.linux的线程
就是进程,也有自己的task_struct,只不过这种进程共享内存,文件,信号等资源
6.内核进程:没有用户空间,只有内核空间,只在内核中运行
7.所谓内核空间和用户空间,其实就是内存上划分了两块区域,内核空间只有内核能访问,用户空间,普通程序可以访问,权限不同而已
进程调度
1.两种进程:一种一直在要用cpu,做计算,内存中数据处理的操作
               一种,大部分时间都在等硬件,比如硬盘的数据拷到内存,或者读取网卡数据
2.分配时间片,优先级高的分的就多,并且会根据使用情况,动态调节优先级,时间片越多,响应越快,但不代表占用cpu的时间长,比如有的给的时间片多,那么他会更频繁的被执行,如果这任务调用一下,就等硬件,那么cpu空下来给别的任务用,只不过,没隔多久,又要切回这个进程,检查下硬件完成任务没。
3.如何计算优先级:系统会记录任务在一个时间片内,占用cpu多长时间,休眠多长时间,根据占的比例判断是否要多给时间片,
4.上下文切换:从一个进程切换到另一个进程,要做两件事,一件是虚拟内存要映射到新的进程,另一个就是保存旧进程的栈信息,寄存器信息和恢复新进程的栈信息和寄存器信息。(这些信息,存放在进程自己的堆栈里)
阻塞与休眠:
休眠,程序把cpu让给其他程序,自己回到等待的队列中
阻塞就是让当前线程休眠

系统调用:
1.啥时候要用到系统调用:
访问硬件和其他资源
2.如何去调用:
软中断,引发异常,引起系统切换到内核态,调用对应的中断处理函数system_call(),这个函数的作用就是调用系统调用
中断:
一个通知CPU的电信号,其他设备或者程序通知cpu有事件发生了。
异常:cpu执行指令时,如果出现错误,自己给自己发的一个信号,后面的处理方式和中断一样,因此又叫软中断
一样的设备,可以共享一个中断线(给各种类型中断的编号)
中断处理函数不能休眠,因为中断后,中断上下文就是一个独立的,与进程无关,如果休眠了,就无法被重新调度了。也就是中断处理函数必须一口气处理完
内核同步:
1.互斥与同步
互斥:我在做什么,你不能做什么
同步:我做完了什么,通知你一声,你才能做什么
2.加锁:
就好比有个全局标志位,当有一个线程用到了这个标志位,就置false,其他线程要用就得等,直到被释放,置回true
3.什么导致了并发:
用户空间:一个线程(或进程)执行到关键区域,换到另一个线程(或进程)执行,或者执行到关键区域,收到信号,要去另一段代码,仍然是处理关键区域
内核:
1.中断,这个与上面的信号类似
2.内核抢占,这个和用户空间类似
3.睡眠,导致重新调度用户空间的进程,然后,再进入内核,结果用到同一段关键区域
4.多核
4.要给啥加锁:
锁的作用是让程序以串行方式对资源进行访问
如果其他线程可以访问到,就要加锁,如果其他任何东西可以访问到,更要加锁
5.如何防止死锁:
加锁顺序要一致
6.同步方法:
a.原子操作:atomic_add
b.自旋锁:类似windows的关键区域,不同的是,自旋锁,如果已经被一个线程霸占,另一个线程要不断的循环,等待这个锁,浪费资源,所以如果需要等待的时间很短,就可以使用,而关键区域,在锁被霸占的时候,会把当前线程阻塞,过会儿再来检查,锁是否释放,缺点是线程阻塞,再打开,涉及到线程重新调度,开销大。
注意:自旋锁只适用于多处理器,单cpu的系统会被优化成空语句,但有一个地方要注意,用到自旋锁的地方,就必须保证cpu在执行完锁内的代码前不能让出去,必须满足下面的条件:
     自旋锁有几个重要的特性:1、被自旋锁保护的临界区代码执行时不能进入休眠。2、被自旋锁保护的临界区代码执行时是不能被被其他中断中断。3、被自旋锁保护的临界区代码执行时,内核不能被抢占。从这几个特性可以归纳出一个共性:被自旋锁保护的临界区代码执行时,它不能因为任何原因放弃处理器。如果被其它线程抢占了,那个线程也要用这个锁,那它会一直占用cpu,做死循环,等待这个锁释放,而这个锁永远不会被释放。
如果一个线程持有自旋锁,它要禁止中断和其他会导致当前线程放弃cpu的操作,所以单cpu上,用了自旋锁,就不能做进程抢占了,也就没有对资源的竞争关系了(用完了,释放了,才能切到其他进程)
在单cpu的环境,自旋锁操作会被优化成空操作。
c.信号量:这个与windows一致,机制和上面说的windows的关键区域相同,用的是阻塞的办法,等到等待的信号量被释放了,就会被通知该线程去继续执行,这个不能用于中断,因为中断上下文是不可调度的,而上面的自旋锁是可以用在中断的
d.与windows不同的是,这里没有event,原因是linux有一套很好用的信号机制,配合信号量就可以做到同步(有个类似的东西:完成变量)
e.只有自旋锁可以用于中断上下文(同样是多cpu),因为其他类型的同步方法都可以睡眠,都不能用于中断
内存管理:
1.物理内存被划分成一页一页,32为的每页4kb,64位8kb
2.kmalloc 获取物理地址连续的页,一般用这个
3.vmalloc获取物理地址不连续,虚拟地址连续的页,只在分配大块内存的时候用
4.空闲链表与slab:
空闲链表:如果要频繁用到某种数据结构的内存,可以预先分配好一堆,放在链表里,要用就抓一个,避免频繁分配释放
slab:相当于空闲链表的作用,把频繁用到的数据结构缓存,里面有空闲链表
slab把不同的数据结构称为高速缓存,一个slab存取一种数据结构的很多个拷贝,(如果数据量大,可以用几个slab存),需要这种结构时,就去还没有满的slab中取一个
5.内核栈,只有一页或者两页
6.内存分配:用户空间0~3g,内核空间3~4g,这样用户空间和内核空间的内存就隔离开了。这样效率更高(进程在用户态和内核态间切换,不需要更新页表)
7.高端内存:通常给内核分配的可映射物理内存只有1g,而如果用的是kmalloc分配的内存,需要一段物理地址连续的内存,如果只限制在这1g的空间内,就可能找不到,高端内存就是,如果这1g的空间里没有,就去用户空间临时借用一下。所以暂时会给内核空间只分配872m的内存,剩下的128m需要的时候去用户空间里找一段连续的物理内存,用完就要释放掉。
文件:
linux可以有很多不同种的文件系统,linux通过封装(VFS),使得操作这些不同的文件系统的方式都一样
1.包括四个概念:文件,目录项,索引节点,安装点
目录项不是目录,目录也是文件,目录项用来表示路径信息
索引节点用来存放文件信息,比如创建时间,大小,索引节点放在特殊的块里。
2.VFS
VFS以对象的形式(结构体)管理文件:
包括4中对象类型:
超级块:每种文件系统都有一个自己的超级块,在这个超级块里存放了与这种文件系统相关的信息,以及索引节点及其创建等
索引节点:存放了操作文件所有的信息,不如文件大小,修改时间,引用数等,一个索引节点代表一个文件,索引节点的操作包括了mkdir,link,create等所有与文件有关的操作
目录项:目录项对象保存了与目录操作相关的信息,比如父目录,子目录等
文件对象:已打开文件,在内存中的表示。与文件直接有关的操作,read,write等,就放在这里,一个文件可以被多个进程打开,所以一个文件(一个索引节点)对应多个文件对象
3.vfsmount:挂载点,安装一个文件系统的信息
块 I/0层
块设备和字符设备:
硬盘,内存这种像数组一样,可以访问某个索引的设备
键盘,串口这样,像流水一样,只能从最开始访问的,就是字符设备

抱歉!评论已关闭.