深入探究:Linux中hrtimer的应用技巧(linuxhrtimer用法)

随着计算机技术的不断发展,现代操作系统的软实时性越来越得到重视。Linux作为一种主流的开源操作系统,其内核设计的软实时性能也得到了广泛认可。其中,hrtimer是一个重要的软实时性能优化工具,能够实现高精度的定时器管理。本文将深入探究Linux中hrtimer的应用技巧,为读者提供关于hrtimer的基础知识和常见用法,帮助读者更好地优化软实时性能。

成都创新互联公司主要从事成都网站设计、成都网站制作、网页设计、企业做网站、公司建网站等业务。立足成都服务敖汉,十年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:18980820575

什么是hrtimer?

在深入探究hrtimer的应用技巧之前,我们需要了解什么是hrtimer。

hrtimer本质上是一种定时器,其中“hr”是high-resolution的缩写,表示高分辨率。与传统定时器不同的是,hrtimer能够实现高精度的定时,达到微秒级甚至纳秒级的时间精度。同时,hrtimer还能够进行周期性定时,因此它被广泛应用于实时性要求较高的场景。

hrtimer主要应用于Linux内核中,可以用来进行内核线程调度、延迟计算、网络协议等场景。同时,hrtimer还被广泛应用于Linux下的各种实时操作系统和实时应用程序中。

hrtimer的基本使用方法

理解了hrtimer的概念和作用之后,接下来我们将介绍hrtimer的基本使用方法。

hrtimer的使用分为两个阶段:创建hrtimer和注册hrtimer。

1. 创建hrtimer

hrtimer的创建需要使用hrtimer_init函数,该函数定义如下:

“`

void hrtimer_init(struct hrtimer *timer, clockid_t which_clock, enum hrtimer_mode mode);

“`

其中,timer是要创建的hrtimer实例,which_clock是时钟源,mode是定时器的模式。

2. 注册hrtimer

hrtimer注册需要使用hrtimer_start或hrtimer_forward函数,这两个函数分别用于启动或重置定时器。它们的定义如下:

“`

int hrtimer_start(struct hrtimer *timer, const ktime_t expires, const enum hrtimer_mode mode);

void hrtimer_forward(struct hrtimer *timer, ktime_t now, const ktime_t interval);

“`

其中,timer是要注册的hrtimer实例,expires是定时器的到期时间,mode是定时器的模式。

除此之外,hrtimer还有一些常用的属性和方法,如下:

– hrtimer_cancel:取消定时器注册

– hrtimer_get_residue:获取剩余时间

– hrtimer_get_expires:获取下次到期时间

– hrtimer_restart:重新启动定时器

hrtimer应用技巧

了解了hrtimer的基本使用方法之后,我们来看一些hrtimer的实际应用技巧。

1. 定时管理

在实际应用中,有许多场景需要进行定时管理,比如延迟计算、周期性任务等。此时,hrtimer就能够派上用场。

比如下面的代码中,我们使用hrtimer启动一个定时器,当定时器到期时输出“hello world”。这个例子展示了如何使用hrtimer进行定时管理:

“`

#include

#include

#include

static struct hrtimer hr_timer;

enum hrtimer_restart timer_callback(struct hrtimer *timer)

{

printk(KERN_INFO “Hello world\n”);

hrtimer_forward(timer, ktime_get(), ktime_set(0, 1000000));

return HRTIMER_RESTART;

}

int init_module(void)

{

ktime_t ktime = ktime_set(0, 1000000);

hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

hr_timer.function = &timer_callback;

hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL);

return 0;

}

void cleanup_module(void)

{

hrtimer_cancel(&hr_timer);

}

MODULE_LICENSE(“GPL”);

“`

2. 内核线程调度

线程调度是Linux内核的一项重要功能,它能够让内核按照某种策略动态地分配CPU时间给各个线程。在实际应用中,可以通过hrtimer来实现内核线程调度。

比如下面的代码中,我们使用hrtimer代替传统的定时器来调度内核线程。具体来说,当定时器到期时,会唤醒对应的内核线程,从而实现线程调度:

“`

#include

#include

#include

#include

static enum hrtimer_restart timer_callback(struct hrtimer *timer);

struct task_struct *task;

static struct hrtimer hr_timer;

enum hrtimer_restart timer_callback(struct hrtimer *timer)

{

wake_up_process(task);

hrtimer_forward(timer, ktime_get(), ktime_set(0, 1000000));

return HRTIMER_RESTART;

}

int thread_fn(void *data)

{

printk(KERN_INFO “I’m in\n”);

while (!kthread_should_stop()) {

set_current_state(TASK_INTERRUPTIBLE);

schedule();

printk(KERN_INFO “awaken\n”);

}

printk(KERN_INFO “I’m out\n”);

return 0;

}

int init_module(void)

{

ktime_t ktime = ktime_set(1, 0);

hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

hr_timer.function = &timer_callback;

hrtimer_start(&hr_timer, ktime, HRTIMER_MODE_REL);

task = kthread_create(&thread_fn, NULL, “my_thread”);

wake_up_process(task);

return 0;

}

void cleanup_module(void)

{

hrtimer_cancel(&hr_timer);

kthread_stop(task);

}

MODULE_LICENSE(“GPL”);

“`

3. 延迟计算

延迟计算是一种实时性要求较高的场景。利用hrtimer,我们可以实现高精度的延迟计算。比如下面的代码中,我们使用hrtimer实现一个每隔10ms打印一次时间戳的程序:

“`

#include

#include

#include

#include

static struct hrtimer hr_timer;

static ktime_t kt_period;

enum hrtimer_restart timer_callback(struct hrtimer *timer)

{

ktime_t currtime, remnder;

currtime = ktime_get();

printk(KERN_INFO “%lld.%lld\n”, (long long)currtime.tv_sec, (long long)currtime.tv_nsec);

remnder = ktime_sub(kt_period, ktime_get());

hrtimer_forward_now(timer, remnder);

return HRTIMER_RESTART;

}

int init_module(void)

{

kt_period = ktime_set(0, 10000000); // 10ms

hrtimer_init(&hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

hr_timer.function = &timer_callback;

hrtimer_start(&hr_timer, kt_period, HRTIMER_MODE_REL);

return 0;

}

void cleanup_module(void)

{

hrtimer_cancel(&hr_timer);

}

MODULE_LICENSE(“GPL”);

“`

成都网站建设公司-创新互联,建站经验丰富以策略为先导10多年以来专注数字化网站建设,提供企业网站建设,高端网站设计,响应式网站制作,设计师量身打造品牌风格,热线:028-86922220

linux 中断 下半部 处理时间过长 怎么办

linux中断的命令是“ctrl+c”这个就茄漏早是命令搜哗。建议在使用的时候使用linux后台管理命令,这样任务操作两不误,这个就是linux的多任务操颤雀作。具体命令可以参考linux就该这样学一书,希望能够帮助你

一、中断处理为什么要下半部?

Linux在中断处理中间中断处理分了上半部和下半部,目的就是提高系统的响应能力和并发能力。通俗一点来讲:当一个中断产生,调用该中断对应的处理程序(上半部)然后告诉系统,对应的后半部可以执行了。然后中断处理程序就返回,下半部会在合适的时机有系统调用。这样一来就大大的减少了中断处理所需要的时间。

二、那些工作应该放在上半部,那些应该放在下半部?

没有严格的规则,只有一些提示:

1、对时间非常敏感,放在上半部。

2、与硬件相关的,放在上半部。

3、不能被其他中断打断的工作,放在上半部。

以上三点之外的,考虑放在下半部。

三、下半部机制在Linux中是怎么实现的?

下半部在Linux中有以下实现机制:

1、BH(在2.5中删除)

2、任务队列(task queue,在2.5删除)

3、软中断(softirq,2.3开始。本文重点)

4、tasklet(2.3开始)

5、工作队列(work queue,2.5开始)

四、软中断是怎么实现的(以下代码出自2.6.32)?

软中断不会抢占另外一个软中断,唯一可以抢占软中断的是中断处理程序。

软中断可以在不同CPU上并发执行(哪怕是同一个软中断)

1、软中断是编译期间静态分配的,定义如亩源下:

struct softirq_action { void (*action)(struct softirq_action *); };

/*

* PLEASE, avoid to allocate new softirqs, if you need not _really_ high

* frequency threaded job scheng. For almost all the purposes

* tasklets are more than enough. F.e. all serial device BHs et

* al. should be converted to tasklets, not to softirqs.

*/

