本站提倡有节制游戏,合理安排游戏时间,注意劳逸结合。

【开单平台源码】【控制软件源码】【展示站源码】linux fifo源码

2024-12-23 23:56:37 来源:探索 分类:探索

1.如何获得优先级在Linux环境编程中?
2.RTlinuxRTLinux的主要功能
3.linux内核数据结构之kfifo
4.linux操作系统文件类型有哪几种,有什么区别?
5.kfifo(linux kernel 无锁队列)

linux fifo源码

如何获得优先级在Linux环境编程中?

       ä»€ä¹ˆæ˜¯å®žæ—¶ç³»ç»Ÿï¼ŒPOSIX .b作了这样的定义:指系统能够在限定的响应时间内提供所需水平的服务。而一个由Donald Gillies提出的更加为大家接受的定义是:一个实时系统是指计算的正确性不仅取决于程序的逻辑正确性,也取决于结果产生的时间,如果系统的时间约束条件得不到满足,将会发生系统出错。

        实时系统根据其对于实时性要求的不同,可以分为软实时和硬实时两种类型。硬实时系统指系统要有确保的最坏情况下的服务时间,即对于事件的响应时间的截止期限是无论如何都必须得到满足。比如航天中的宇宙飞船的控制等就是现实中这样的系统。其他的所有有实时特性的系统都可以称之为软实时系统。如果明确地来说,软实时系统就是那些从统计的角度来说,一个任务(在下面的论述中,我们将对任务和进程不作区分)能够得到有确保的处理时间,到达系统的事件也能够在截止期限到来之前得到处理,但违反截止期限并不会带来致命的错误,像实时多媒体系统就是一种软实时系统。

        一个计算机系统为了提供对于实时性的支持,它的操作系统必须对于CPU和其他资源进行有效的调度和管理。在多任务实时系统中,资源的调度和管理更加复杂。本文下面将先从分类的角度对各种实时任务调度算法进行讨论,然后研究普通的 Linux操作系统的进程调度以及各种实时Linux系统为了支持实时特性对普通Linux系统所做的改进。最后分析了将Linux操作系统应用于实时领域中时所出现的一些问题,并总结了各种实时Linux是如何解决这些问题的。

        1. 实时CPU调度算法分类

        各种实时操作系统的实时调度算法可以分为如下三种类别[Wang][Gopalan]:基于优先级的调度算法(Priority-driven scheduling-PD)、基于CPU使用比例的共享式的调度算法(Share-driven scheduling-SD)、以及基于时间的进程调度算法(Time-driven scheduling-TD),下面对这三种调度算法逐一进行介绍。

        1.1. 基于优先级的调度算法

        基于优先级的调度算法给每个进程分配一个优先级,在每次进程调度时,调度器总是调度那个具有最高优先级的任务来执行。根据不同的优先级分配方法,基于优先级的调度算法可以分为如下两种类型[Krishna][Wang]:

        静态优先级调度算法:

        这种调度算法给那些系统中得到运行的所有进程都静态地分配一个优先级。静态优先级的分配可以根据应用的属性来进行,比如任务的周期,用户优先级,或者其它的预先确定的策略。RM(Rate-Monotonic)调度算法是一种典型的静态优先级调度算法,它根据任务的执行周期的长短来决定调度优先级,那些具有小的执行周期的任务具有较高的优先级。

        动态优先级调度算法:

        这种调度算法根据任务的资源需求来动态地分配任务的优先级,其目的就是在资源分配和调度时有更大的灵活性。非实时系统中就有很多这种调度算法,比如短作业优先的调度算法。在实时调度算法中, EDF算法是使用最多的一种动态优先级调度算法,该算法给就绪队列中的各个任务根据它们的截止期限(Deadline)来分配优先级,具有最近的截止期限的任务具有最高的优先级。

        1.2. 基于比例共享调度算法

        虽然基于优先级的调度算法简单而有效,但这种调度算法提供的是一种硬实时的调度,在很多情况下并不适合使用这种调度算法:比如象实时多媒体会议系统这样的软实时应用。对于这种软实时应用,使用一种比例共享式的资源调度算法(SD算法)更为适合。

        比例共享调度算法指基于CPU使用比例的共享式的调度算法,其基本思想就是按照一定的权重(比例)对一组需要调度的任务进行调度,让它们的执行时间与它们的权重完全成正比。

        我们可以通过两种方法来实现比例共享调度算法[Nieh]:第一种方法是调节各个就绪进程出现在调度队列队首的频率,并调度队首的进程执行;第二种做法就是逐次调度就绪队列中的各个进程投入运行,但根据分配的权重调节分配个每个进程的运行时间片。

        比例共享调度算法可以分为以下几个类别:轮转法、公平共享、公平队列、彩票调度法(Lottery)等。

        比例共享调度算法的一个问题就是它没有定义任何优先级的概念;所有的任务都根据它们申请的比例共享CPU资源,当系统处于过载状态时,所有的任务的执行都会按比例地变慢。所以为了保证系统中实时进程能够获得一定的CPU处理时间,一般采用一种动态调节进程权重的方法。

        1.3. 基于时间的进程调度算法

        对于那些具有稳定、已知输入的简单系统,可以使用时间驱动(Time-driven:TD)的调度算法,它能够为数据处理提供很好的预测性。这种调度算法本质上是一种设计时就确定下来的离线的静态调度方法。在系统的设计阶段,在明确系统中所有的处理情况下,对于各个任务的开始、切换、以及结束时间等就事先做出明确的安排和设计。这种调度算法适合于那些很小的嵌入式系统、自控系统、传感器等应用环境。

        这种调度算法的优点是任务的执行有很好的可预测性,但最大的缺点是缺乏灵活性,并且会出现有任务需要被执行而CPU却保持空闲的情况。

        2. 通用Linux系统中的CPU调度

        通用Linux系统支持实时和非实时两种进程,实时进程相对于普通进程具有绝对的优先级。对应地,实时进程采用SCHED_FIFO或者SCHED_RR调度策略,普通的进程采用SCHED_OTHER调度策略。

        在调度算法的实现上,Linux中的每个任务有四个与调度相关的参数,它们是rt_priority、policy、priority(nice)、counter。调度程序根据这四个参数进行进程调度。

        在SCHED_OTHER 调度策略中,调度器总是选择那个priority+counter值最大的进程来调度执行。从逻辑上分析,SCHED_OTHER调度策略存在着调度周期(epoch),在每一个调度周期中,一个进程的priority和counter值的大小影响了当前时刻应该调度哪一个进程来执行,其中 priority是一个固定不变的值,在进程创建时就已经确定,它代表了该进程的优先级,也代表这该进程在每一个调度周期中能够得到的时间片的多少; counter是一个动态变化的值,它反映了一个进程在当前的调度周期中还剩下的时间片。在每一个调度周期的开始,priority的值被赋给 counter,然后每次该进程被调度执行时,counter值都减少。当counter值为零时,该进程用完自己在本调度周期中的时间片,不再参与本调度周期的进程调度。当所有进程的时间片都用完时,一个调度周期结束,然后周而复始。另外可以看出Linux系统中的调度周期不是静态的,它是一个动态变化的量,比如处于可运行状态的进程的多少和它们priority值都可以影响一个epoch的长短。值得注意的一点是,在2.4以上的内核中, priority被nice所取代,但二者作用类似。

        可见SCHED_OTHER调度策略本质上是一种比例共享的调度策略,它的这种设计方法能够保证进程调度时的公平性--一个低优先级的进程在每一个epoch中也会得到自己应得的那些CPU执行时间,另外它也提供了不同进程的优先级区分,具有高priority值的进程能够获得更多的执行时间。

        对于实时进程来说,它们使用的是基于实时优先级rt_priority的优先级调度策略,但根据不同的调度策略,同一实时优先级的进程之间的调度方法有所不同:

        SCHED_FIFO:不同的进程根据静态优先级进行排队,然后在同一优先级的队列中,谁先准备好运行就先调度谁,并且正在运行的进程不会被终止直到以下情况发生:1.被有更高优先级的进程所强占CPU;2.自己因为资源请求而阻塞;3.自己主动放弃CPU(调用sched_yield);

        SCHED_RR:这种调度策略跟上面的SCHED_FIFO一模一样,除了它给每个进程分配一个时间片,时间片到了正在执行的进程就放弃执行;时间片的长度可以通过sched_rr_get_interval调用得到;

        由于Linux系统本身是一个面向桌面的系统,所以将它应用于实时应用中时存在如下的一些问题:

        Linux系统中的调度单位为ms,所以它不能够提供精确的定时;

        当一个进程调用系统调用进入内核态运行时,它是不可被抢占的;

        Linux内核实现中使用了大量的封中断操作会造成中断的丢失;

        由于使用虚拟内存技术,当发生页出错时,需要从硬盘中读取交换数据,但硬盘读写由于存储位置的随机性会导致随机的读写时间,这在某些情况下会影响一些实时任务的截止期限;

        虽然Linux进程调度也支持实时优先级,但缺乏有效的实时任务的调度机制和调度算法;它的网络子系统的协议处理和其它设备的中断处理都没有与它对应的进程的调度关联起来,并且它们自身也没有明确的调度机制;

        3. 各种实时Linux系统

        3.1. RT-Linux和RTAI

        RT -Linux是新墨西哥科技大学(New Mexico Institute of Technology)的研究成果[RTLinuxWeb][Barabanov]。它的基本思想是,为了在Linux系统中提供对于硬实时的支持,它实现了一个微内核的小的实时操作系统(我们也称之为RT-Linux的实时子系统),而将普通Linux系统作为一个该操作系统中的一个低优先级的任务来运行。另外普通Linux系统中的任务可以通过FIFO和实时任务进行通信。RT-Linux的框架如图 1所示:

       å›¾ 1 RT-Linux结构

       RT -Linux的关键技术是通过软件来模拟硬件的中断控制器。当Linux系统要封锁CPU的中断时时,RT-Linux中的实时子系统会截取到这个请求,把它记录下来,而实际上并不真正封锁硬件中断,这样就避免了由于封中断所造成的系统在一段时间没有响应的情况,从而提高了实时性。当有硬件中断到来时, RT-Linux截取该中断,并判断是否有实时子系统中的中断例程来处理还是传递给普通的Linux内核进行处理。另外,普通Linux系统中的最小定时精度由系统中的实时时钟的频率决定,一般Linux系统将该时钟设置为每秒来个时钟中断,所以Linux系统中一般的定时精度为 ms,即时钟周期是ms,而RT-Linux通过将系统的实时时钟设置为单次触发状态,可以提供十几个微秒级的调度粒度。

        RT-Linux实时子系统中的任务调度可以采用RM、EDF等优先级驱动的算法,也可以采用其他调度算法。

        RT -Linux对于那些在重负荷下工作的专有系统来说,确实是一个不错的选择,但他仅仅提供了对于CPU资源的调度;并且实时系统和普通Linux系统关系不是十分密切,这样的话,开发人员不能充分利用Linux系统中已经实现的功能,如协议栈等。所以RT-Linux适合与工业控制等实时任务功能简单,并且有硬实时要求的环境中,但如果要应用与多媒体处理中还需要做大量的工作。

        意大利的RTAI( Real-Time Application Interface )源于RT-Linux,它在设计思想上和RT-Linux完全相同。它当初设计目的是为了解决RT-Linux难于在不同Linux版本之间难于移植的问题,为此,RTAI在 Linux 上定义了一个实时硬件抽象层,实时任务通过这个抽象层提供的接口和Linux系统进行交互,这样在给Linux内核中增加实时支持时可以尽可能少地修改 Linux的内核源代码。

        3.2. Kurt-Linux

        Kurt -Linux由Kansas大学开发,它可以提供微秒级的实时精度[KurtWeb] [Srinivasan]。不同于RT-Linux单独实现一个实时内核的做法,Kurt -Linux是在通用Linux系统的基础上实现的,它也是第一个可以使用普通Linux系统调用的基于Linux的实时系统。

        Kurt-Linux将系统分为三种状态:正常态、实时态和混合态,在正常态时它采用普通的Linux的调度策略,在实时态只运行实时任务,在混合态实时和非实时任务都可以执行;实时态可以用于对于实时性要求比较严格的情况。

        为了提高Linux系统的实时特性,必须提高系统所支持的时钟精度。但如果仅仅简单地提高时钟频率,会引起调度负载的增加,从而严重降低系统的性能。为了解决这个矛盾, Kurt-Linux采用UTIME所使用的提高Linux系统中的时钟精度的方法[UTIMEWeb]:它将时钟芯片设置为单次触发状态(One shot mode),即每次给时钟芯片设置一个超时时间,然后到该超时事件发生时在时钟中断处理程序中再次根据需要给时钟芯片设置一个超时时间。它的基本思想是一个精确的定时意味着我们需要时钟中断在我们需要的一个比较精确的时间发生,但并非一定需要系统时钟频率达到此精度。它利用CPU的时钟计数器TSC (Time Stamp Counter)来提供精度可达CPU主频的时间精度。

        对于实时任务的调度,Kurt-Linux采用基于时间(TD)的静态的实时CPU调度算法。实时任务在设计阶段就需要明确地说明它们实时事件要发生的时间。这种调度算法对于那些循环执行的任务能够取得较好的调度效果。

        Kurt -Linux相对于RT-Linux的一个优点就是可以使用Linux系统自身的系统调用,它本来被设计用于提供对硬实时的支持,但由于它在实现上只是简单的将Linux调度器用一个简单的时间驱动的调度器所取代,所以它的实时进程的调度很容易受到其它非实时任务的影响,从而在有的情况下会发生实时任务的截止期限不能满足的情况,所以也被称作严格实时系统(Firm Real-time)。目前基于Kurt-Linux的应用有:ARTS(ATM Reference Traffic System)、多媒体播放软件等。另外Kurt-Linux所采用的这种方法需要频繁地对时钟芯片进行编程设置。

        3.3. RED-Linux

        RED -Linux是加州大学Irvine分校开发的实时Linux系统[REDWeb][ Wang],它将对实时调度的支持和Linux很好地实现在同一个操作系统内核中。它同时支持三种类型的调度算法,即:Time-Driven、 Priority-Dirven、Share-Driven。

        为了提高系统的调度粒度,RED-Linux从RT-Linux那儿借鉴了软件模拟中断管理器的机制,并且提高了时钟中断频率。当有硬件中断到来时,RED-Linux的中断模拟程序仅仅是简单地将到来的中断放到一个队列中进行排队,并不执行真正的中断处理程序。

        另外为了解决Linux进程在内核态不能被抢占的问题, RED-Linux在Linux内核的很多函数中插入了抢占点原语,使得进程在内核态时,也可以在一定程度上被抢占。通过这种方法提高了内核的实时特性。

        RED-Linux的设计目标就是提供一个可以支持各种调度算法的通用的调度框架,该系统给每个任务增加了如下几项属性,并将它们作为进程调度的依据:

        Priority:作业的优先级;

        Start-Time:作业的开始时间;

        Finish-Time:作业的结束时间;

        Budget:作业在运行期间所要使用的资源的多少;

        通过调整这些属性的取值及调度程序按照什么样的优先顺序来使用这些属性值,几乎可以实现所有的调度算法。这样的话,可以将三种不同的调度算法无缝、统一地结合到了一起。

       å¦å¤–,团IDC网上有许多产品团购,便宜有口碑

