linux内核分析笔记----定时器和时间管理

LInux编程 解决X11定时器因系统时间改变而失效的缺陷 timer_create使用 最近公司用了20年的产品,被客户抱怨莫名其妙的图像定在那里,过了好几分钟才恢复正常。经研究发现是因为X11的定时器存在缺陷,每次注册定时器下次执行的时间时,使用的是系统时间,如果系统时间被修改为较早的时间,则定时器任务不会被触发,得系统时间走到注册时间才会触发。 于是我进行了研究,刚开始考虑用线程加sleep来模拟定时器,后面查阅了资料发现,Linux内核也有定时器接口timer_create,并且它强大之处是可以选择定时器创建的时钟模式,我选用了CLOCK_MONOTONIC模式,即... 阅读详情

      在这一次里,主要讲讲和时间相关的东西,这个我们都比较熟悉,我就直接如主题。

      首先要明白两个概念:系统定时器和动态定时器。周期性产生的事件都是有系统定时器驱动的,这里的系统定时器是一种可编程硬件芯片,它能以固定频率产生中断。该中断就是定时器中断,它所对应的中断处理程序负责更新系统时间,也负责执行需要周期行运行的任务。系统定时器和时钟中断处理程序是Linux系统内核管理机制中的中枢。动态定时器是用来推迟执行程序的工具。内核可以动态创建或销毁动态定时器。

       内核必须在硬件的帮助下才能计算和管理时间。硬件为内核提供了一个系统定时器用以计算流逝的时间,该时钟在内核中可看成是一个电子时间资源。系统定时器以某种频率自行触发时钟中断,该频率可以通过编程预定称为节拍率(tick rate).当时钟中断发生时,内核就通过一种特殊的中断处理程序对其进行处理。系统定时器频率(节拍率)是通过静态预处理定义的,也就是HZ.在系统启动时按照HZ值对硬件进行设置。体系结构不一样,HZ的值也不同,定义在asm/param.h中。刚提到的节拍率就是这个意思。周期是1/HZ秒。最后要说明的是这个HZ值在编写内核代码时,不是固定不变的,而是可调的。当然,对于操作系统而言,也并不是一定要这个固定的时钟中断。实际上,内核可以使用动态编程定时器操作挂起事件。这里就不多说了。

       在linux内核里,有一个叫jiffies的变量(定义在linux/jiffies)记录了自系统启动以来产生的节拍的总数。启动时,内核将该变量初始化为0,此后每次时钟中断处理程序都会增加该变量的值。因为一秒内时钟中断的次数等于HZ,所以jiffies一秒内增加的值也就为HZ.系统运行时间以秒为单位计算,就等于jiffes/HZ.它作为在计算机表示的变量,就总存在大小,当这个变量增加到超出它的表示上限时,就要回绕到0.这个回绕看起来很简单,但实际上还是给我们编程造成了很大的麻烦,比如边界条件判断时。幸好,内核提供了四个宏来帮助比较节拍计数,这些宏定义在linux/jiffies.h可以很好的处理节拍回绕的情况:

      1    说明:unknown参数通常是jiffies,known参数是需要对比的值。

       如果改变内核中的HZ的值则会给用户空间中某些程序造成异常结果,这是因为内核是以节拍数/秒的形式给用户空间导出这个值的,在这个接口稳定了很长一段时间后,应用程序便逐渐依赖于这个特定的HZ的值了。所以如果在内核中更改了HZ的定义值,就打破了用户空间的常量关系----用户空间并不知道这个新的HZ的值。为了解决这个问题,内核必须更改所有导出的jiffies的值。内核定义了USER_HZ来代表用户空间看到的HZ值。内核可以使用宏jiffies_to_clock_t()将一个由HZ表示的节拍计数转换成一个由USER_HZ表示的节拍数。改宏的用法取决于USER_HZ是否为HZ的整数倍或相反。当是整数倍时,宏的形式相当简单:

