Concurrency and Race Condition

产生竞争的原因:

   对资源的共享访问,包括硬件资源(设备)和软件资源(内存空间)

 

原则:

   尽量减少共享资源的使用,如全局变量等

 

解决的方法:

   通过建立critical section是操作成为原子操作,使同一时间内,只有一个线程操作该段代码。

   kernel对不同的情况提供了不同的方法,注意的是,有的方法可以 Go to sleep 的,有的不行!

   有的方法会导致执行的线程go to sleep,而有的方法不会。

   有的代码是允许sleep的,那就可以使用go to sleep的方法。

   但有的代码是不允许sleep的,那就绝对不能go to sleep的方法。

   spinlock就是可以用在不允许sleep的代码中的。

 

Semaphore

 

头文件<asm/semaphore.h>.

struct semaphore;

 

初始化 信号量

void sema_init(struct semaphore *sem, int val);

where val is the initial value to assign to a semaphore.

 

直接声明 互斥量

Thus, a mutex can be declared and initialized with one of the following:
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);

 

运行时 初始化

void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);

 

获取信号量

void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);

用down_interruptible比较多,这样用户可以中断这个函数的执行。

所以一定要对这个函数做返回值的判断,如果返回非零,则表示并没有得到信号量。

 

返还信号量

void up(struct semaphore *sem);

 

例子:

struct scull_dev {
    struct scull_qset *data; /* Pointer to first quantum set */
    int quantum; /* the current quantum size */
    int qset; /* the current array size */
    unsigned long size; /* amount of data stored here */
    unsigned int access_key; /* used by sculluid and scullpriv */
    struct semaphore sem; /* mutual exclusion semaphore */
    struct cdev cdev; /* Char device structure */
};

 

for (i = 0; i < scull_nr_devs; i++) {
    scull_devices[i].quantum = scull_quantum;
    scull_devices[i].qset = scull_qset;
    init_MUTEX(&scull_devices[i].sem);
    scull_setup_cdev(&scull_devices[i], i);
}

一定要在scull_setpu_cdev之前初始化信号量,否则会出现错误。

 

读写信号量

这种信号量使用于 有多个读进程,少量写进程。 可以同时有多个读进程一起运行。

 

头文件 <linux/rwsem.h>

struct rw_semaphore

 

读操作的信号量获取和释放

void down_read(struct rw_semaphore *sem);
int down_read_trylock(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem);

 

写操作的信号量获取和释放

void down_write(struct rw_semaphore *sem);
int down_write_trylock(struct rw_semaphore *sem);
void up_write(struct rw_semaphore *sem);
void downgrade_write(struct rw_semaphore *sem);

 

 

Completions

这种结构专门用于等待其他任务的完成的。

虽然用信号量也可以达到这个作用,但信号量的效率要低。

struct semaphore sem;
init_MUTEX_LOCKED(&sem);
start_external_task(&sem);
down(&sem);

 

头文件 <linux/completion.h>

struct completion;

 

静态声明:
DECLARE_COMPLETION(my_completion);

 

动态定义:

struct completion my_completion;
/* ... */
init_completion(&my_completion);

 

 

等待任务完成:

void wait_for_completion(struct completion *c);

 

通知任务完成:

void complete(struct completion *c);
void complete_all(struct completion *c);

 

Spinlock

spinlock是比较特殊的一种锁,它是可以运行在不能sleep的地方的,比如 ISR中。

进入spinlock后,有几点要注意

1. 不能被抢占,这点是自动的,得到spinlock后会自动disable当前处理器的抢占。

2. 不能sleep, 所以需要非常注意得到spinlock后调用的函数。

3. disable 中断。

 

 

 

你可能感兴趣的:(Concurrency and Race Condition)