RTlinuxRTLinux的主要功能

       RTLinux提供了一整套对硬实时进程的支持函数集。以下是对在嵌入式系统中的实现的阐述:

       a. 中断仿真

       在中断控制硬件与LINUX核心之间放置一个软件仿真层。具体做法是在LINUX源码中出现cli、sti和iret的所有地方都用仿真宏:S_CLI、S_STI和S_IRET来替换。硬件中断被仿真器截获。开单平台源码当需要关中断时,就将仿真器中的一个变量置0。若有中断发生,仿真器就检查变量。如果是1(LINUX已开中断),立即调用LINUX的中断处理程序;否则,LINUX中断被禁止。所有挂起中断的处理程序会在LINUX重新开中断时被执行。这种仿真方式可以称之为"软中断"。

       b. 实时任务

       实时任务是在一个由核心控制的调度程序的调度下执行的用户定义的程序。最初,实时任务设计为ELF格式的目标文件。然而,这种方案的最大缺点是性能差。原因在于,的缓存是虚拟的,每当页表目录的基址寄存器改变时,TLB会失效。控制软件源码实时任务的上下文转换频繁,导致TLB失效严重,系统性能下降。另外,的保护级别变换耗时,尤其是陷入更高级别时需要个循环,而其它指令一般少于个循环。解决办法是使用可加载模组技术,所有的实时任务都同处于一个地址空间-内核地址空间,这不仅避免了频繁的TLB失效,同时消除了变换保护级别的消耗,而且任务转换变得容易。

       c. 进程调度

       实时系统的进程调度的主要任务是满足实时任务在时间上的要求。调度算法种类很多,没有一个策略适用于所有情况,因此采用哪种算法取决于具体应用。RT-LINUX采用的方法是允许用户编写自己的调度程序,并可以编译成模组的形式。这样可以方便地试验不同的策略和算法对于某一特定应用的适合性,从中选出最优。RT-LINUX自带的调度程序是基于优先数的抢占式调度程序,将LINUX当作具有最低优先数的实时任务。因此,展示站源码LINUX只在实时系统无任何实时任务时才运行。在从LINUX切换到实时任务时,系统记下软中断的状态并禁止软中断。在切换回来时,再恢复软中断的状态。

       d. 时钟

       调度程序需要精确的时钟才能准确操作。调度通常在特定的时刻进行任务切换。时钟的偏差会引起预定调度的偏差,导致产生被称为任务发布抖动的现象。这是一种应该尽量避免的不良现象。RT-LINUX的解决办法是,将IBM PC兼容机中的时钟芯片Intel 设置为中断开启终端计数模式。在这种模式下,精度可以达到1毫秒。这样在降低中断处理的影响的同时,获得了较高的时钟精度。

       e. IPC

       由于标准LINUX核心可以被实时任务在任意时刻抢占,实时任务无法安全地调用LINUX的程序。但是总要有一个信息交换的机制。在RT-LINUX中所用的信息交换方式是RT-FIFO(实时队列)。它与UNIX的管道非常相似,都是一个无结构的数据流。通过RT-FIFO,会员系统 源码LINUX的进程之间,实时进程之间,以及LINUX的核心与实时进程之间可以交换信息。对于一个普通的进程来说,RT-FIFO就是一个特殊的字符文件。这些文件必须自建:# for i in 0 1 2 3; do mknod /dev/rtf$i c $i; done

