Linux内核-—jiffies全局变量

在Linux内核中,jiffies是一个全局变量,用于跟踪自系统启动以来经过的时钟滴答数(tick)。时钟滴答是内核用于计时的一个基本单位,它的长度取决于系统硬件和内核配置(通常是1/100秒或1毫秒)。

由于jiffies是以滴答数来表示时间的,所以内核提供了一系列函数来将其他时间单位(如毫秒、秒等)转换为jiffiesmsecs_to_jiffies是其中一个这样的函数,它将毫秒数转换为jiffies

函数原型如下:

 

c复制代码

  unsigned long msecs_to_jiffies(const unsigned int m);
  • m:要转换的毫秒数。

返回值:

  • 对应的jiffies数。

使用msecs_to_jiffies可以将毫秒数转换成内核可以理解的jiffies单位,这样你就可以在内核中使用这个值来设置超时、等待时间等。

例如,如果你想设置一个5秒的超时时间,你可以这样做:

 

c复制代码

  unsigned long timeout = msecs_to_jiffies(5000); // 5秒转换为jiffies

然后,你可以将这个timeout值传递给需要超时的内核函数,如<

Linux 内核中,**全局变量**的定义与用户空间程序类似,但由于内核是单个地址空间运行的大型 C 程序(不是多个进程独立作用域),其“全局”含义更强调**跨文件共享、在整个内核中可访问**。因此,内核中定义全局变量需要遵循特定的规则和机制。 --- ### 一、基本语法:C 语言的 `extern` 和 `static` #### 1. 定义一个全局变量(存储在 `.data` 或 `.bss` 段) ```c // file: kernel/time/timer.c #include <linux/jiffies.h> unsigned long volatile jiffies; // 全局变量 jiffies 的实际定义 ``` 这个变量就是著名的 `jiffies` —— 它是一个 **全局可读写的变量**,被成千上万个内核函数使用。 > 注意:`volatile` 是必须的,因为它的值可能被中断上下文修改,编译器不能优化掉重复读取。 --- #### 2. 在其他文件中声明该变量(使用 `extern`) ```c // file: include/linux/jiffies.h #include <linux/types.h> extern unsigned long volatile jiffies; ``` 这样任何包含 `<linux/jiffies.h>` 的源文件都可以访问 `jiffies`。 --- ### 二、如何组织内核中的全局变量? #### ✅ 正确做法: - **在一个 .c 文件中定义一次** - **在头文件中用 `extern` 声明** - 所有想使用的模块 `#include` 这个头文件即可 示例结构: ```c // kernel/my_module.c int my_global_counter = 0; // 实际定义 struct task_struct *global_daemon; // 可能指向某个守护进程 ``` ```c // include/linux/my_module.h #ifndef _LINUX_MY_MODULE_H #define _LINUX_MY_MODULE_H #include <linux/sched.h> extern int my_global_counter; extern struct task_struct *global_daemon; #endif ``` ```c // another_file.c #include <linux/my_module.h> #include <linux/kernel.h> void some_function(void) { my_global_counter++; printk("Counter: %d\n", my_global_counter); } ``` --- ### 三、特殊类型的全局变量 #### 1. 每 CPU 变量(per-CPU variables) 避免竞争条件的一种方式是为每个 CPU 单独保存一份副本。 ```c // 定义 per-cpu 变量 DEFINE_PER_CPU(int, cpu_load); // 使用时: int load = __get_cpu_var(cpu_load); // 获取当前 CPU 上的值(旧接口) // 或者使用新接口: raw_cpu_write(cpu_load, 100); ``` 这类变量不会引起锁争用,适合频繁读写但无需全局同步的场景。 #### 2. 初始化段控制(使用 `__initdata`, `__read_mostly` 等修饰符) ```c // 只在初始化阶段使用的全局变量,之后释放内存 static int __initdata debug_init_only = 0; // 很少修改、主要只读的变量,放入专属缓存行以提高性能 static struct timerqueue_head timer_queue __read_mostly; ``` 这些是由链接器段(section)支持的特性,帮助优化内核布局。 --- ### 四、注意事项 | 要点 | 说明 | |------|------| | ❗只能定义一次 | 避免 multiple definition 错误(违反 ODR:One Definition Rule) | | ✅推荐放在 `.c` 文件 | 不要将变量定义写进头文件(除非是 `static inline` 函数内部) | | 🔐并发访问需保护 | 多个 CPU 或中断可能同时访问,需配合自旋锁、互斥体等机制 | | 🧠注意内存对齐和缓存行 | 频繁访问的变量应避免“伪共享”(false sharing) | 例如加锁保护: ```c static DEFINE_SPINLOCK(my_lock); static int shared_counter; void inc_counter(void) { spin_lock(&my_lock); shared_counter++; spin_unlock(&my_lock); } ``` --- ### 五、查看内核中真实例子 你可以查看以下文件了解真实全局变量定义: - `kernel/time/timer.c`: `jiffies`, `xtime`, `wall_to_monotonic` - `kernel/sched/core.c`: `init_task`(初始任务结构体) - `mm/vmalloc.c`: `vmlist`(虚拟内存链表) 这些都是典型的全局变量,在整个内核广泛使用。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蘑菇二号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值