linuxtimer
‘壹’ linux kernel里timer怎么用
定时器,有时也称为动态定时器或内核定时器,是管理内核时间的基矗内核经常要推后执行某些代码,比如下半部机制就是为了将工作推后执行。我们需要一种工具,使工作能够在指定时间点上执行,正好在希望的时间点上,内核定时器正是这样一种工具。 ...
‘贰’ 如何在Linux下实现定时器
定时器Timer应用场景非常广泛,在Linux下,有以下几种方法:
1,使用sleep()和usleep()
其中sleep精度是1秒,usleep精度是1微妙,具体代码就不写了。使用这种方法缺点比较明显,在Linux系统中,sleep类函数不能保证精度,尤其在系统负载比较大时,sleep一般都会有超时现象。
2,使用信号量SIGALRM + alarm()
这种方式的精度能达到1秒,其中利用了*nix系统的信号量机制,首先注册信号量SIGALRM处理函数,调用alarm(),设置定时长度,代码如下:
[cpp] view plain
#include <stdio.h>
#include <signal.h>
void timer(int sig)
{
if(SIGALRM == sig)
{
printf("timer\n");
alarm(1); //we contimue set the timer
}
return ;
}
int main()
{
signal(SIGALRM, timer); //relate the signal and function
alarm(1); //trigger the timer
getchar();
return 0;
}
alarm方式虽然很好,但是无法首先低于1秒的精度。
3,使用RTC机制
RTC机制利用系统硬件提供的Real Time Clock机制,通过读取RTC硬件/dev/rtc,通过ioctl()设置RTC频率,代码如下:
[cpp] view plain
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
unsigned long i = 0;
unsigned long data = 0;
int retval = 0;
int fd = open ("/dev/rtc", O_RDONLY);
if(fd < 0)
{
perror("open");
exit(errno);
}
/*Set the freq as 4Hz*/
if(ioctl(fd, RTC_IRQP_SET, 1) < 0)
{
perror("ioctl(RTC_IRQP_SET)");
close(fd);
exit(errno);
}
/* Enable periodic interrupts */
if(ioctl(fd, RTC_PIE_ON, 0) < 0)
{
perror("ioctl(RTC_PIE_ON)");
close(fd);
exit(errno);
}
for(i = 0; i < 100; i++)
{
if(read(fd, &data, sizeof(unsigned long)) < 0)
{
perror("read");
close(fd);
exit(errno);
}
printf("timer\n");
}
/* Disable periodic interrupts */
ioctl(fd, RTC_PIE_OFF, 0);
close(fd);
return 0;
}
这种方式比较方便,利用了系统硬件提供的RTC,精度可调,而且非常高。
4,使用select()
这种方法在看APUE神书时候看到的,方法比较冷门,通过使用select(),来设置定时器;原理利用select()方法的第5个参数,第一个参数设置为0,三个文件描述符集都设置为NULL,第5个参数为时间结构体,代码如下:
[cpp] view plain
#include <sys/time.h>
#include <sys/select.h>
#include <time.h>
#include <stdio.h>
/*seconds: the seconds; mseconds: the micro seconds*/
void setTimer(int seconds, int mseconds)
{
struct timeval temp;
temp.tv_sec = seconds;
temp.tv_usec = mseconds;
select(0, NULL, NULL, NULL, &temp);
printf("timer\n");
return ;
}
int main()
{
int i;
for(i = 0 ; i < 100; i++)
setTimer(1, 0);
return 0;
}
这种方法精度能够达到微妙级别,网上有很多基于select()的多线程定时器,说明select()稳定性还是非常好。
总结:如果对系统要求比较低,可以考虑使用简单的sleep(),毕竟一行代码就能解决;如果系统对精度要求比较高,则可以考虑RTC机制和select()机制。
‘叁’ linux下的几种时钟和定时器机制
1. RTC(Real Time Clock)
所有PC都有RTC. 它和CPU和其他芯片独立。它在电脑关机之后还可以正常运行。RTC可以在IRQ8上产生周期性中断. 频率在2Hz--8192HZ.
Linux只是把RTC用来获取时间和日期. 当然它允许进程通过对/dev/rtc设备来对它进行编程。Kernel通过0x70和0x71 I/O端口来访问RTC。
2. TSC(Time Stamp Counter)
80x86上的微处理器都有CLK输入针脚. 从奔腾系列开始. 微处理器支持一个计数器. 每当一个时钟信号来的时候. 计数器加1. 可以通过汇编指令rdtsc来得到计数器的值。通过calibrate_tsc可以获得CPU的频率. 它是通过计算大约5毫秒里tsc寄存器里面的增加值来确认的。或者可以通过cat /proc/cpuinfo来获取cpu频率。tsc可以提供比PIT更精确的时间度量。
3. PIT(Programmable internval timer)
除了RTC和TSC. IBM兼容机提供了PIT。PIT类似微波炉的闹钟机制. 当时间到的时候. 提供铃声. PIT不是产生铃声. 而是产生一种特殊中断. 叫定时器中断或者时钟中断。它用来告诉内核一个间隔过去了。这个时间间隔也叫做一个滴答数。可以通过编译内核是选择内核频率来确定。如内核频率设为1000HZ,则时间间隔或滴答为1/1000=1微秒。滴答月短. 定时精度更高. 但是用户模式的时间更短. 也就是说用户模式下程序执行会越慢。滴答的长度以纳秒形式存在tick_nsec变量里面。PIT通过8254的0x40--0x43端口来访问。它产生中断号为IRQ 0.
下面是关于pIT里面的一些宏定义:
HZ:每秒中断数。
CLOCK_TICK_RATE:值是1,193,182. 它是8254芯片内部振荡器频率。
LATCH:代表CLOCK_TICK_RATE和HZ的比率. 被用来编程PIT。
setup_pit_timer()如下:
spin_lock_irqsave(&i8253_lock, flags);
outb_p(0x34,0x43);
udelay(10);
outb_p(LATCH & 0xff, 0x40);
udelay(10);
outb (LATCH >> 8, 0x40);
spin_unlock_irqrestore(&i8253_lock, flags);
4. CPU Local Timer
最近的80x86架构的微处理器上的local apic提供了cpu local timer.他和pit区别在于它提供了one-shot和periodic中断。它可以使中断发送到特定cpu。one-shot中断常用在实时系统里面。
‘肆’ Linux定时服务器程序 timer (用c语言)
同学,你是段瀚聪老师的学生的吧?选了他的LINUX环境高级编程??
‘伍’ Linux下的定时器,怎么用
数为秒数,在经过指定秒数后,alarm会发出一个SIGALRM信号
singal函数用来绑定信号处理器函数,这里绑定的是timer,被绑定的函数必须固定为返回值void、参数int.
只需要alarm(时间)就设置了,可能由于getchar需要进入中断导致信号被挂起所以没反应,可以试试把getchar换成别的东西来延时看看。
关于更多Linux的学习,请查阅书籍《linux就该这么学》。
‘陆’ linux/timer.h路径在哪
输入whereis time.h就知道了,whereis命令找某个头文件的路径非常适合,time.h头文件是系统头文件,应该找到的。它的路径不同的Linux发行版应该是有些微差别的,用whereis命令查看一些才是最合适的。
‘柒’ linux使用timer产生100us会很占资源吗
系统资源肯定占,但是Timer本身耗费极少而已,而是应该关注Timer事件中的自定义方法。 你说的情况,没必要用多个Timer啊,一个Timer中同时多个图片各平移一帧不就可以了么?
‘捌’ linux0.11版本中,关于函数do_timer的疑问
void do_timer (long cpl){
...
fn = next_timer->fn;
next_timer->fn = NULL;
next_timer = next_timer->next;
(fn)();
...
}
这个函数中的函数指针是在函数void add_timer(long jiffies, void (*fn)(void))中添加的。这个函数是供内核使用的,用户空间的函数是不能调用add_timer的,也就是说 do_timer (long cpl)函数中的函数指针只会指向内核里面的函数。
(我去看了linux0.11的源码,用的地方确实只有
Floppy.c (kernel\blk_drv): add_timer(2,&transfer);
Floppy.c (kernel\blk_drv): add_timer(ticks_to_floppy_on(current_drive),&floppy_on_interrupt);
Sched.c (kernel):void add_timer(long jiffies, void (*fn)(void))
Sched.h (include\linux):extern void add_timer(long jiffies, void (*fn)(void));
)
所以的你的“内核不能直接访问用户空间函数问题”是不存在的。
我也是看到了http://bbs.chinaunix.net/thread-3727536-1-1.html这个帖子才想到的。
刚开始学这个,可能说的不对,多包涵。
‘玖’ 有谁会用linux里面的定时器timer_list
这段代码是Linux的一个内核模块程序,timer_list也是Linux内核中的数据结构。模块程序不是以main函数作为入口的。而是以mole_init指定。
mole_init/mole_exit分别用于指定模块的加载和卸载函数。
加载模块(insmod)时,会调用mytimer_init函数。这个函数设置一个定时器,在定时器超时时执行myfunc函数,指定函数参数为“Hello,world!”。
myfunc执行时,会输出“Hello,world!”,mod_timer函数会将定时器重新计时,两秒后到期。
因此整个代码执行起来后的现象就是每两秒输出一次Hello,world!
‘拾’ linux 加硬件定时器 timer 可否实时
一. Linux的硬件时间 PC机中的时间有三种硬件时钟实现,这三种都是基于晶振产生的方波信号输入。这三种时钟为:(1)实时时钟RTC ( Real Time Clock)