内核定时器编程:
时钟脉冲:它是soc的重要指标和性能参数。供内核使用(进程调度,计时)。也称为时钟中断,通常是操作系统的0号中断。
jiffies:
- 内核中表示自系统开机以来,一共发生了多少次时钟脉冲。
HZ:
- 内核中表示一秒钟发生多少次时钟脉冲
Tick:
- 内核中表示两次时钟脉冲之间的时间间隔。
内核中在软件层面。提供了一系列数据结构和函数供于底层驱动计时编程。
步骤:
-
1.定义:
- struct timer_list xxx;
-
2.初始化:
init_timer(&xxx);
xxx.function = do_my_xxx;
xxx.data = (unsigned long)ooo;
xxx.expeirs = jiffies + 400;
-
3.使用:
- 3.1注册并启动定时器:
* add_timer(&xxx); - 3.2完成定时器回调函数:
void do_my_xxx(unsigned long data) { ....... }
- 3.1注册并启动定时器:
-
3.3修改定时器延时时间并启动:
mod_timer(&xxx,jiffies + 延时时间);
-
3.4注销定时器:
del_timer(&xxx);
并发控制:
- 多个进程并发访问临界资源区,是会引起竞态现象,由此我们必须对这种现象加以控制,就是并发控制。并发控制中常用的手段
就是锁。
linux内核中提供的锁:
- 1.中断屏蔽(强烈推荐不使用)
- 2.原子操作 (建议不使用,常见于汇编,一般也只是极短的赋值语句)
- 3.自旋锁
- 3.1 读写锁 读读进程并发,读写进程互斥,写写进程互斥
- 3.2 顺序锁 读读进程并发,读写进程并发,写写进程互斥
- 3.3 RCU 读读进程并发,读写进程并发,写写进程并发
- 4.信号量 操作pv信号的一种锁,其使用场景和互斥体类似,但效率比互斥体低,故逐渐被互斥体所替代
- 5.互斥体
自旋锁和互斥体使用的3大原则:
- 1.当临界资源区较小时,使用自旋锁,当临界资源区比较大时,使用互斥体。因为自旋锁所面临的是自旋等待的cpu资源消耗,
而互斥体是进程切换的资源消耗。 - 2.当临界资源区中有引起睡眠的函数时,只能使用互斥体。因为互斥体运行于进程上下文。而自旋锁运行于中断上下文,在中断
上下文,绝对避免进程调度,否则可能将引起系统崩溃。 - 3.当临界资源区中有中断时,只能使用自旋锁,而不能使用互斥体。因为互斥体是运行于进程上下文。在中断中会禁止进程调度,
使用互斥体,将会造成上下文丢失。
1.原子操作:
- 1.定义并初始化
- atomic_t xxx = ATOMIC_INIT(1);
- 2.使用:
- atomic_dec_and_test(&xxx);
- atomic_inc(&xxx);
- 或者:
- atomic_inc_and_test(&xxx);
- atomic_dec(&xxx);
- 2.自旋锁:
- 1.定义:
- spinlock_t xxx;
- 2.初始化:
- spin_lock_init(&xxx);
- 3.使用:
- 3.1上锁:
- spin_lock(&xxx);
- 3.2解锁:
- spin_unlock(&xxx);
- 3.1上锁:
- 3.信号量:
- 1.定义:
- struct semaphore xxx;
- 1.定义:
- 2.初始化:
- sema_init(&xxx,1);
- 3.使用:
- 3.1上锁:
- down(&xxx);
- 3.2解锁:
- up(&xxx);
- 3.1上锁:
- 1.定义:
- 4.互斥体:
- 1.定义:
- struct mutex xxx;
- 2.初始化:
- mutex_init(&xxx);
- 3.使用:
- 3.1上锁:
- mutex_lock(&xxx);
- 3.2解锁:
- mutex_unlock(&xxx);
- 3.1上锁:
- 1.定义:
网友评论