扩展资料

       RTLinux(AReal-Time Linux,亦称作实时Linux)是Linux中的一种实时操作系统。它由新墨西哥矿业及科技学院的V. Yodaiken开发。目前,RTLinux有一个由社区支持的免费版本,称为RTLinux Free,以及一个来自FSMLabs的商业版本,称作RTLinux Pro。

linux内核数据结构之kfifo

       Linux内核中的kfifo是一个精简且巧妙设计的环形队列,常用于解决生产者和消费者模型中的数据缓冲问题,确保数据处理的高效性。本文将探讨kfifo的数据结构、实现方法以及在并发环境下的使用。

       在项目开发中,环形缓冲区(ring buffer)作为缓存机制,通过Linux内核的kfifo实现,能够有效降低CPU与内存或磁盘之间的交互压力。kfifo利用FIFO特性,通过队列形式处理数据,android 源码 汉化避免了进程间的频繁等待。维基百科提供详细的实现方法,包括判断队列状态的技巧。

       内核的kfifo设计独具匠心,其数据结构简洁,包含in和out两个无符号变量。put和get操作通过自旋锁保证并发安全,当in或out达到最大值时,通过溢出机制实现循环使用。代码中,如put和get的memcpy调用处理边界情况,展示了缓冲区的动态变化过程。

       为了更好地理解kfifo,可以参考Linux内核源码学习资源,同时,作者还分享了一个学习交流群,其中包含了丰富的学习资料。通过编写测试程序,我们可以模拟生产者和消费者场景,验证kfifo在并发环境下的性能和稳定性。

       总结,kfifo是Linux内核中实用的环形队列,通过理解和应用,我们可以优化生产者消费者模型的性能,并在实际项目中有效利用它。

