【学习笔记】原子位|内核线程

来源:互联网 发布:cad中网络接口怎么画 编辑:程序博客网 时间:2024/06/06 03:41

原子位和原子变量

原子变量

原子操作主要用于实现资源计数
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.hhandler:    中断处理函数 irqreturn_t handler(int irq, void *dev_id);    irqreturn_t:        See include/linux/irqreturn.hirqflags:    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/interruptsdev_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