您的位置 首页 资料

根据Linux2.6内核的实时性增强方案设计

基于Linux2.6内核的实时性增强方案设计-Linux以其功能强大、源代码开放、支持多种硬件平台、模块化设计方案以及丰富的开发工具支持等特点广泛应用在嵌入式系统领域。作为嵌入式产品的操作系统平台,具有较好的实时性、系统可靠性、任务处理随机性是系统追求的目标,目前商业嵌入式操作系统实时性能可以满足嵌入式领域的需求,但由于其价格昂贵,应用受到了限制。而嵌入式Linux以其非常低廉的价格,可以大大地降低成本,逐渐成为嵌入式操作系统的首选。但由于其在实时应用领域的技术障碍,要应用在嵌入式领域,还必须对Linux内核作必要的改进。本文以S3C2410+Linux作为移动机器人操作平台,为了提高机器人任务处理的实时性,针对影响Linux OS实时性能的若干方面进行研究,并利用相应的解决方法基于标准Linux2.6内核加以实现,最后通过测试,验证了此改进方法的效果。

Linux以其功用强大、源代码敞开、支撑多种硬件渠道、模块化规划计划以及丰厚的开发工具支撑等特色广泛运用在嵌入式体系范畴。作为嵌入式产品的操作体系渠道,具有较好的实时性、体系可靠性、使命处理随机性是体系寻求的方针,现在商业嵌入式操作体系实时功用能够满意嵌入式范畴的需求,但因为其价格昂贵,运用受到了约束。而嵌入式Linux以其十分低价的价格,能够大大地降低成本,逐步成为嵌入式操作体系的首选。但因为其在实时运用范畴的技能妨碍,要运用在嵌入式范畴,还有必要对Linux内核作必要的改善。本文以S3C2410+Linux作为移动机器人操作渠道,为了进步机器人使命处理的实时性,针对影响Linux OS实时功用的若干方面进行研究,并运用相应的解决办法根据规范Linux2.6内核加以完结,最终经过测验,验证了此改善办法的作用。

根据Linux2.6内核的实时性增强计划规划

1 Linux内核实时性剖析

1.1 Linux内核限制实时性的要素

衡量操作体系实时性的目标首要有中止推迟和抢占推迟。嵌入式体系中许多实时使命是靠中止驱动的,中止事情有必要在限制的时限内处理,否则将产生灾难性的成果。大多数实时体系都是处理一些周期性的或非周期性的重复事情,事情产生的频度就确认了使命的履行时限,因而每次事情产生时,相应的处理使命有必要及时呼应处理,否则将无法满意时限 。抢占推迟就反映了体系的呼应及时程度。针对Linux内核,中止封闭及中止优先级履行机制、内核不行抢占性、自旋锁(spinlock)及大内核锁及一些O(n)的使命调度算法影响了体系的实时功用。

1.2 现存增强Linux内核实时性的技能

多年来,Linux实时性改善技能的开展首要有两种技能计划:(1)直接批改Linux内核。针对内核数据结构、调度函数、中止办法进行改动,从头规划一个由优先级驱动的实时调度器,替换原有Linux内核中的进程调度器sched.c。这一计划首要是针对中止机制、使命调度算法进行改善的,较为成功的事例为Kansas大学开发的Kurt-Linux。Kurt进步了Linux体系中的实时精度,将时钟芯片设置为单触发状况。关于实时使命的调度,Kurt-Linux选用根据时刻的静态实时CPU调度算法。实时使命在规划阶段就需要明确地阐明其实时事情要产生的时刻。这种调度算法关于那些循环履行的使命能够获得较好的调度作用;(2)在Linux内核之外进行实时性扩展,添加一个实时内核。实时内核接收硬件一切中止,并根据是否为实时使命给予呼应。Fsm Labs公司开发的RTLinux便是根据这种战略开发规划的 。以上论说的两种技能计划有其可学习之处,但假如归纳考虑使命呼应、内核可抢占性、实时调度战略等都将影响操作体系的实时功用,因而,这两种技能还不能很好地满意实时性要求。为了增强嵌入式Linux实时功用,下面将介绍中止机制、内核的抢占性以及大内核锁等相关问题。

2 Linux实时性改善办法

Linux2.4及曾经版别内核是不行抢占的,在Linux2.6中,内核现已能够抢占,实时性有所增强。可是内核中依然有不行抢占的区域,如自旋锁spinlock维护的临界区等。其他,影响内核实时功用的要素还有中止运转机制、大内核锁机制以及调度算法等。

2.1 中止运转机制改善

