一些内核定时API (1)

本文介绍了Linux内核中的一些定时API,包括创建和管理软件定时器、获取系统时间、设置系统时间等。通过示例代码展示了如何使用init_timer、add_timer、del_timer等函数操作定时器,并解释了相关结构体如struct timer_list的功能。此外,还提供了获取和设置时间的函数如get_seconds、mktime等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//创建一个软件定时器
static struct timer_list my_timer;//定义一个软件定时器
   struct timer_list {  
struct list_head entry;          //定时器链表的入口  
unsigned long expires;           //定时器超时时的节拍数  
void (*function)(unsigned long); //【重要】定时器处理函数  
unsigned long data;              //传给定时器处理函数的长整型参数  
struct tvec_t_base_s *base;      //定时器内部值,用户不使用  
#ifdef CONFIG_TIMER_STATS  
void *start_site;  
char start_comm[16];  
int start_pid;  
#endif  
};  
           
   void my_timer_function(...);//定义自己的软件定时器函数
           
   init_timer(&my_timer);
           my_timer.function=my_timer_function;


   add_timer(my_timer);


//获得当前系统内核的时间,该时间是距离1970年1月1日0时0分0秒的时间,用秒和纳秒表示
//timespec里面是秒和纳秒
struct timespec current_kernel_time(void)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 now;
unsigned long seq;


do {
seq = read_seqcount_begin(&tk_core.seq);


now = tk_xtime(tk);
} while (read_seqcount_retry(&tk_core.seq, seq));


return timespec64_to_timespec(now);
}


//用于将非活跃状态的定时器从动态定时器链表中删除
//返回1说明删除成功,返回0说明定时器正在执行或已经不存在,删除无效
int del_timer(struct timer_list *timer);


//获取当前系统内核时间,保存再tv结构体中,距离1970.1.1 00:00:00的秒差
void do_gettimeofday(struct timeval *tv)
{
struct timespec64 now;


getnstimeofday64(&now);
tv->tv_sec = now.tv_sec;
tv->tv_usec = now.tv_nsec/1000;
}


//设定系统内核时间,设定为 ts 所代表的时间,距离1970的秒数
int do_settimeofday64(const struct timespec64 *ts)
{
struct timekeeper *tk = &tk_core.timekeeper;
struct timespec64 ts_delta, xt;
unsigned long flags;


if (!timespec64_valid_strict(ts))
return -EINVAL;


raw_spin_lock_irqsave(&timekeeper_lock, flags);
write_seqcount_begin(&tk_core.seq);


timekeeping_forward_now(tk);


xt = tk_xtime(tk);
ts_delta.tv_sec = ts->tv_sec - xt.tv_sec;
ts_delta.tv_nsec = ts->tv_nsec - xt.tv_nsec;


tk_set_wall_to_mono(tk, timespec64_sub(tk->wall_to_monotonic, ts_delta));


tk_set_xtime(tk, ts);


timekeeping_update(tk, TK_CLEAR_NTP | TK_MIRROR | TK_CLOCK_WAS_SET);


write_seqcount_end(&tk_core.seq);
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);


/* signal hrtimers about time change */
clock_was_set();


return 0;
}


//获得当前系统内核的时间,距离1970的整秒数
unsigned long get_seconds(void)
{
struct timekeeper *tk = &tk_core.timekeeper;


return tk->xtime_sec;
}


//初始化一个timer_list变量,将此定时器插入到内核定时器模块中,并确定由哪个cpu处理
static struct timer_list my_timer;//定义一个软件定时器
init_timer(&my_timer);


//计算输入的年月日时分秒距离1970的秒数
static inline unsigned long mktime(const unsigned int year,
                       const unsigned int mon,
   const unsigned int day,
                       const unsigned int hour, 
   const unsigned int min,
                       const unsigned int sec
  )
{
return mktime64(year, mon, day, hour, min, sec);
}


//更改定时器的到期时间,使定时器timer执行新的expires
//返回1 修改成功;返回0 修改失败
int mod_timer(struct timer_list *timer,unsigned long expires);
=//等价于
del_timer(my_timer);
my_timer->expires=expires;
add_timer(timer);


//将一个64位有符号整数 nsec 转成 timespec 结构体时间
struct timespec ns_to_timespec(const s64 nsec)
{
struct timespec ts;
s32 rem;


if (!nsec)
return (struct timespec) {0, 0};


ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
if (unlikely(rem < 0)) {
ts.tv_sec--;
rem += NSEC_PER_SEC;
}
ts.tv_nsec = rem;


return ts;
}


//将一个64位有符号整数 nsec 转成 timeval 结构体时间
struct timeval ns_to_timeval(const s64 nsec)
{
struct timespec ts = ns_to_timespec(nsec);
struct timeval tv;


tv.tv_sec = ts.tv_sec;
tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000;


return tv;
}


//将秒 sec 和纳秒 nsec 转换成 timespec 变量表示的时间
void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec)
{
while (nsec >= NSEC_PER_SEC) {
asm("" : "+rm"(nsec));
nsec -= NSEC_PER_SEC;
++sec;
}
while (nsec < 0) {
asm("" : "+rm"(nsec));
nsec += NSEC_PER_SEC;
--sec;
}
ts->tv_sec = sec;
ts->tv_nsec = nsec;
}


//用于测试动态定时器的状态是否处于活跃态
//0-活跃 1-非活跃
static inline int timer_pending(const struct timer_list *timer)
{
return timer->entry.next != NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值