原子位和原子变量
原子变量
原子操作主要用于实现资源计数
Linux中的基本原子操作
Atomic_read
- 返回原子变量的值
Atomic_set
- 设置原子变量的值。
Atomic_add
- 原子的递增计数的值。
Atomic_sub
- 原子的递减计数的值。
atomic_cmpxchg
- 原子比较并交换计数值。
atomic_clear_mask
- 原子的清除掩码。
while(atomic_cmpxchg(&v, 1, 0) != 1)
;
for(i = 0; i < 3; i++)
{
mdelay(1000);
}
atomic_set(&v, 1);
atomic_cmpxchg()函数实现了一个比较+交换的原子操作(原子就是说cpu要不就不做,要做就一定要做完某些操作才能干别的事情,对应这里就是比较和交换要一次过做完).
atomic_cmpxchg()比较kgdb_active->count的值是否等用-1,如果是则把cpu的值赋给kgdb_active->count,否则不修改它的值,atomic_cmpxchg返回kgdb_active->count赋值前的值.简单的讲,假设4个进程同时开始,1号成功进入, atomic_dec_and_test成功减1并通过检测,跳出while循环,其他3个进程成功减1但数值已为负数,不通过test,循环知道1号进程完成时加1(atomic_inc)。
while(!atomic_dec_and_test(&v))
{
atomic_inc(&v); //kind like spin_lock();
//wait -> mutex
}
/*do something*/
atomic_inc(&v);
中断
先来看一下头文件和函数(:
#include <linux/interrupt.h>
int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)
irq:
中断号 arch/arm/plat-s3c64xx/include/plat/irqs.h
handler:
中断处理函数 irqreturn_t handler(int irq, void *dev_id);
irqreturn_t:
See include/linux/irqreturn.h
irqflags:
See line 21-59 in include/linux/interrupt.h
使用IRQF_SHARED共享irq时, irqflags必须相同
如: request_irq(IRQ_EINT(0), handler1,
IRQF_TRIGGER_FALLING | IRQF_SHARED, "dev1", &dev1);
request_irq(IRQ_EINT(0), handler2,
IRQF_TRIGGER_FALLING | IRQF_SHARED, "dev2", &dev2);
devname:
设备名, cat /proc/interrupts
dev_id:
发生中断时将dev_id传递给handler函数,
irqflags含有IRQF_SHARED时dev_id不能为NULL, 并且要保证唯一
dev_id一般采用当前设备的结构体指针
1.中断时不能睡眠,进入中断时会屏蔽其他中断,此时睡眠将无法接受用于唤醒的中断,而自己处于睡眠,也无法唤醒自己。——所以使用自旋锁,不进入睡眠。
2.中断可以设为共享让其他‘人’使用。
内核线程
创建内核线程:
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data, const char namefmt[]);唤醒内核线程(可以唤醒所有进程(线程)):
wake_up_process(struct task_struct *k);
创建并运行内核线程:
struct task_struct *kthread_run(int (*threadfn)(void *data),
void *data, const char namefmt[]);
- 通知内核线程停止:
int kthread_stop(struct task_struct *k);
返回threadfn函数的返回值, 如果k没有被wake_up_process(k)过将返回-EINTR
不是强制停止, 如果内核线程不停止将一直等待
你可以直接拔出模块‘杀死’一个自己建立并插入的内核态线程(不使用通知),内核将会崩溃。
- 检查是否收到停止信号:
int kthread_should_stop(void);
头文件 linux/kthread.h