Linux内核支持多核是如何实现的? (linux 内核 多核)

随着计算机硬件技术的不断发展,多核处理器已经成为了现代计算机的重要组成部分。而Linux作为更流行的开源操作系统之一,已经提供了对多核处理器的完全支持。那么,Linux内核支持多核是如何实现的呢?本文将探讨Linux内核支持多核的实现原理。

了解多核处理器

在探讨Linux内核支持多核的实现原理之前,我们需要了解多核处理器的工作原理。多核处理器就是在一个物理处理器集成两个或多个核心。每个核心都是一个完整的处理器,可以处理一个线程。因此,多核处理器可以同时处理多个线程,从而提高计算机的性能。

多核处理器的性能提高取决于多个因素,包括程序的并行性、内存带宽、线程间通信的效率等。有时候,由于多个线程竞争同一个资源,可能会出现性能瓶颈。因此,合理地使用多核处理器需要更高的系统优化水平。

Linux内核如何支持多核?

1. 处理器亲和性

处理器亲和性是一种机制,用于将进程绑定到特定的处理器核心上。在Linux内核中,处理器亲和性是通过 sched_setaffinity() 系统调用实现的。这个系统调用可以将进程绑定到一个或多个特定的处理器上。通过处理器亲和性机制,可以使得进程优先在绑定的处理器上运行,从而提高系统的性能。

2. 任务调度

Linux内核对于多核处理器的支持,还涉及到任务调度机制。任务调度是指内核决定哪个进程占用处理器的时间。在多核处理器中,任务调度需要考虑许多因素,例如处理器亲和性、负载均衡等。内核的调度器必须合理地分配处理器内核,从而保证每个进程都可以获得足够的时间片,使系统保持高效运行。

3. 中断处理

中断处理是指当系统硬件设备发生需要处理的事件时,中断处理程序被调用处理这个事件。在多核处理器中,中断处理需要考虑到每个核心的中断处理程序的并发性。 Linux内核通过使用自旋锁和信号量等机制来处理并发中断请求,保证每个内核都可以按照正确的顺序处理中断请求,确保系统的稳定运行。

4. 线程同步

在多核处理器中,线程同步是非常重要的因素,如果没有得到正确的处理,可能会导致系统的不稳定。线程同步是指当多个线程访问共享资源时,确保每个线程访问时机的协调性。在Linux内核中,线程同步是通过锁机制来实现的。锁机制确保每个线程能够按照正确的先后顺序访问共享资源,从而防止出现访问冲突,导致系统的不稳定。

在多核处理器上,Linux内核支持多核的实现是一个复杂而细致的工作。Linux内核提供了处理器亲和性、任务调度、中断处理和线程同步等机制来优化多核处理器的运行。这样就可以充分利用多核处理器的优势,提高计算机的性能。了解Linux内核支持多核的实现原理不仅可以让我们更好地使用计算机,还可以在优化系统性能方面着手进行更深层次的工作。

相关问题拓展阅读:

在Linux系统上,多个线程能否同时使用多个CPU核心?有人说能,有人说不能

与超慎慎核线程CPU在逻辑上模拟双核不同,多核CPU每个核心都可以独立执行一个线程,是真正意义的多个物理CPU。

第孝耐二个问题,如果你的程序的线程数少于CPU的核心数,且系统此时没有其他进程同时运行,那么这个程序的每个线程会享有一个CPU,当同时运行的线程数多于CPU核心数时,CPU会采用一定的调度算法每隔一段时间就将这些线程调入或调出CPU,以宽掘确保每个线程都能分享一部分CPU时间,实现多线程并发。

arm linux 多核同时运行

多处理器可以被定义用来包含多个core的单个设备中含烂同时运行二洞迅个或多个指令。现在广泛应用于通用应用处理器和嵌谈颤漏入式系统中。

并行编程技术是谁的核心技术体系

并行编程技术是谁的核心技术体系

在摩尔定律失效之前,提升处理器性能通过主频提升、硬件超线程等技术就能满足应用需要。随着主频提升慢慢接近撞上光速这道墙,摩尔定律开始逐渐失效,多核集成为处理器性能提升的主流手段。现在市面上已经很难看到单核的处理器,就是这一发展趋势的佐证。要充分发挥多核丰富的计算资源优势,多核下的并行编程就不可避免,Linux kernel就是一典型的多核并行编程哗袭纤场景。但多核下的并行编程却挑战多多。

多核并行编程的挑战

目前主流的计算机都是冯诺依曼架构,即共享内存的计算模型,这种过程计算模乱仿型对并行计算并不友好。下图是一种典型的计算机硬件体系架构。

这种架构中,有如下设计特点:

多个CPU核改善处理器的计算处理能力;

多级cache改善CPU访问主存的效率;

各个CPU都有本地内存(NUMA(非一致性内存访问)),进一步改善CPU访问主存的效率;

store buffer模块改善cache write由于应答延迟而造成的写停顿问题;

invalidate queue模块改善使无效应答的时延,把使无效命令放入queue后就立即发送应答;

外设DMA支持直接访问主存,改善CPU使用效率;

这些硬件体系设计特点也引入很多问题,更大的问题就是cache一致性问题和乱序执行问题。

