linux的时间管理和定时器原理
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,本篇内容主要讲解"linux的时间管理和定时器原理",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"linux的时间管理和定时器原理"吧!linux初始化的时
千家信息网最后更新 2025年12月02日linux的时间管理和定时器原理
本篇内容主要讲解"linux的时间管理和定时器原理",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"linux的时间管理和定时器原理"吧!
linux初始化的时候,初始化了定时相关的代码。
void sched_init(void)
{
...
// 43是控制字端口,0x36=0x00110110,即二进制,方式3,先读写低8位再读写高8位,选择计算器0
outb_p(0x36,0x43); /* binary, mode 3, LSB/MSB, ch 0 */
/*
写入初始值,40端口是计数通道0,初始值
的含义是,8253每一个波动,初始值会减一,减到0则输出一个通知,
LATCH = (1193180/100),1193180是8253的工作频率,
一秒钟波动1193180次。(1193180/100)就是(1193180/1000)*10,即
(1193180/1000)减到0的时候,过去了1毫秒。乘以10即过去10毫秒。
*/
outb_p(LATCH & 0xff , 0x40); /* LSB */
// 再写8位
outb(LATCH >> 8 , 0x40); /* MSB */
// 设置定时中断处理函数,中断号是20,8253会触发该中断
set_intr_gate(0x20,&timer_interrupt);
...
}
_timer_interrupt:
push %ds # save ds,es and put kernel data space
push %es # into them. %fs is used by _system_call
push %fs
pushl %edx # we save %eax,%ecx,%edx as gcc doesn't
pushl %ecx # save those across function calls. %ebx
pushl %ebx # is saved as we use that in ret_sys_call
pushl %eax
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
movl $0x17,%eax
mov %ax,%fs
incl _jiffies
movb $0x20,%al # EOI to interrupt controller #1
outb %al,$0x20
movl CS(%esp),%eax
andl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)
pushl %eax
call _do_timer # 'do_timer(long CPL)' does everything from
addl $4,%esp # task switching to accounting ...
jmp ret_from_sys_call
我们看到中断的时候执行了do_timer函数,该函数就是处理定时器和进程调度的。在此之前我们先看看怎么新增一个定时器。
#define TIME_REQUESTS 64
// 定时器数组,其实是个链表
static struct timer_list {
long jiffies;
void (*fn)();
struct timer_list * next;
} timer_list[TIME_REQUESTS], * next_timer = NULL;
void add_timer(long jiffies, void (*fn)(void))
{
struct timer_list * p;
if (!fn)
return;
// 关中断,防止多个进程"同时"操作
cli();
// 直接到期,直接执行回调
if (jiffies <= 0)
(fn)();
else {
// 遍历定时器数组,找到一个空项
for (p = timer_list ; p < timer_list + TIME_REQUESTS ; p++)
if (!p->fn)
break;
// 没有空项了
if (p >= timer_list + TIME_REQUESTS)
panic("No more time requests free");
// 给空项赋值
p->fn = fn;
p->jiffies = jiffies;
// 在数组中形成链表
p->next = next_timer;
// next_timer指向第一个节点,即最早到期的
next_timer = p;
/*
修改链表,保证超时时间是从小到大的顺序
原理:
每个节点都是以前面一个节点的到时时间为坐标,节点里的jiffies即超时时间
是前一个节点到期后的多少个jiffies后该节点到期。
*/
while (p->next && p->next->jiffies < p->jiffies) {
// 前面的节点比后面节点大,则前面节点减去后面节点的值,算出偏移值,下面准备置换位置
p->jiffies -= p->next->jiffies;
// 先保存一下
fn = p->fn;
// 置换两个节点的回调
p->fn = p->next->fn;
p->next->fn = fn;
jiffies = p->jiffies;
// 置换两个节点是超时时间
p->jiffies = p->next->jiffies;
p->next->jiffies = jiffies;
/*
到这,第一个节点是最快到期的,还需要更新后续节点的值,其实就是找到一个合适的位置
插入,因为内核是用数组实现的定时器队列,所以是通过置换位置实现插入,
如果是链表,则直接找到合适的位置,插入即可,所谓合适的位置,
就是找到第一个比当前节点大的节点,插入到他前面。
*/
p = p->next;
}
/*
内核这里实现有个bug,当当前节点是最小时,需要更新原链表中第一个节点的值,,
否则会导致原链表中第一个节点的过期时间延长,修复代码如下:
if (p->next && p->next->jiffies > p->jiffies) {
p->next->jiffies = p->next->jiffies - p->jiffies;
}
即更新原链表中第一个节点相对于新的第一个节点的偏移,剩余的节点不需要更新,因为他相对于
他前面的节点的偏移不变,但是原链表中的第一个节点之前前面没有节点,所以偏移就是他自己的值,
而现在在他前面插入了一个节点,则他的偏移是相对于前面一个节点的偏移
*/
}
sti();
}

上面是示例图。这样就完成了定时节点的插入。我们再回头看一下do_timer的代码,即系统由定时中断时执行的代码。
void do_timer(long cpl)
{
...
// 当前在用户态,增加用户态的执行时间,否则增加该进程的系统执行时间
if (cpl)
current->utime++;
else
current->stime++;
// next_timer为空说明还没有定时节点
if (next_timer) {
// 第一个节点减去一个jiffies,因为其他节点都是相对第一个节点的偏移,所以其他节点的值不需要变
next_timer->jiffies--;
// 当前节点到期,如果有多个节点超时时间一样,即相对第一个节点偏移是0,则会多次进入while循环
while (next_timer && next_timer->jiffies <= 0) {
void (*fn)(void);
fn = next_timer->fn;
next_timer->fn = NULL;
next_timer = next_timer->next;
(fn)();
}
}
...
// 进程调度
schedule();
}
我们发现,add_timer的时候已经算好了定时器的顺序是从先到期到后到期的,并且后面的节点是相对前面节点的偏移,所以判断超时的时候,只需要从前往后判断,如果第一节点没到期则后面的也不会到期,如果第一个到期,则继续判断下一个节点。把耗时的操作放到新增节点的时候,因为新增定操作是很少且不频繁的,但是定时中断是频繁的操作。所以这样就保证了性能。最后我们还发现,操作系统就是在这里通过schedule函数处理进程调度的。即没10毫秒,系统进程一次进程调度。
到此,相信大家对"linux的时间管理和定时器原理"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
节点
时间
定时器
偏移
进程
就是
时候
位置
原理
代码
函数
数组
系统
更新
置换
调度
时间管理
管理
合适
处理
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
梦幻西游天坛公园服务器
书画出版物数据库
武汉呱呱网络技术有限公司
县委办网络技术干啥
信息网络安全监察专业内容
自动化交易炒股软件开发
怎样读取数据库文件
查看服务器名称
佛山分布式服务器价格
软件开发合同第一笔款比例
学校网络安全台帐
云服务器如何部署企业网站
saas系统的数据库用什么软件
接入他人数据库的技术原理论文
科技金融互联网公司官网
数据库配置源码
现成的数据库代码
四川服务器5g网络机柜云空间
成都非外包软件开发公司
vb 随机数据库
laravel数据库多库
wdcp数据库恢复
怎么利用服务器做成直链下载
我的世界服务器无限生成矿物
墨菲网络技术有限公司
科技金融互联网公司官网
ensp怎么创建服务器组
web服务器日志在哪
汽车车型配件数据库
ios王者登不上微信服务器