linux操作系统文件类型有哪几种,有什么区别?

       Linux文件类型常见的有:普通文件、目录文件、字符设备文件和块设备文件、符号链接文件等,现在我们进行一个简要的说明。

       1. 普通文件

       我们用 ls -lh 来查看某个文件的属性,可以看到有类似-rwxrwxrwx,值得注意的是第一个符号是 - ,这样的文件在Linux中就是普通文件。这些文件一般是用一些相关的应用程序创建,比如图像工具、文档工具、归档工具... .... 或 cp工具等。这类文件的删除方式是用rm 命令。

       2. 目录文件

       当我们在某个目录下执行,看到有类似 drwxr-xr-x ,这样的文件就是目录,目录在Linux是一个比较特殊的文件。注意它的第一个字符是d。创建目录的命令可以用 mkdir 命令,或cp命令,cp可以把一个目录复制为另一个目录。删除用rm 或rmdir命令。

       3. 字符设备或块设备文件

       区块(block)设备文件 :就是一些储存数据, 以提供系统随机存取的接口设备,举例来说,硬盘与软盘等就是啦。 你可以随机的在硬盘的不同区块读写,这种装置就是成组设备。你可以自行查一下/dev/sda看看, 会发现第一个属性为[ b ]。

       字符(character)设备文件:亦即是一些串行端口的接口设备, 例如键盘、鼠标等等。这些设备的特色就是一次性读取的,不能够截断输出。 举例来说,你不可能让鼠标跳到另一个画面,而是滑动到另一个地方。第一个属性为 [ c ]。

       4. 数据接口文件(sockets):

       数据接口文件(或者:套接口文件),这种类型的文件通常被用在网络上的数据承接了。我们可以启动一个程序来监听客户端的要求, 而客户端就可以透过这个socket来进行数据的沟通了。第一个属性为 [ s ], 最常在/var/run这个目录中看到这种文件类型了。

       5. 符号链接文件:

       当我们查看文件属性时,会看到有类似 lrwxrwxrwx,注意第一个字符是l,这类文件是链接文件。是通过ln -s 源文件名 新文件名创建的。这和Windows操作系统中的快捷方式有点相似。