enum {

HI_SOFTIRQ=0,

TIMER_SOFTIRQ,

NET_TX_SOFTIRQ,

NET_RX_SOFTIRQ,

BLOCK_SOFTIRQ,

BLOCK_IOPOLL_SOFTIRQ,

TASKLET_SOFTIRQ,

SCHED_SOFTIRQ,

HRTIMER_SOFTIRQ,

RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */

NR_SOFTIRQS

};

/*

* map softirq index to softirq name. update ‘softirq_to_name’ in * kernel/softirq.c when adding a new softirq.

*/

extern char *softirq_to_name;

static struct softirq_action softirq_vec __cacheline_aligned_in_p;

说明:

(1)、软中断的个数书上说是32,看来到这个版本已经发生变化了。

(2)、void (*action)(struct softirq_action *);传递整个结构体指针在于当结构体成员发生变化是,接口不变。

2、系统执行软中断一个注册的软中断必须被标记后才会执行(触发软中断),通常中断处理程序会在返回前标记它的软中断。在下列地方,待处理的软中断会被执行:

(1)、从一个硬件迅悉态中断代码处返回。

(2)、在ksoftirqd内核线程。

(3)、在那些显示检查和执行待处理的软中断代码中。

ksoftirqd说明:

每个处理器都有一个这样的线程。所有线程的名字都叫做ksoftirq/n,区别在于n,它对应的是处理器的编号。在一个双CPU的机器上就有两个这样陆世的线程,分别叫做ksoftirqd/0和ksoftirqd/1。为了保证只要有空闲的处理器,它们就会处理软中断,所以给每个处理器都分配一个这样的线程。

执行软中断的代码如下:

alinkage void __do_softirq(void)

{

struct softirq_action *h;

__u32 pending;

int max_restart = MAX_SOFTIRQ_RESTART;

int cpu;

pending = local_softirq_pending();

account_system_vtime(current);

__local_bh_disable((unsigned long)__builtin_return_address(0));

lockdep_softirq_enter();

cpu = p_processor_id();

restart:

/* Reset the pending bitmask before enabling irqs */

set_softirq_pending(0);

local_irq_enable();

h = softirq_vec;

do {

if (pending & 1) {

int prev_count = preempt_count();

kstat_incr_softirqs_this_cpu(h – softirq_vec);

trace_softirq_entry(h, softirq_vec);

h->action(h);

trace_softirq_exit(h, softirq_vec);

if (unlikely(prev_count != preempt_count())) {

printk(KERN_ERR “huh, entered softirq %td %s %p”

“with preempt_count %08x,”

” exited with %08x?\n”, h – softirq_vec,

softirq_to_name,

h->action, prev_count, preempt_count());

preempt_count() = prev_count;

}

rcu_bh_qs(cpu);

}

h++;

pending >>= 1;

} while (pending);

local_irq_disable();

pending = local_softirq_pending();

if (pending && –max_restart)

goto restart;

if (pending)

wakeup_softirqd();

lockdep_softirq_exit();

account_system_vtime(current);

_local_bh_enable();

}

3、编写自己的软中断

(1)、分配索引,在HI_SOFTIRQ与NR_SOFTIRQS中间添加自己的索引号。

(2)、注册处理程序,处理程序:open_softirq(索引号,处理函数)。

(3)、触发你的软中断:raise_softirq(索引号)。

4、软中断处理程序注意

(1)、软中断处理程序执行的时候,允许响应中断,但自己不能休眠。

(2)、如果软中断在执行的时候再次触发,则别的处理器可以同时执行,所以加锁很关键。

加入等待队列,等系统有空的时候执行

kill -9 强制杀死!!!

linux hrtimer用法的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux hrtimer用法,深入探究:Linux中hrtimer的应用技巧,linux 中断 下半部 处理时间过长 怎么办的信息别忘了在本站进行查找喔。

成都网站建设选创新互联(☎:028-86922220),专业从事成都网站制作设计,高端小程序APP定制开发,成都网络营销推广等一站式服务。

名称栏目:深入探究:Linux中hrtimer的应用技巧(linuxhrtimer用法)
文章源于:http://www.stwzsj.com/qtweb/news33/15133.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联