定义
内核文件include/asm-generic/param.h定义了两者的值:
# undef HZ
# define HZ CONFIG_HZ /* Internal kernel timer frequency */
# define USER_HZ 100 /* some user interfaces are */
# define CLOCKS_PER_SEC (USER_HZ) /* in "ticks" like times() */
其中CONFIG_HZ为通过make menuconfig配置的HZ值,一般为1000,即每秒钟jiffies增加1000个计数。实际值可参见代码中include/generated/autoconf.h文件。USER_HZ固定为100,用户层调用times系统调用,返回的是按照USER_HZ计算的jiffies值。
u64 jiffies_64_to_clock_t(u64 x)
{
...
x = div_u64(x * TICK_NSEC, (NSEC_PER_SEC / USER_HZ));
return x;
}
SYSCALL_DEFINE1(times, struct tms __user *, tbuf)
{
...
return (long) jiffies_64_to_clock_t(get_jiffies_64());
}
用户层与内核之间相关交互
两者定义的差别导致用户层与内核交互时,需要进行转换。除了以上的64位转换函数jiffies_64_to_clock_t。内核还提供了另外两个互换函数:
kernel/time.c
clock_t jiffies_to_clock_t(unsigned long x)
{
return div_u64((u64)x * TICK_NSEC, NSEC_PER_SEC / USER_HZ);
}
unsigned long clock_t_to_jiffies(unsigned long x)
{
return x * (HZ / USER_HZ);
}
Linux网桥的ioctl为例
代码位于文件net/bridge/br_ioctl.c中,示例为设置和获取bridge表项的最大超时时间:
static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
unsigned char mac[ETH_ALEN];
struct net_bridge *br = netdev_priv(dev);
unsigned long args[4];
if (copy_from_user(args, rq->ifr_data, sizeof(args)))
return -EFAULT;
switch (args[0]) {
case BRCTL_GET_BRIDGE_INFO:
{
struct __bridge_info b;
b.max_age = jiffies_to_clock_t(br->max_age); //转化为USER_HZ表示的clock
return 0;
}
case BRCTL_SET_BRIDGE_MAX_AGE:
{
unsigned long t = clock_t_to_jiffies(args[1]); //转化为HZ表示的jiffies
br->bridge_max_age = t;
return 0;
}
}
获取运行系统HZ值
网络中邻居表的locktime参数,默认设置的是一个HZ,通过proc文件可读取:
cat /proc/sys/net/ipv4/neigh/ens160/locktime
100
内核版本
linux-3.10.0