kfifo(linux kernel 无锁队列)

       队列作为常见数据结构,其主要特点是先进先出(FIFO)。FIFO用于缓冲通信速度不匹配场景,例如生产者快速生成数据,消费者则难以及时处理。在通信接口驱动中,数据被暂存于队列中,驱动程序可以立即返回接收新数据或等待,而解析程序仅需从队列中获取数据。FIFO也可解决“多生产者-单消费者”问题。

       kfifo是Linux内核中实现队列功能的一种无锁环形队列。无锁意味着在单生产者单消费者场景下无需加锁操作。它通过使用in和out两个变量作为入队和出队索引来实现无锁操作,避免了在多个生产者或消费者场景下的加锁需求。通过将in/out与fifo的空间大小减一进行“与”操作,kfifo实现了比取余操作更快的队列循环。这意味着当in和out超过队列大小时,它们会继续向前加,而不是简单地减去队列大小后重新开始。

       kfifo实现“无锁”特性仅针对“单生产者-单消费者”场景。对于“多生产者”或“多消费者”情况,需对入队或出队操作进行加锁以避免数据竞争。

       使用kfifo有两种方式:动态申请和静态定义。动态申请包括包含头文件、定义结构体、申请内存、执行入队和出队操作,最后释放内存。静态定义则在定义fifo变量时使用宏,操作函数更加简洁,无需内存管理步骤。

       kfifo结构体包含用于管理队列的变量,如in、out、mask等。内存申请过程确保了用mask大小掩码与in/out索引进行“与”操作,实现队列循环,避免了取余运算的开销。使用kfifo_alloc动态申请内存时,最终分配的内存空间是向上取2的次方,以支持mask大小掩码操作。这可能导致使用者在不了解规则的情况下踩坑,例如,申请字节内存时实际上分配了字节,可能导致数据错位。

       入队操作涉及确定内存地址、拷贝数据并确保内存屏障以避免乱序异常。整个过程高效且简洁。对于更深入的了解,可查阅kfifo的源码。

相关推荐
一周热点