Linux 的同步机制从 2.0 到 2.6 以来不断发展完善。从最初的原子操做,到后来的信号量,从 大内核锁到今天的自旋锁。这些同步机制的发展伴随 Linux 从单处理器到对称多处理器的 过渡;
伴随着从非抢占内核到抢占内核的过分。Linux 的锁机制愈来愈有效,也愈来愈复杂。 Linux 的内核锁主要是自旋锁和信号量。
自旋锁最多只能被一个可执行线程持有,若是一个执行线程试图请求一个已被争用(已经被 持有)的自旋锁,那么这个线程就会一直进行忙循环——旋转——等待锁从新可用。要是锁 未被争用,请求它的执行线程便能马上获得它而且继续进行。自旋锁能够在任什么时候刻防止多 于一个的执行线程同时进入临界区。
Linux 中的信号量是一种睡眠锁。若是有一个任务试图得到一个已被持有的信号量时,信号 量会将其推入等待队列,而后让其睡眠。这时处理器得到自由去执行其它代码。当持有信号 量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而即可以得到这个信号量。
信号量的睡眠特性,使得信号量适用于锁会被长时间持有的状况;只能在进程上下文中使用, 由于中断上下文中是不能被调度的;另外当代码持有信号量时,不能够再持有自旋锁。
Linux 内核中的同步机制:原子操做、信号量、读写信号量和自旋锁的 API,另一些同步机 制,包括大内核锁、读写锁、大读者锁、RCU (Read-Copy Update,顾名思义就是读-拷贝修 改),和顺序锁。node
MS-DOS 等操做系统在单一的 CPU 模式下运行,可是一些类 Unix 的操做系统则使用了双 模式,能够有效地实现时间共享。在 Linux 机器上,CPU 要么处于受信任的内核模式,要么处 于受限制的用户模式。除了内核自己处于内核模式之外,全部的用户进程都运行在用户模式之中。
内核模式的代码能够无限制地访问全部处理器指令集以及所有内存和 I/O 空间。若是用户 模式的进程要享有此特权,它必须经过系统调用向设备驱动程序或其余内核模式的代码发出请求。另外,用户模式的代码容许发生缺页,而内核模式的代码则不容许。
在 2.4 和更早的内核中,仅仅用户模式的进程能够被上下文切换出局,由其余进程抢占。除非 发生如下两种状况,不然内核模式代码能够一直独占 CPU:
(1) 它自愿放弃 CPU;
(2) 发生中断或异常。
2.6 内核引入了内核抢占,大多数内核模式的代码也能够被抢占。linux
在 Linux 内核环境下,申请大块内存的成功率随着系统运行时间的增长而减小,虽然能够经过 vmalloc 系列调用申请物理不连续但虚拟地址连续的内存,但毕竟其使用效率不高且在 32 位 系统上 vmalloc 的内存地址空间有限。因此,通常的建议是在系统启动阶段申请大块内存,但 是其成功的几率也只是比较高而已,而不是 100%。若是程序真的比较在乎这个申请的成功 与否,只能退用“启动内存”(Boot Memory)。下面就是申请并导出启动内存的一段示例代码:算法
可见其应用仍是比较简单的,不过利弊老是共生的,它不可避免也有其自身的限制: 内存申请代码只能链接进内核,不能在模块中使用。
被申请的内存不会被页分配器和 slab 分配器所使用和统计,也就是说它处于系统的可见内 存以外,即便在未来的某个地方你释放了它。
通常用户只会申请一大块内存,若是须要在其上实现复杂的内存管理则须要本身实现。 在不容许内存分配失败的场合,经过启动内存预留内存空间将是咱们惟一的选择。缓存
(1)管道(Pipe):管道可用于具备亲缘关系进程间的通讯,容许一个进程和另外一个与它有共同祖 先的进程之间进行通讯。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,所以,除具备管道所具备的 功能外,它还容许无亲缘关系进程间的通讯。命名管道在文件系统中有对应的文件名。命名 管道经过命令 mkfifo 或系统调用 mkfifo 来建立。
(3)信号(Signal):信号是比较复杂的通讯方式,用于通知接受进程有某种事件发生,除了用于进 程间通讯外,进程还能够发送信号给进程自己;linux 除了支持 Unix 早期信号语义函数 sigal 外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD 的,BSD 为了实现可靠信号机制,又可以统一对外接口,用 sigaction 函数从新实现了 signal 函数)。
(4)消息(Message)队列:消息队列是消息的连接表,包括 Posix 消息队列 system V 消息队 列。有足够权限的进程能够向队列中添加消息,被赋予读权限的进程则能够读走队列中的消 息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等 缺
(5)共享内存:使得多个进程能够访问同一块内存空间,是最快的可用 IPC 形式。是针对其余 通讯机制运行效率较低而设计的。每每与其它通讯机制,如信号量结合使用,来达到进程间 的同步及互斥。
(6)信号量(semaphore):主要做为进程间以及同一进程不一样线程之间的同步手段。
(7)套接字(Socket):更为通常的进程间通讯机制,可用于不一样机器之间的进程间通讯。起初是 由 Unix 系统的 BSD 分支开发出来的,但如今通常能够移植到其它类 Unix 系统上:Linux 和 System V 的变种都支持套接字。markdown
在物理页面管理上实现了基于区的伙伴系统(zone based buddy system)。对不一样区的内存 使用单独的伙伴系统(buddy system)管理,并且独立地监控空闲页。相应接口 alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。数据结构
struct super_block,struct inode,struct file,struct dentry;并发
struct file_operations函数
执行文件,普通文件,目录文件,连接文件和设备文件,管道文件。spa
clone(),fork(),vfork();系统调用服务例程:sys_clone,sys_fork,sys_vfork;操作系统
1.系统调用 do_fork();
2.定时中断 do_timer();
3.唤醒进程 wake_up_process
4.改变进程的调度策略 setscheduler();
5.系统调用礼让 sys_sched_yield();
Liunx 调度程序是根据根据进程的动态优先级来调度进程的,可是动态优先级又是根据静态 优先级根据算法计算出来的,二者是两个相关联的值。由于高优先级的进程老是比低优先级
的进程先被调度,为防止多个高优先级的进程占用 CPU 资源,致使其余进程不能占有 CPU, 因此引用动态优先级概念
struct runqueue
insmod 加载,rmmod 卸载
模块运行在内核空间,应用程序运行在用户空间
应用程序实现,Linux 中的浮点运算是利用数学库函数实现的,库函数可以被应用程序连接后 调用,不能被内核连接调用。这些运算是在应用程序中运行的,而后再把结果反馈给系统。 Linux 内核若是必定要进行浮点运算,须要在创建内核时选上 math-emu,使用软件模拟计算 浮点运算,听说这样作的代价有两个:用户在安装驱动时须要重建内核,可能会影响到其余的 应用程序,使得这些应用程序在作浮点运算的时候也使用 math-emu,大大的下降了效率。
模块程序运行在内核空间,不能连接库函数。
TLB,页表缓存,当线性地址被第一次转换成物理地址的时候,将线性地址和物理地址的对应 放到 TLB 中,用于下次访问这个线性地址时,加快转换速度。
字符设备和块设备。网卡是例外,他不直接与设备文件对应,mknod 系统调用用来建立设备 文件。
字符设备描述符 struct cdev,cdev_alloc()用于动态的分配 cdev 描述符,cdev_add()用于注 册一个 cdev 描述符,cdev 包含一个 struct kobject 类型的数据结构它是核心的数据结构
open(),read(),write(),llseek(),realse();
Linux 使用一个设备编号来惟一的标示一个设备,设备编号分为:主设备号和次设备号,通常主 设备号标示设备对应的驱动程序,次设备号对应设备文件指向的设备,在内核中使用 dev_t 来 表示设备编号,通常它是 32 位长度,其中 12 位用于表示主设备号,20 位用于表示次设备号, 利用 MKDEV(int major,int minor);用于生成一个 dev_t 类型的对象。
靠软件中断实现的,首先,用户程序为系统调用设置参数,其中一个编号是系统调用编号,参数 设置完成后,程序执行系统调用指令,x86 上的软中断是有 int 产生的,这个指令会致使一个异 常,产生一个事件,这个事件会致使处理器跳转到内核态并跳转到一个新的地址。并开始处 理那里的异常处理程序,此时的异常处理就是系统调用程序。
Linux 中的软中断和工做队列是中断处理。
1.软中断通常是“可延迟函数”的总称,它不能睡眠,不能阻塞,它处于中断上下文,不能进城切 换,软中断不能被本身打断,只能被硬件中断打断(上半部),能够并发的运行在多个 CPU 上。 因此软中断必须设计成可重入的函数,所以也须要自旋锁来保护其数据结构。
2.工做队列中的函数处在进程上下文中,它能够睡眠,也能被阻塞,可以在不一样的进程间切 换。已完成不一样的工做。 可延迟函数和工做队列都不能访问用户的进程空间,可延时函数在执行时不可能有任何正在 运行的进程,工做队列的函数有内核进程执行,他不能访问用户空间地址
看到这里的小伙伴,若是你喜欢这篇文章的话,别忘了转发、收藏、留言互动!
若是对文章有任何问题,欢迎在留言区和我交流~
最近我新整理了一些Java资料,包含面经分享、模拟试题、和视频干货,若是你须要的话,欢迎私信我!