cache一致性问题由cache一致性协议MESI解决,MESI由硬件保禅逗证,对软件来说是透明的。MESI协议保证所有CPU对单个cache line中单个变量修改的顺序保持一致,但不保证不同变量的修改在所有CPU上看到的是相同顺序。这就造成了乱序。不仅如此,乱序的原因还有很多:

store buffer引起的延迟处理,会造成乱序;

invalidate queue引起的延迟处理,会造成乱序;

编译优化,会造成乱序;

分支预测、多流水线等CPU硬件优化技术,会造成乱序;

外设DMA,会造成数据乱序;

这种情况造成,就连简单的++运算操作的原子性都无法保证。这些问题必须采用多核并行编程新的技术手段来解决。

多核并行编程关键技术

锁技术

Linux kernel提供了多种锁机制,如自旋锁、信号量、互斥量、读写锁、顺序锁等。各种锁的简单比较如下,具体实现和使用细节这里就不展开了,可以参考《Linux内核设计与实现》等书的相关章节。

自旋锁,不休眠,无进程上下文切换开销,可以用在中断上下文和临界区小的场合;

信号量,会休眠,支持同时多个并发体进入临界区,可以用在可能休眠或者长的临界区的场合;

互斥量,类似与信号量,但只支持同时只有一个并发体进入临界区;

读写锁,支持读并发,写写/读写间互斥,读会延迟写,对读友好,适用读侧重场合;

顺序锁,支持读并发,写写/读写间互斥,写会延迟读,对写友好,适用写侧重场合;

锁技术虽然能有效地提供并行执行下的竞态保护,但锁的并行可扩展性很差,无法充分发挥多核的性能优势。锁的粒度太粗会限制扩展性,粒度太细会导致巨大的系统开销,而且设计难度大,容易造成死锁。除了并发可扩展性差和死锁外,锁还会引入很多其他问题,如锁惊群、活锁、饥饿、不公平锁、优先级反转等。不过也有一些技术手段或指导原则能解决或减轻这些问题的风险。

按统一的顺序使用锁(锁的层次),解决死锁问题;

指数后退,解决活锁/饥饿问题;

范围锁(树状锁),解决锁惊群问题;

优先级继承,解决优先级反转问题 ;

原子技术

原子技术主要是解决cache和内存不一致性和乱序执行对原子访问的破坏问题。Linux kernel中主要的原子原语有:

ACCESS_ONCE()、READ_ONCE() and WRITE_ONCE():禁止编译器对数据访问的优化,强制从内存而不是缓存中获取数据;

barrier():乱序访问内存屏障,限制编译器的乱序优化;

b_wmb():写内存屏障,刷新store buffer,同时限制编译器和CPU的乱序优化;

b_rmb():读内存屏障,刷新invalidate queue,同时限制编译器和CPU的乱序优化;

b_mb():读写内存屏障,同时刷新store buffer和invalidate queue,同时限制编译器和CPU的乱序优化;

atomic_inc()/atomic_read()等:整型原子操作;

严格来说,Linux kernel作为系统软件,实现受硬件影响很大,不同硬件有不同的内存模型,因此,不同于高级语言,Linux kernel的原子原语语义并没有一个统一模型。比如在P的ARM64 CPU上,barrier、b_wmb、b_rmb的实现与b_mb都是一样的,都是volatile (“” ::: “memory”)。

另外,再多提一句的是,atomic_inc()原语为了保证原子性,需要对cache进行刷新,而缓存行在多核体系下传播相当耗时,其多核下的并行可扩展性差。

无锁技术

上一小节中所提到的原子技术,是无锁技术中的一种,除此之外,无锁技术还包括RCU、Hazard pointer等。值得一提的是,这些无锁技术都基于内存屏障实现的。

Hazard pointer主要用于对象的生命周期管理,类似引用计数,但比引用计数有更好的并行可扩展性;

RCU适用的场景很多,其可以替代:读写锁、引用计数、垃圾回收器、等待事物结束等,而且有更好的并行扩展性。但RCU也有一些不适用的场景,如写侧重;临界区长;临界区内休眠等场景。

不过,所有的无锁原语也只能解决读端的并行可扩展性问题,写端的并行可扩展性只能通过数据分割技术来解决。

数据分割技术

分割数据结构,减少共享数据,是解决并行可扩展性的根本办法。对分割友好(即并行友好)的数据结构有:

数组

哈希表

基树(Radix Tree)/稀疏数组

跳跃列表(skip list)

使用这些便于分割的数据结构,有利于我们通过数据分割来改善并行可扩展性。

除了使用合适的数据结构外,合理的分割指导规则也很重要:

读写分割:以读为主的数据与以写为主的数据分开;

路径分割:按独立的代码执行路径来分割数据;

专项分割:把经常更新的数据绑定到指定的CPU/线程中;

所有权分割:按CPU/线程个数对数据结构进行分割,把数据分割到per-cpu/per-thread中;

4种分割规则中,所有权分割是分割最彻底的。

以上这些多核并行编程内容基本上涵盖了Linux kernel中所有的并发编程关键技术。当然并行编程还有很多其他技术没有应用到Linux kernel中的,如无副作用的并行函数式编程技术(Erlang/Go等)、消息传递、MapReduce等等。

关于linux 内核 多核的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux内核支持多核是如何实现的? (linux 内核 多核)