zoukankan      html  css  js  c++  java
  • Linux内核--并发【转】

    本文转自自:http://www.jianshu.com/p/035550ae05d2

    为什么会产生并发

    1、多个用户同时登陆的时候,他们有可能在任何时刻以任意的组合调用内核代码。

    2、smp系统可能同时在不同的处理器上执行你的代码。

    3、内核代码是抢占式的,你的程序有可能随时被剥夺掉处理器。

    4、设备中断可能导致并发的异步事件。

    5、内核也提供了各种延迟代码执行机制,如工作队列等,任务队列和定时器,它可以使你在与当前进程无关的方法中运行代码

    并发带来的影响

    并发产生了竞争条件,比如两个进程同时访问相同的硬件资源

    应对的基本原则是:尽量避免共享数据

    如果无法避免那就一定要注意共享的数据。

    Linux 的 信号量

    #include <linux/semaphore.h>

    /*
    * Copyright (c) 2008 Intel Corporation
    * Author: Matthew Wilcox <willy@linux.intel.com>
    *
    * Distributed under the terms of the GNU GPL, version 2
    *
    * Please see kernel/semaphore.c for documentation of these
    functions
    */
    #ifndef __LINUX_SEMAPHORE_H
    #define __LINUX_SEMAPHORE_H
    #include <linux/list.h>
    #include <linux/spinlock.h>
    /* Please don't access any members of this structure directly */
    struct semaphore {
        raw_spinlock_t lock;
        unsigned int count;
        struct list_head wait_list;
    };
    #define __SEMAPHORE_INITIALIZER(name , n)
    {
        .lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock),
        .count = n,
        .wait_list = LIST_HEAD_INIT((name).wait_list),
    } #
    define DEFINE_SEMAPHORE(name) struct semaphore name = __SEMAPHORE_INITIALIZER(name , 1)
    static inline void sema_init(struct semaphore *sem, int val)
    {
        static struct lock_class_key __key;
        *sem = (struct semaphore) __SEMAPHORE_INITIALIZER(*sem, val);
        lockdep_init_map(&sem->lock.dep_map , "semaphore ->lock", &__key , 0);
    }
    extern void down(struct semaphore *sem);
    extern int __must_check down_interruptible(struct semaphore *sem);
    extern int __must_check down_killable(struct semaphore *sem);
    extern int __must_check down_trylock(struct semaphore *sem);
    extern int __must_check down_timeout(struct semaphore *sem, long jiffies);
    extern void up(struct semaphore *sem);
    #endif /* __LINUX_SEMAPHORE_H */

    down方法将信号量的值减一然后等到信号量的值大于等于零继续执行。

    down_interruptible跟down类似但是可以被中断,建议使用这个API,只使用down容易造成该线程永远无法退出。

    一般的使用方法是:

    if (down_interruptible(&sem))
        return -ERESTARTSYS;

    读写信号量

    一种常见的信号量,针对共享文件,允许多个线程同时读,而读的时候不允许写。在同一时间只允许一个线程写。

    #include <linux/rwsem.h>

    自旋锁

    自旋锁最初是为了SMP系统设计的,实现在多处理器情况下保护临界区。
    自旋锁只有两种状态,上锁,未上锁,经常被用来确保一段代码的原子性

    spinlock API:

    void spin_lock(spinlock_t *lock);
    void spin_lock_irqsave(spinlock_t *lock , unsigned long flags);
    void spin_lock_irq(spinlock_t *lock);
    void spin_lock_bh(spinlock_t *lock);

    读写自旋锁

    linux内核提供了读写自旋锁,实际上它与读写信号量很相似。

    上锁的要求

    1、如果你在自己的代码里实现了一个设备锁,而你也要套用到linux内核提供的锁,请先把自己的锁锁上,再把系统的锁锁上。

    2、如果你使用信号量和自旋锁,请先down信号量,再使用自旋锁。

    3、确保自旋锁内没有其他的锁,以防系统被死锁。

  • 相关阅读:
    EntytyFramework批量更新
    EntityFramework批量Insert
    asp.net MVC Session锁的问题
    谈谈ThreadStatic
    C#中XmlSerializer的内存占用问题
    转:【译】Asp.net MVC 利用自定义RouteHandler来防止图片盗链
    面试心得
    Part 39 AngularJS route change events
    Part 38 AngularJS cancel route change
    Part 37 Difference between $scope and $rootScope
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6740169.html
Copyright © 2011-2022 走看看