#define jiffies_to_clock_t(x) ((x)/(HZ/USER_HZ));

       如果不是整数倍关系,那么该宏就得用更为复杂的算法了。同样的,如果是64位系统,内核使用函数jiffies_64_to_clock()将64位的jiffies值的单位从HZ转换为USER_HZ.

       体系结构提供了两种设备进行计时:系统定时器和实时时钟。系统定时器提供一种周期性触发中断机制。实时时钟(RTC)是用来持久存储系统时间的设备,即便系统关闭后,它也可以靠主板上的微型电池提供的电力保护系统的计时。当系统启动时,内核通过读取RTC来初始化墙上时间,该时间存放在xtime变量中,实时时钟最主要的作用是在启动时初始化xtime变量。

       有了上面的概念基础,下面就分析时钟中断处理程序。它分为两个部分:体系结构相关部分和体系结构无关部分。相关的部分作为系统定时器的中断处理程序而注册到内核中,以便在产生时钟中断时,它能够相应地运行。执行的工作如下:

1.获得xtime_lock锁,以便对访问jiffies_64和墙上时间xtime进行保护。
2.需要时应答或重新设置系统时钟。
3.周期性地使用墙上时间更新实时时钟。
4.调用体系结构无关的时间例程:do_timer().
中断服务程序主要通过调用与体系结构无关的例程do_timer()执行下面的工作:
1.给jiffies_64变量加1.
2.更新资源消耗的统计值,比如当前进程所消耗的系统时间和用户时间。
3.执行已经到期的动态定时器.
4.执行scheduler_tick()函数.
5.更新墙上时间,该时间存放在xtime变量中.
6.计算平均负载值.

       do_timer看起来还是很简单的,应为它的主要工作就是完成上面的框架,具体的让其它函数做就好了:

void do_timer(struct pt_regs *regs)
{
	jiffies_64++;
	update_process_times(user_mode(regs));
	update_times();
}

       上述user_mode()宏查询处理器寄存器regs的状态,如果时钟中断发生在用户空间,它返回1;如果发生在内核模式,则返回0.update_process_times()函数根据时钟中断产生的位置,对用户或对系统进行相应的时间更新:

void update_process_times(int user_tick)
{
	struct task_struct *p=current;
	int cpu=smp_processor_id();
	int system=user_tick^1;
	updata_one_process(p,user_tick,system,cpu);
	run_local_timers();
	scheduler_tick(user_tick,system);
}

       update_one_process()函数的作用是更新进程时间。它的实现是相当细致的。但注意,因为使用了XOR操作,所以user_tick和system两个变量只要其中有一个为1,则另外一个就必须为0,updates_one_process()函数可以通过判断分支,将user_tick和system加到进程相应的计数上:

p->utime = user;
p->stime = system;

       上述操作将适当的计数值增加1,而另外一个值保持不变。也许你已经发现了,这样做意味着内核对进程时间计数时,是根据中断发生时处理器所处的模式进行分类统计的,它把上一个tick全部算给进程。但是事实上进程在上一个节拍器间可能多次进入和退出内核模式,而在在上一个节拍期间,该进程也不一定是唯一一个运行进程,但是这没办法。接下来的run_lock_times() 函数标记了一个软中断去处理所有到期的定时器。最后,scheduler_tick()函数负责减少当前运行进程的时间片计数值并且在需要时设置need_resched标志,在SMP机器中中,该函数还要负责平衡每个处理器上的运行队列。当update_process_times()函数返回时,do_timer()函数接着会调用update_times()更新墙上时间。

