分类:
2008-11-14 16:38:12
第一 互斥操作
一, 信号量
初始化 init_MUTEX(struct semaphore *sem)
P函数 down(struct semaphore *sem) down_interruptible(struct semaphore *sem)
V操作 up(struct semapheore *sem)
二 读取者/写入着信号量
初始化 init_rwsem(struct rw_sempahore *sem);
读操作 down_read(struct rw_seamphore *sem);
Up_read(struct rw_semphore *sem);
写操作 down_write (struct rw_semphore *sem);
Up_write(struct rw_semphore *sem);
三 Completion
初始化: struct completion my_completion;
Init_completion(&my_completion );
等待: void wait_for_completion(struct completion *c)
触发: void complete(struct completion *c);
Void complet_all(struct completion *c);
四 自旋锁
所有自旋锁等待本质上都是不可中断的, 一旦调用sping_lock, 在获得锁之前将一直处于自旋的状态。
初始化: void spin_lock_init(spinlock_t *lock);
获得锁: void spin_lock(spinlock_t *lock);
Void spin_lock_irq(spinlock *lock);
void apin_lock_irqsave(spinlock *lock);
Void spin_lock_bh(spinlock *lock);
释放锁: void spin_unlock(spinlock_t *lock);
对共享资源的访问时间很短, 可以用自旋锁来访问。并且可以用在中断里。
五 读取者/写入者 自旋锁
自旋锁大的 读者/写者 形式
定义: rwlock_t my_rwlock
Rwlock_init(&my_lock);
读者: read_lock(rwlock_t *lock)
Read_lock_irq(); read_lock_irqsave(); read_lock_bh();
Read_unlock(); read_unlock_irqsave()。。。。。。。。
写者: write_lock(rwlock_t *lock);
Write_lock_irqsave(); write_lock_irq(); write_lock_bh();
Write_unlock(); write_unlock_irqsave();。。。。。。
六 原子变量
原子操作
七 seqlock
当要保护的资源很小, 很简单, 会很频繁的访问而且写入访问会很少发生且必须快速是,就可以使用seqlock.本质上seqlock会允许读者对资源的自由访问,但需要读取者检查是否和写入者冲突,当这种冲突发生时,就需要重试对资源的访问。 通常不用于保护包含指针的数据结构。
八 读取 复制 更新
通常发生在经常读取 而很少写入的情形的优化。被保护的资源应该通过指针访问,而对这些资源应该通过指针访问,而对这些资源的引用必须用原子代码拥有。 写入者首先复制, 然后修改副本, 之后 用新的版本替代相关的指针。
第二 进程的休眠
第一 简单休眠
声明: DELCARE_WAIT_QUEUE_HEAD(name);
或者 wait_queue_head_t my_queue;
Init_wait_queue_head(&my_queue);
等待: wat_event(queue, condition);
Wiat_event_interrupt(); wait_event_timeout(); wait_event_interruptible_timeout();
唤醒: void wake_up(wait_queue_head_t *queue);
Void wake_up_interruptible(wait_queue_head_t *queue);
Wake_up_all();
Wake_up_nr();
Wake_up_interruptible_sync();
第三 中断下半部分
第一 tasklet 机制
task queue基于bottom half,bottom half基于tasklet,而tasklet则基于softirq。
do_softirq()有四种执行动机, 分别是: 从系统调用中返回, 从异常中返回, 调度程序中, 以及处理完硬件中断之后。
一个tasklet执行结束后, 它就从执行队列里删除了,要想重新让他转入运行,就必须重新调用tasklet_schedule();
定义: 1 DECLARE_TASKLET(my_tasklet, my_tasklet_func , data); 定义一个名为tasklet结构my_tasklet, 与my_tasklet_func(data)函数相关联。。
2 tasklet_shedule(&my_tasklet); 登记my_tasklet, 允许系统在适当的时候进行调度运行。
第二 工作队列
工作队列与tasklet之间的区别:
1 tasklet 在软件中断的上下文执行,所有的tasklet代码必须是原子的。相反,工作队列函数是一个特殊的内核进程的上下文中运行,因此他们具有更好的灵活行。尤其是, 工作队列函数可以休眠。
2 tasklet 始终运行在被初始提交的同一个处理器上,但这只是工作队列的默认方式。
3 内核代码可以请求工作队列函数的执行延迟给定的时间间隔。
定义: static struct work_struct jiq_work;
初始化: INIT_WORK(&jiq_work, jiq_print_wq, &jiq_data);
触发: schedule_work(struct work_struct *work);
清除: void flush_workqueue(struct workqueue_struct *queue);
同一个tasklet 和 timer 只能在同一个CPU上运行,而不同的软中间断运行在不同的CPU上。Tasklet 可以被调度多次,但实际 只有一次运行, 是不能积累的。
信号
只要同一个信号处于未决状态,如果此时又收到同一个信号,那么就合并两个信号位一个,这就是不可靠信号。对于可靠的信号就是排队的信号,一个收到多次,就调用多次信号处理函数。