一、Linux内核定时器是一个软件类型的定时器,并不是一个硬件定时器。
Linux内核中有大量的函数需要时间管理,比如说:周期性的调度程序、延时函数、定时器(这里的定时器应该是一个软件类型的定时器)等。
用到时间管理就需要一个硬件定时器提供准确的时间,比如stm32中freertos用的是systick定时器。硬件定时器提供时钟源,时钟源的频率可以设置,设置完成后就可以周期性的产生定时中断,系统使用定时中断来计时。中断周期性产生的频率就是系统频率,也叫做节拍率(tick rate),比如 1000Hz,100Hz 等等说的就是系统节拍率。系统节拍率是可以设置的,单位是 Hz,我们在编译 Linux 内核的时候可以通过图形化界面设置系统节拍率(make menuconfig 命令),设置完之后就会在配置文件中出现一个对应的宏。
Linux内核中应该也有一个通用的定时器,或者内核中用的不是通用定时器,而是在通用API下调用某一个定时器驱动提供的函数(这个函数由驱动编写者提供),在编写定时器驱动时会用到之前配置好的系统节拍率的宏。(这段是自己的一些理解)
Linux内核使用全局变量jiffies来记录系统从启动以来的系统节拍数(比如在1000Hz下就1ms就加一),在系统启动时jiffies为0。jiffies有32位的也有64位的,在系统节拍率为1000Hz的情况下,64位的能记录的时间是5.8 亿年,32位的则是 49.7 天就发生了绕回,也就是会存在溢出归零的可能性
jiffies存在的意义是:记录时间点,比如定义一个2秒的定时器,就可以用jiffies + 2*Hz来表示,因为jiffies是一个一直在变化的变量
二、ioctrl函数
应用层程序可以利用系统函数ioctrl函数来跟内核交换数据,但是驱动层要实现对应的函数:struct file_operations结构体中 unlocked_ioctl函数和compat_ioctl函数。
unlocked_ioctl函数和compat_ioctl函数的区别:
在 64 位系统上运行32 位的应用程序调用将会使用 compat_ioctl 函数。
在 32 位的系统上运行 32 位的应用程序调用的是 unlocked_ioctl 函数(imx6ull使用这个)
在实现 ioctl 驱动层函数时,会用到 cmd 这个东西,cmd 由四部分组成:
cmd要用对应的宏来定义,不要用普通的数字(比如:0,1,2,3,这种)来执行不同的代码,因为普通的数字可能会出问题,虽然cmd实际上也是一个数字。
(cmd 那个 _IO 和 _IOW 的效果好像是一样的,还有就是 ioctrl 函数那个参数arg可以用指针也可以直接传值,如果用指针的方式的话就要用 copy_from_user 这个函数来弄)
三、Linux定时器的一些相关函数
void init_timer(struct timer_list *timer)
void add_timer(struct timer_list *timer)
int del_timer(struct timer_list * timer)
int del_timer_sync(struct timer_list *timer)
int mod_timer(struct timer_list *timer, unsigned long expires)