在Linux规范内核中,中止是最高优先级的履行单元,硬件架构决议了硬件中止到来的时分在该中止没有被屏蔽的条件下有必要处理。不论内核其时处理什么,即便是Linux中最高优先级的实时进程,只需有中止产生,体系将当即呼应该事情并履行相应的中止处理程序,这就大大削弱了Linux的实时功用。特别是体系有严峻的网络或I/O负载时,中止将十分频频,实时使命将很难有时机运转,这关于Linux的实时运用来说是不行承受的。Linux选用的关中止技能在关中止区域使相应实时使命得不到呼应,添加了实时使命的中止推迟。Linux实时化后自旋锁变为互斥锁的技能,但因为自旋锁的中止处理不能及时呼应,降低了体系的实时功用。因而,学习Ingo Molnar实时补丁的实时化办法,选用中止线程化技能改善中止运转机制,中止将作为内核线程运转并且赋予不同的实时优先级,实时使命能够有比中止线程更高的优先级,这样,实时使命就能够作为最高优先级的履行单元来运转了,即便在严峻负载下仍有实时性确保。另一方面,中止处理线程也能够因为在内核同步中得不到锁而挂载到锁的等候行列中,许多关中止就不用真实的制止硬件中止了,而是制止内核进程抢占,然后减小了中止推迟 。

在初始化阶段,惯例中止初始化和中止线程化的初始化在start_kernel( )函数中都调用trap_init( )和init_IRQ( )两个函数来初始化irq_desc_t结构体,差异首要体现在内核初始化创立init线程时,中止线程化的中止在init( )函数中还将调用init_hardirqs(kernel/irq/manage.c)来为每一个IRQ创立一个内核线程,最高实时优先级为50,顺次类推直到25。因而,任何IRQ线程的最低实时优先级为25,详细完结是经过kthread_create函数创立的。功用完结等同于如下代码:

void __init init_hardirqs(void)

{ ……

for (i = 0; i 《 NR_IRQS; i++) {

//关于每一个中止树立一个中止线程

irq_desc_t *desc = irq_desc + i;

if(desc-》action && !(desc-》status & IRQ_NODELAY))

//有IRQ_NODELAY标志的中止不允许线程化

desc-》thread = kthread_create(do_irqd,

desc, “IRQ %d”, irq); //树立线程

……

}

}

staTIc int do_irqd(void * __desc)

//分配中止线程优先级50~25

{ ……

/*Scale irq thread prioriTIes from prio 50 to prio 25 */

param.sched_priority = curr_irq_prio;

if (param.sched_priority 》 25)

curr_irq_prio = param.sched_priority – 1;

……

}

在中止处理阶段当中止产生时,CPU调用do_IRQ( )函数来处理中止,do_IRQ( )在做了必要的相关处理之后调用_do_IRQ( )。_do_IRQ( )首要功用为判别该中止是否现已被线程化(核对终端描述符的状况字段是否包括IRQ_NODELAY标志),关于没有线程化的中止,将直接调用 handle_IRQ_event( )函数来处理。功用完结等同于如下代码:

fastcall notrace unsigned int __do_IRQ(unsigned int irq,

struct pt_regs *regs)

{ ……

if (redirect_hardirq(desc))

//检测是否为线程化中止,若是则唤醒中止线程

goto out_no_end;

……

acTIon_ret = handle_IRQ_event(irq, regs, acTIon);

//处理非线程化中止

……

}

int redirect_hardirq(struct irq_desc *desc)

//检测irq_desc结构体,判别是否线程化

{ ……

if (!hardirq_preemption || (desc-》status & IRQ_

NODELAY) || !desc-》thread)

return 0;

……

if (desc-》thread && desc-》thread-》state != TASK_

RUNNING)

wake_up_process(desc-》thread);

……

}

针对已线程化的状况,调用wake_up_process( )函数唤醒中止处理线程履行,内核线程将调用do_hardirq( )来处理相应的中止。详细完结是经过handle_IRQ_event( )函数直接调用相应的中止处理函数完结的。关于紧迫的中止(如时钟中止),内核坚持本来的中止处理办法,而不为其创立中止线程,这样就确保了紧迫中止的快速呼应。

2.2 内核可抢占性规划

在Linux规范内核中,因不具有可抢占性和导致较大的推迟,添加内核的可抢占功用,可进步体系的实时使命处理才能。当时批改Linux内核进步实时性的办法首要有添加抢占点和改构成抢占式内核两种办法。添加抢占点办法是在内核中刺进抢占点,经过检测抢占点调度标志来决议是否进行实时使命的调度。选用这种办法,在检测抢占点标志时大大添加了体系开支,因而本计划选用直接改造Linux内核的办法,经过批改自旋锁为互斥锁来进步内核的可抢占性  。即学习Ingo Molnar的实时补丁的实时化办法,运用mutex互斥锁来替换spinlock自旋锁。运用mutex替换spinlock,能够让spinlock 可抢占。起先spinlock不行抢占性规划意图是避免死锁,可抢占性规划或许导致竞赛者与坚持者的死锁局势。中止处理函数中也能够运用 spinlock,假如spinlock现已被某一进程坚持,则中止处理函数无法进行,然后构成死锁。中止线程化今后,中止线程将挂在等候行列上并抛弃 CPU让其他线程或进程来运转,让每个spinlock都有一个等候行列,该等候行列按进程或线程优先级排队,假如一个进程或线程竞赛的spinlock 现已被另一个线程坚持,它将把自己挂在该spinlock的优先级化的等候行列上,然后产生调度把CPU让给其他进程或线程。mutex替换 spinlock后,spinlock结构界说如下代码:

typedef struct {

struct rt_mutex lock; //新的实时互斥锁

unsigned int break_lock;

} spinlock_t;

其间struct rt_mutex结构如下:

struct rt_mutex {

raw_spinlock_t wait_lock;

struct plist wait_list; //优先级等候行列

struct task_struct *owner; //具有该锁进程的信息

int owner_prio;

… …

};

在如上代码中,类型raw_spinlock_t便是本来的spinlock_t。即代码中的spinlock_t便是新规划的自旋锁。rt_mutex 结构中,wait_list字段为优先级等候行列。在mutex运用中,当遇到锁住的临界资源时,使命被挂起到wait_list中,临界资源解锁时等候使命被激活。临界资源被维护的一起能够抢占。

因为Linux内核底层的临界资源是不行抢占的,运用mutex替换spinlock的过程中,这部分能够保存,仍由不行抢占的spinlock维护,如:维护硬件寄存器的锁、调度器的运转行列锁等。不行抢占的spinlock被从头命名为raw_spinlock_t。spin_lock被宏界说为:

#define spin_lock(lock) PICK_OP(raw_spinlock_t,spin,_lock,lock)

函数PICK_OP支撑两种锁共存机制,PICK_OP在编译阶段将锁操作转化为mutex或许spinlock:

#define PICK_OP(type, optype, op, lock) \

do { \

if (TYPE_EQUAL((lock), type)) \

_raw_##optype##op((type *)(lock)); \

else if (TYPE_EQUAL(lock, spinlock_t)) \

//调用gcc的内嵌函数__builtin_types_compatible_p()

_spin##op((spinlock_t *)(lock)); \

else __bad_spinlock_type(); \

} while (0)

#define TYPE_EQUAL(lock, type) \

__builtin_types_compatible_p(typeof(lock), type *)

gcc的内嵌函数__builtin_types_compatible_p用于判别一个变量的类型是否为某指定的类型,假如类型为 spinlock_t,将运转函数_spin_lock;类型为raw_spinlock_t,将运转函数_raw_spin_lock。

实时rt_mutex在详细运用中,一个高优先级使命抢占该锁的一起,把从前的锁具有者添加到互斥锁等候行列中,并在当时具有该锁的使命 task_struct中符号等候该锁的一切使命;反之,不能得到该锁就把当时使命添加到锁的优先级等候行列中,直到唤醒履行。为了避免优先级反转,能够改动锁的当时具有者的优先级为锁的等候行列中使命的最高优先级。

rt_mutex能够使高优先级使命运用抢占锁进入临界区,这样内核不行抢占区的数量和规模大大缩小,内核可抢占性有了很大的进步,且降低了实时高优先级使命的抢占推迟,改善了体系的实时功用。

2.3 可抢占大内核锁规划

大内核锁BKL(Big Kernel Lock)实质上也是spinlock,它用于维护整个内核,该锁坚持时刻较长,对体系的实时功用影响很大 。选用Ingo Molnar的实时化办法,BKL运用semaphore完结,结构界说如下代码:

struct semaphore {

atomic_t count;

struct rt_mutex lock; //实时互斥锁的运用

};

由结构体发现,在BKL完结中运用了实时互斥锁rt_mutex,在改善后的spinlock结构体spinlock_t中也运用了实时互斥锁 rt_mutex,因而可抢占大内核锁和新的spinlock共用了低层的处理代码。运用semaphore之后,大内核锁就可抢占了。

3 内核实时性测验

针对Linux2.6内核,本文并没有作出对内核调度算法的批改,仅仅探讨了中止运转机制、自旋锁及大内核锁技能在体系实时功用上的局限性,所以试验测验首要测验中止推迟时刻和使命呼应时刻。试验环境: Intel 2 GHz CPU,256 DDR内存,Kernel 2.6.22版别。测验成果。

由表可知,在中止服务程序中写入符号,测验中止触发至中止服务程序履行均匀呼应时刻,规范Linux2.6内核均匀中止呼应时刻为182 μs,改善后Linux2.6内核为14 μs。选用开源软件LMbench3.0 测验体系使命调度推迟时刻,规范Linux2.6内核均匀使命呼应时刻为1 260 μs,改善后Linux2.6内核为162μs。由此可见,改善战略在必定程度上大大减小了中止推迟和使命调度时刻,有利于改善移动机器人使命处理的实时功用。

本文根据Linux2.6内核的关中止、中止优先级、内核的不行抢占性以及大内核锁坚持时刻过长等问题进行了实时性剖析,提出了相应的改善办法。运用中止线程化、互斥锁的运用及大内核锁的改善等技能进步了体系的实时功用,降低了内核中止推迟和调度推迟。改善后的内核在移动机器人操控器渠道中有很好的运用价值,进步了机器人操控的实时功用。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/100635.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部