void update_times(void)
{
	unsigned long ticks;
	if(ticks){
		wall_jiffies += ticks;
		update_wall_time(ticks);
	}
	last_time_offset = 0;
	calc_load(ticks);
}

       这里的ticks记录最近一次更新后新产生的节拍数。通常情况下ticks显然应该等于1.但是时钟中断也有可能丢失,因而节拍也会丢失。在中断长时间被禁止的情况下,就会出现这种现象(这种情况并不常见,往往是个BUG).wall_jiffies值随后被加上ticks----所以此刻wall_jiffies值就等于更新的墙上时间的更新值jiffies----接着调用update_wall_time()函数更新xtime,最后由calc_load()执行。do_timer()函数执行完毕后返回与体系结构相关的中断处理程序,继续执行后面的工作,释放xtime_lock锁,然后退出。以上的工作每1/HZ都要发生一次。

       刚前边说的墙上时间就是我们常说的实际时间,指变量xtime,由结构体timespec定义(kernel/timer.c),如下:

struct	timespec{
	time_t tv_sec;	//秒,存放自1970年7月1日(UTC)以来经过的时间,1970年7月1日称为纪元
	long tv_nsec;	//纳秒,记录自上一秒开始经过的纳秒数
}       

读写这个xtime变量需要xtime_lock锁,该锁是一个顺序锁(seqlock).关于内核读写就不说了,注意适当加解锁就好。回到用户空间,从用户空间取得墙上时间的主要接口是gettimeofday(),在内核中对应系统调用为sys_gettimeofday():

asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz)
{
         if (likely(tv != NULL)) {
                 struct timeval ktv;
                 do_gettimeofday(&ktv);
                 if (copy_to_user(tv, &ktv, sizeof(ktv)))
                         return -EFAULT;
         }
         if (unlikely(tz != NULL)) {
                 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
                         return -EFAULT;
         }
         return 0;
}

       分析上面的函数发现,问题就集中在tv上。当tv非空,就调用do_gettimeofday(),它主要完成循环读取xtime的操作。如果tz参数为空,该函数将把系统时区(存放在sys_tz中)返回用户。如果给用户空间拷贝墙上时间或时区发生错误,该函数返回-EFAULT;如果成功,则返回0.另外,内核提供的time系统调用,几乎被gettimeofday()完全取代。C库函数提供的一些墙上时间相关的库调用如ftime和ctime。系统的settimeofday()是用来设置当前时间,它需要具有CAP_SYS_TIME权限。除了更新xtime时间以外,内核不会像用户空间程序那样频繁使用xtime。但也需要注意在文件系统的实现代码中存放访问时间戳时需要使用xtime。

      上面说完了有关硬时钟,下面开始新的话题,是关于定时器的(也称动态定时器或内核定时器)。定时器并不周期执行,它在超时后就自行销毁。定义器由定义在linux/timer.h中的time_list表示,如下:

struct timer_list {
         struct list_head entry;
         unsigned long expires; 
         spinlock_t lock;
         unsigned long magic; 
         void (*function)(unsigned long);
         unsigned long data; 
         struct tvec_t_base_s *base;
};

      内核提供了一组与定时器相关的用来简化管理定时器的操作。所有这些接口都声明在文件linux/timer.h中,大多数接口在文件kernel/timer.c中获得实现。有了这些接口,我们要做的事情就很简单了:

1.创建定时器:struct timer_list my_timer;

2.初始化定时器:init_timer(&my_timer);

3.根据需要,设置定时器了:

            my_timer.expires = jiffies + delay;

            my_timer.data = 0;

            my_timer.function = my_function;

