基于linux0.11操作系统定时器的原理分析
发表于:2025-02-23 作者:千家信息网编辑
千家信息网最后更新 2025年02月23日,今天就跟大家聊聊有关基于linux0.11操作系统定时器的原理分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。操作系统的定时器原理是,操作系
千家信息网最后更新 2025年02月23日基于linux0.11操作系统定时器的原理分析
今天就跟大家聊聊有关基于linux0.11操作系统定时器的原理分析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
操作系统的定时器原理是,操作系统维护了一个定时器节点的链表,新增一个定时器节点时,设置一个jiffies值,这是触发定时中断的频率。linux0.11版本里是1秒触发100次,即10毫秒一次。加入新增一个定时器的jiffies值是2,那经过两次定时中断后就会被执行。jiffies值在每次定时中断时会加一。
_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 ...
下面是定时器的结构图
#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();
}
// 定时中断处理函数
void do_timer(long cpl)
{
extern int beepcount;
extern void sysbeepstop(void);
if (beepcount)
if (!--beepcount)
sysbeepstop();
// 当前在用户态,增加用户态的执行时间,否则增加该进程的系统执行时间
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)();
}
}
if (current_DOR & 0xf0)
do_floppy_timer();
// 当前进程的可用时间减一,不为0则接着执行,否则可能需要重新调度
if ((--current->counter)>0) return;
current->counter=0;
// 是系统进程则继续执行
if (!cpl) return;
// 进程调度
schedule();
}
看完上述内容,你们对基于linux0.11操作系统定时器的原理分析有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。
节点
定时器
时间
偏移
系统
位置
进程
操作系统
原理
数组
更新
置换
合适
内容
就是
分析
两个
内核
函数
多个
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
可以进行引文检索的数据库是
对dba加密的数据库
迎风起航服务器
京东有几个服务器
免费下载软件开发报价方案
美孚公司网络安全事件
网络安全三级认证流程
济南地区联想服务器代理测评
社区居民数据库多色可选
数据中心要解决服务器散热问题
mmi软件开发工程师是干啥的
龙胜万合天宜互联网科技
深圳中辉互联网科技怎么样
逻辑数据库与什么相对
小吃技术创业数据库
至强服务器cpu主频3G
数据库疾病编码
windos服务器多台管理
软件开发工程师 什么级别
安全关键软件开发与审定电子书
ob9数据库
数据库连表查询语句左联
网络安全法禁止渗透入侵
云服务器 企商在线
nfs服务器导出的文件
华为5g数据库在哪里
深圳股票自动交易软件开发
地平线无法连接到内容服务器
北京软件开发招聘网
九江优客软件开发有限公司