概述:
**********jiffies在英语中是"瞬间,一会儿"的意思
**********jiffies是一个计数器,记录了系统从刚开始启动到关闭系统时所运行的秒数,系统初始化时jiffies是0
**********内核是通过定时器中断来使jiffies计数器的值增加的,每次产生一个时钟中断,jiffies就会+1
**********产生中断的频率是由HZ(中断间隔,时钟滴答数)来决定的.HZ包含在<linux/param.h>头文件中的
**********内核计数器jiffies或jiffies_64都是一个64位变量,并且都是只读的,可以对jiffies计数器直接存取,而对jiffies_64不能直接存取需要借助函数
u64 get_jiffies_64(void);
在内核中的定义
extern u64 __jiffy_data jiffies_64; extern unsigned long volatile __jiffy_data jiffies;**********jiffies计数器和操作这个计数器的函数都在头文件<linux/jiffies.h>中,(<linux/sched.h>包含<linux/jiffies.h>文件)
操作jiffies计数器的宏函数:
int time_after(unsigned long a, unsigned long b); //jiffies a在jiffies b之后,即 a > b int time_before(unsigned long a, unsigned long b); //jiffies a在jiffies b之后,即 a < b int time_after_eq(unsigned long a, unsigned long b); // a >= b int time_before_eq(unsigned long a, unsigned long b); // a <= b
**********time_after的宏定义
#define time_after(a,b) (typecheck(unsigned long, a) && typecheck(unsigned long, b) && ((long)(b) - (long)(a) < 0)) //returns true if the time a is after time b**********time_before的宏定义
#define time_before(a,b) time_after(b,a)**********time_after_eq的宏定义
#define time_after_eq(a,b) (typecheck(unsigned long, a) && typecheck(unsigned long, b) && ((long)(a) - (long)(b) >= 0))**********time_before_eq的宏定义
#define time_before_eq(a,b) time_after_eq(b,a)在用户空间,用来表示jiffies值的方法:
**********使用结构体,struct timeval或使用结构体struct timespec,这些结构体在内核空间包含在<linux/time.h>中,在用户空间包含在<sys/time.h>头文件中
*****struct timeval结构的原型是
struct timeval { time_t tv_sec; /* seconds */ //秒 suseconds_t tv_usec; /* microseconds */ //毫秒 };*****struct timespec结构的原型是
struct timespec { time_t tv_sec; /* seconds */ //秒 long tv_nsec; /* nanoseconds */ //纳秒 };jiffies和这两个结构体之间转换的函数:
unsigned long timespec_to_jiffies(struct timespec *value); //将timespec转换成jiffies void jiffies_to_timespec(unsigned long jiffies, struct timespec *value); //将jiffies装换成timespec unsigned long timeval_to_jiffies(struct timeval *value); //将timeval转换成jiffies void jiffies_to_timeval(unsigned long jiffies, struct timeval *value); //将jiffies转换成timeval
##################################################################################################################################
模块实例:(jiffies.c)
# include <linux/module.h> # include <linux/init.h> # include <linux/kernel.h> # include <linux/fs.h> # include <linux/cdev.h> # include "jiffies.h" /** * The descriptions for the module **/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Bruce.Wang"); MODULE_DESCRIPTION("Test the char device"); MODULE_VERSION("1.0"); MODULE_ALIAS("CHRDEV"); //MODULE_DEVICE_TABLE("for device of char "); /** *the major device number **/ static int major = 66; static int minor = 88; static int count = 2; static dev_t cdevno; static char chrdev_name[] = "Dediprog"; /** *char device **/ static struct cdev mycdev; int my_open(struct inode *inodep, struct file *filep) { } size_t my_read(struct file *filep, char __user *buf, size_t count, loff_t *offset) { struct time_jiffies tj; unsigned long j; unsigned stamp_60; j = jiffies; stamp_60 = j + 60 * HZ; printk("HZ----------->%d\n",HZ); jiffies_to_timeval(j, &tj.old_tj); jiffies_to_timeval(stamp_60, &tj.new_tj); copy_to_user(buf,&tj,sizeof(tj)); printk("current jiffies is------------>%ld\n stamp_60--------->%ld\nstamp_60 - j------------>%ld\n", j, stamp_60, stamp_60 - j); if (time_after(stamp_60,j)){ printk("stamp_60 > j\n that is stamp_60 after j\n"); } if (time_before(j,stamp_60)){ printk("j < stamp_60\n that is j before stamp_60\n"); } return 66; } ssize_t my_write(struct file *filp, const char __user *buf, size_t count, loff_t *off) { } int my_release(struct inode *inodp, struct file *filp) { printk("%s %d\n", __func__, __LINE__); return 40; } /** *Operations for the character device **/ static struct file_operations fops = { .owner = THIS_MODULE, .open = my_open, .read = my_read, .write = my_write, .release = my_release, }; /** *The init function of the module **/ static int __init chrdev_init(void) { int ret; /** *Combined major and minor device numbers **/ cdevno = MKDEV(major, minor); /** *static register the number of the char device into the kernel **/ ret = register_chrdev_region(cdevno, count, chrdev_name); if (ret < 0){ goto ERROR1; } /** *Allocate space for character devices and init it **/ cdev_init(&mycdev, &fops); /** *Add the char device into the kernel(that is,relate with device number) **/ ret = cdev_add(&mycdev, cdevno, count); if (ret < 0){ goto ERROR2; } return 0; ERROR1: printk("register char device number failed!\n"); return ret; ERROR2: printk("relate char device with number failed!"); unregister_chrdev_region(cdevno, count); return ret; } /** *Function executed when the module exits **/ static void __exit chrdev_exit(void) { /** *Cancellation the char device number from the kernel **/ unregister_chrdev_region(cdevno, count); /** *Remove the char device from the kernel **/ cdev_del(&mycdev); printk("See you later,guys!!\n"); } module_init(chrdev_init); module_exit(chrdev_exit);##################################################################################################################################
jiffies.h头文件(我自己写的)
#ifndef __TIME_JIFFIES__ #define __TIME_JIFFIES__ #include <linux/jiffies.h> #include <linux/param.h> #include <linux/time.h> # include <asm/uaccess.h> struct time_jiffies { struct timeval old_tj; struct timeval new_tj; }; #endif####################################################################################################################################
app.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/time.h> #include <fcntl.h> #include <unistd.h> struct time_jiffies { struct timeval old_tj; struct timeval new_tj; }; int main(int argc, char *argv[]) { int fd; int ret; struct time_jiffies tj; if(argc != 2){ fprintf(stderr, "Usage: %s dev_file\n", argv[0]); return -1; } fd = open(argv[1], O_RDWR | O_NDELAY); if(fd < 0){ perror("open"); return -2; } ret = read(fd, &tj, sizeof(tj)); printf("old_tj--------------->%ld\n new_tj------------->%ld\n", tj.old_tj.tv_sec, tj.new_tj.tv_sec); printf("ret----------->%d\n",ret); printf("new_tj - old_tj---------->%ld\n",tj.new_tj.tv_sec - tj.old_tj.tv_sec); return 0; }