4.激活定时器:add_timer(&my_timer);

      经过上面的几步,定时器就可以开始工作了。然而,一般来说,定时器都在超时后马上就会执行,但是也有可能被推迟到下一时钟节拍时才能运行,所以不能使用它来实现硬实时。如果修改定时器,使用mod_timer(&my_timer,jiffies+new_delay)来修改已经激活的定时器时间。它也可以操作那些已经初始化,但还没有被激活的定时器,如果定时器未被激活,mod_timer会激活它。如果第啊哟个定时器时未被激活,该函数返回0;否则返回1。但不论哪种情况,一旦从mod_timer函数返回,定时器都将被激活而且设置了新的定时值。当然你也可以在超市前删除定时器用:del_timer(&my_timer);另外需要注意的是在多处理器上定时器中断可能已经在其它机器上运行了,这是就需要等待可能在其它处理器上运行的定时器处理程序都退出后再删除该定时器。这是就要使用del_timer_sync()函数执行删除工作。这个函数参数和上面一个一样,只是不能在中断上下文中使用而已。定时器是独立与当前代码的,这意味着可能存在竞争条件,这个就要特别小心,从这个意义上讲后者删除比前者更加安全。

      内核在时钟中断发生后执行定时器,定时器作为软件中断在下半部上下文中执行。具体来说就是时钟中断处理程序会执行update_process_timers()函数,该函数随即调用run_local_timers()函数:

void run_local_timers(void)
{
	raise_softirq(TIMER_SOFTIRQ);
}

      这个函数处理软中断TIEMR_SOFTIRQ,从而在当前处理器上运行所有的超时定时器。所有定时器都以链表的形式组织起来,但如果单纯的链表结构显然影响性能,因为每次都要顺序的的查找调整,这个时候,内核定时器按它们的超时时间将他们分为5组,当定时器超时时间接近时,定时器将随组一起下移。采用这种方法可以减少搜素超时定时器所带来的负担。

下一话题,内核代码(尤其是驱动程序)除了使用定时器或下半部机制以外还提供了许多延迟的方法来处理各种延迟请求。下面就来总结一下:

1.忙等待(也叫忙循环):通常是最不理想的方法,因为处理器被白白占用旋转而无法做别的事情。该方法仅仅在想要延迟的时间是节拍的整数倍或者精确率要求不高时才可以使用。实现起来还是挺简单的,就是在循环中不断旋转直到希望的时钟节拍数耗尽。比如:

unsigned long delay = jiffies+10;   //10个节拍
while(time_before(jiffies,delay))
	cond_resched();

      缺点很明显,更好的方法是在代码等待时,允许内核重新调度执行其他任务,如下:

unsigned long delay = jiffies+10;   //10个节拍
while(time_before(jiffies,delay))
	cond_resched();

      cond_resched()函数将调度一个新程序投入运行,但它只有在设置完need_resched标志后才能生效。换句话说,就是系统中存在更重要的任务需要运行。再由于该方法需要调用调度程序,所以它不能在中断上下文中使用----只能在进程上下文中使用。事实上,所有延迟方法在进程上下文中使用,因为中断处理程序都应该尽可能快的执行。另外,延迟执行不管在哪种情况下都不应该在持有锁时或者禁止中断时发生。

      至于说那些需要很短暂的延迟(比时钟节拍还短)而且还要求延迟的时间很精确,这种情况多发生在和硬件同步时,也就是说需要短暂等待某个动作的完成----等待时间往往小于1ms,所以不可能使用像前面例子中那种基于jiffies的延迟方法。这时,就可以使用在linux/delay.h中定义的两个函数,它们不使用,这两个函数可以处理微秒和毫秒级别的延迟的时间,如下所示:

void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);

      前者是依靠执行次数循环来达到延迟效果的,而mdelay()函数又是通过udelay()函数实现的。因为内核知道处理器在一秒内能执行多少次循环,所以udelay()函数仅仅需要根据指定的延迟时间在1秒中占的比例,就能决定需要进行多少次循环就能达到需要的推迟时间。udelay()函数仅能在要求的延迟时间很短的情况下执行,而在高速机器中时间很长的延迟会造成溢出,经验表明,不要试图在延迟超过1ms的情况下使用这个函数。这两个函数其实和忙等待一样,如果不是非常必要,还是不要用了算了。

      前边说的有点害怕,那咋办呢?其实更理想的延迟执行方法是使用schedule_timeout()函数,该方法会让需要延迟执行的任务睡眠到指定的延迟时间耗尽后再重新运行。但该方法也不能保证睡眠时间正好等于指定的延迟时间----只能尽量是睡眠时间接近指定的延迟时间。当指定的时间到期后,内核唤醒被延迟的任务并将其重新放回运行队列,如下:

set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(s*HZ);

      唯一的参数是延迟的相对时间,单位是jiffies,上例中将相应的任务推入可中断睡眠队列,睡眠s秒。在调用函数schedule_timeout之前,不要要将任务设置成可中断或不和中断的一种,否则任务不会休眠。这个函数需要调用调度程序,所以调用它的代码必须保证能够睡眠,简而言之,调用代码必须处于进程上下文中,并且不能持有锁。有关这个函数的实现细节,可以看下源码,还是相当简单的。接下来就是当定时器超时,process_timeout()函数被调用:

void process_timeout(unsigned long data)
{
	wake_up_process((task_t *)data);
}

      该函数将任务置为TASK_RUNNING状态,然后哦将其放入运行队列。当任务重新被调度时,将返回代码进入睡眠前的位置继续执行(正好在调用schedule()后)。如果任务提前被唤醒(比如收到信号),那么定时器被销毁,process_timeout()函数返回剩余的时间。

      最后,在进程调度那一节我们说过,进程上下文的代码为了等待特定时间发生,可以将自己放入等待队列。但是,等待队列上的某个任务可能既在等待一个特定事件到来,又在等待一个特定时间到期----就看谁来得更快。这种情况下,代码可以简单的使用scedule_timeout()函数代替schedule()函数,这样一来,当希望指定时间到期后,任务都会被唤醒,当然,代码需要检查被唤醒的原因----有可能是被事件唤醒,也有可能是因为延迟的时间到期,还可能是因为接收到了信号----然后执行相应的操作。

如果使用ssms连接SQLserver的时候出现无法连接到服务器。 如果使用ssms连接SQLserver的时候出现无法连接到服务器。 Lan 2020-03-29 22:11 329 人阅读 0 条评论 标题: 连接到服务器------------------------------无法连接到... 阅读详情

相关推荐

CarPlay无线连接背后的‘握手’秘密:深入解读iAP2协议与蓝牙/Wi-Fi协同

本文深入解析了CarPlay无线连接背后的技术细节,重点探讨了iAP2协议与蓝牙/Wi-Fi的协同工作原理。从蓝牙层的UUID识别到iAP2协议的握手过程,再到Wi-Fi热点的建立与优化,详细揭示了CarPlay无线连接的安全机制和调试方法,为开发者提供了实用的技术参考。

weixin_42520573的博客 475

LINUX定时器和时间管理

首先要明白两个概念:系统定时器和动态定时器。周期性产生的事件都是有系统定时器驱动的,这里的系统定时器是一种可编程硬件芯片,它能以固定频率产生中断。该中断就是定时器中断,它所对应的中断处理程序负责更新系统时间,也负责执行需要周期行运行的任务。系统定时器和时钟中断处理程序是Linux系统内核管理机制中的中枢。动态定时器是用来推迟执行程序的工具。内核可以动态创建或销毁动态定时器(schedule_tim

Phoenix_FuliMa 3656

Flutter版本升级踩坑实录:从3.27到3.35,我们是如何修复Impeller引擎导致的花屏问题的?

本文详细记录了团队在Flutter版本升级过程中遇到的Impeller引擎导致的花屏问题及解决方案。从问题诊断到最终升级至稳定版3.35,文章分享了排查步骤、升级策略和性能对比数据,为开发者提供了实用的参考经验。

weixin_26854555的博客 504

【读书笔记】深入浅出SSD

深入浅出SSD

谈笑的博客 8236

逆向学习:从已上线微信小游戏反推Cocos工程结构(以切水果跑酷为例)

本文以“切水果跑酷”为例,详细介绍了如何通过逆向分析已上线的微信小游戏,反推其基于Cocos Creator的原始工程结构。文章深入拆解了编译后的目录骨架、资源加载逻辑与依赖关系,并重点解析了微信平台API的调用特征,为开发者提供了一种高效学习游戏架构与设计模式的实用方法。

kk1234的博客 1073

硬件即代码:用软件工程思维拆解F450无人机装配的模块化设计哲学

本文探讨了如何用软件工程思维重构DJI-F450无人机的模块化设计,将硬件装配提升为可编程系统。通过硬件抽象层、控制系统分层架构和扩展槽位设计模式,展示了无人机装配的模块化哲学,并结合实际案例说明如何优化性能与安全性。

weixin_29294975的博客 386

Linux内核设计与实现——定时器和时间管理

Linux内核设计与实现——定时器和时间管理

weixin_46006645的博客 1047

Virtuoso 中的tech file 详细说明

工艺文件(Techfile)是集成电路设计中的核心配置文件,定义了从晶圆制造到版图验证全流程所需的工艺规则和图层属性。在Cadence Virtuoso平台中,Techfile作为连接设计与制造的桥梁,主要包含以下内容: 图层体系定义 金属层、介质层、多晶硅层等物理图层的编号、名称和显示属性 图层用途(DRAW、MASK等)及图层-用途组合(LPP)的优先级 设计规则约束 几何尺寸规则(最小线宽/间距) 包围和延伸规则 密度规则和特殊工艺规则(如天线效应) 器件定义 MOS管、电阻等器件的图层构成 电学参数

u013620135的博客 8127

进程调度 以及softirq中定时器会调用的进程调度过程分析

实时进程:

fengpsky 1084

5.6华为OD机试真题 新系统 - 匹配命令行前缀关键字 (Java/Py/C/C++/Js/Go)

5.6华为OD机试真题 新系统 - 匹配命令行前缀关键字本文整理华为 OD 机试新系统机考真题库,涵盖高频考点精析与完整题目内容,提供 C 语言、Java、C++、Python、Go、JavaScript 多语言源码实现,搭配详细解题思路讲解,并支持在线 OJ 刷题练习,助力高效备考华为 OD 机试新系统。

算法大师! 2128

2026年1至9月武汉市房地产价格深度分析报告

本报告基于2026年1月至9月武汉市实际成交案例,从成交价格、区域分布、户型结构、价格走势等维度进行深度分析。数据来源包括武汉市住房保障和房屋管理局备案数据、主要中介机构成交记录及典型楼盘网签案例,覆盖全市15个行政区及主要功能板块。

王国平的博客 327

Linux 内核中的时间管理:时钟源与定时器的实现

Linux 内核中的时间管理系统是一个核心组件,它负责维护系统的时间,提供定时器功能,支持各种时间相关的操作。时间管理的设计思路与企业管理中的时间规划有着密切的联系,它通过时间基准、任务调度、效率优化和可靠性等机制,为系统的高效运行提供了保障。工作也要流程化,时间管理就像是系统中的时间规划工具,它确保了系统的时间准确性和任务的按时执行。在实际应用中,我们需要根据具体场景选择合适的时钟源和定时器类型,并优化定时器的使用,以实现系统的最佳性能。

jiang_style的博客 4508

XRoboToolkit —— 基于 PICO 4 Ultra 的机器人遥操作方案(一)

视觉-语言-动作模型(Vision-Language-Action models)的快速发展催生了对大规模、高质量机器人演示数据集的迫切需求。尽管遥操作是数据采集的主要方法,但现有方法存在可扩展性有限、设置流程复杂以及数据质量不佳等问题。本文提出XRoboToolkit,这是一个基于OpenXR标准的跨平台扩展现实(XR)机器人遥操作框架。该系统具备低延迟立体视觉反馈、基于优化的逆运动学算法,并支持多种跟踪模态,包括头部、控制器、手部及辅助运动追踪器。

2506_90492529的博客 3308

Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河

本节笔记主要学习Linux内核定时器的驱动开发,主要包括内核时间管理和定时器、硬件原理图分析【LED】、驱动开发和测试。最重要的内容为定时器驱动开发部分。

2328

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【Note】《深入理解Linux内核》 Chapter 6:Linux 内核中的时间管理机制

Linux 如何高效分配和回收内存,包含页级分配器(Buddy 内存管理)、Slab/SLUB 页面缓存机制、缓存层次结构、NUMA 支持、调试与调优技术等。

YZJincsdn的博客 953

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Linux内核设计与实现 - 第11章 定时器和时间管理

【代码】Linux内核设计与实现 - 第11章 定时器和时间管理。

baron-周贺贺-代码改变世界ctw 384

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

i.MX6ULL终结者Linux时间管理和内核定时器简介

这里写目录标题1 Linux内核时间管理1.1 内核中的时间概念1.2 节拍率1.3 jiffies2 内核定时器简介 1 Linux内核时间管理 时间管理在内核中占有非常重要的地位。相对于事件驱动,内核中有大量的函数都是基于时间驱动的。内核必须管理系统的运行时间以及当前的日期和时间。 周期产生的事件都是由系统定时器驱动的。系统定时器是一种可编程硬件芯片,它已固定频率产生中断。该中断就是所谓的定时器中断,它所对应的中断处理程序负责更新系统时间,还负责执行需要周期性运行的任务。系统定时器和时钟中断处理程序是L

weixin_46635880的博客 417

Linux内核中的时间管理详解

时间管理是Linux内核中最基础且最重要的功能之一,它为系统提供了计时、调度、超时处理等核心能力。没有精确的时间管理,系统调度、IO操作、网络超时等都将无法正常工作。本文将深入探讨Linux内核中的时间管理机制,包括时间源、定时器、时间统计和时间相关系统调用等。

jiang_style的博客 2583

Linux 内核中的定时器机制:从低精度到高精度

Linux 内核中的定时器机制是实现时间相关功能的核心组件。定时器机制通过低精度定时器、高精度定时器、定时器轮、时钟源和时钟事件设备等组件,实现了精确的时间调度和管理。工作也要流程化,定时器机制就像是系统中的时间管理工具,它确保了任务的按时执行和系统的高效运行。在实际应用中,我们需要选择合适的定时器,避免长时间持有锁,正确处理定时器取消,使用高精度定时器,以及优化定时器数量,以实现系统的最佳性能和可靠性。

jiang_style的博客 4526

linux内核定时器实验

文章目录一、linux时间管理和内核定时器简介1.内核时间管理简介2.内核定时器简介1.init_timer 函数2.add_timer 函数3.del_timer 函数4.del_timer_sync 函数5.mod_timer 函数3.linux内核短延时函数二、硬件原理图分析三、实验程序编写1.修改设备树文件2.定时器驱动程序编写3.编写测试APP四、运行测试 定时器是我们最常用到的功能,一般用来完成定时功能,本章我们就来学习一下 Linux 内核提供的定时器 API 函数,通过这些定时器

lengyuefeng212的博客 661

Linux内核时间管理:深入解析clockevents框架

在Linux内核的时间管理子系统中,`clockevents`框架扮演着至关重要的角色。作为`clocksource`框架的补充,`clockevents`主要负责管理那些能够在未来特定时间点产生中断的硬件设备。本文将深入探讨`clockevents`框架的设计原理、核心数据结构以及其在内核中的实际应用。 ## clockevents与clocksource的关系 在深入`clockevent...

gitblog_00408的博客 576
上一篇: linux内核分析笔记----内核同步
下一篇: linux内核分析笔记----内存管理
wustdatamining
博客等级 码龄15年 12粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值