ºìÁªLinuxÃÅ»§
Linux°ïÖú

LinuxÄÚºËÖеÄͬ²½ºÍ»¥³â·ÖÎö±¨¸æ

·¢²¼Ê±¼ä:2006-11-16 09:31:05À´Ô´:ºìÁª×÷Õß:augustnov
ÏÈ¿´½ø³Ì¼äµÄ»¥³â¡£ÔÚlinuxÄÚºËÖÐÖ÷Ҫͨ¹ýsemaphore»úÖƺÍspin_lock»úÖÆʵÏÖ¡£Ö÷ÒªµÄÇø±ðÊÇÔÚsemaphore»úÖÆÖУ¬½ø²»ÁËÁÙ½çÇøʱ»á½øÐнø³ÌµÄÇл»£¬¶øspin_lock¸ÕÖ´ÐÐæµÈ£¨ÔÚSMPÖУ©¡£ÏÈ¿´ÄÚºËÖеÄsemaphore»úÖÆ¡£Ç°ÌáÊǶÔÒýÓüÆÊýcountÔö¼õµÄÔ­×ÓÐÔ²Ù×÷¡£ÄÚºËÓÃatomic_tµÄÊý¾Ý½á¹¹ºÍÔÚËüÉÏÃæµÄһϵÁвÙ×÷Èçatomic_add()¡¢atomic_sub()µÈµÈʵÏÖ¡££¨¶¨ÒåÔÚatomic.hÖУ©semaphone»úÖÆÖ÷Ҫͨ¹ýup()ºÍdown()Á½¸ö²Ù×÷ʵÏÖ¡£semaphoneµÄ½á¹¹Îª:


struct semaphore
{
atomic_t count;
int sleepers;
wait_queue_head_t wait;
};


ÏàÓ¦µÄdown()º¯ÊýΪ:


static inline void down(struct semaphore*sem)
{
/* 1 */sem->count--; //Ϊԭ×Ó²Ù×÷
if(sem->count<0)
{
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
tsk->state = TASK_UNINTERRUPTIBLE;
add_wait_queue_exclusive(&sem->wait, &wait);
spin_lock_irq(&semaphore_lock);
/* 2 */ sem->sleepers++;
for (;;) {
int sleepers = sem->sleepers;
/*
* Add "everybody else" into it. They aren't
* playing, because we own the spinlock.
*/
/* 3 */ if (!atomic_add_negative(sleepers - 1, &sem->count)) {
/* 4 */ sem->sleepers = 0; //Õâʱsem->count=0
break;
}
/* 4 */ sem->sleepers = 1; /* us - see -1 above */ // Õâʱsem
->count
=-1
spin_unlock_irq(&semaphore_lock);
schedule();
tsk->state = TASK_UNINTERRUPTIBLE;
spin_lock_irq(&semaphore_lock);
}
spin_unlock_irq(&semaphore_lock);
remove_wait_queue(&sem->wait, &wait);
tsk->state = TASK_RUNNING;
wake_up(&sem->wait);
}
}


ÏàÓ¦µÄup()º¯ÊýΪ:


void up(struct semaphore*sem)
{
sem->count++; //Ϊԭ×Ó²Ù×÷
if(sem->count<=0)
{
//»½Ðѵȴý¶ÓÁÐÖеÄÒ»¸ö·ûºÏÌõ¼þµÄ½ø³Ì£¨ÒòΪÿ¸ö½ø³Ì¶¼¼ÓÁËTASK_EXCLUSIVE±êÖ¾£©
¡£
};
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 6 ÌõÆÀÂÛ

  1. feng201310 ÓÚ 2014-05-19 14:46:08·¢±í:

    ¶ÁÁË£¬Ð»ÁË

  2. h497916507 ÓÚ 2013-08-01 13:38:28·¢±í:

    mark

  3. js001sdx ÓÚ 2009-09-29 10:10:58·¢±í:

    ¶ÁÁË£¬Ð»ÁË

  4. augustnov ÓÚ 2006-11-16 09:32:15·¢±í:

    ¿ÉÒÔ¿´³ö£¬ËüºÍsemaphore»úÖƽâ¾öµÄ¶¼ÊÇÁ½¸ö½ø³ÌµÄ»¥³âÎÊÌ⣬¶¼ÊÇÈÃÒ»¸ö½ø³ÌÍ˳öÁÙ½çÇøºóÁíÒ»¸ö½ø³Ì²Å½øÈëµÄ·½·¨£¬²»¹ýsempahore»úÖÆʵÐеÄÊÇÈýø³ÌÔÝʱÈóöCPU£¬½øÈëµÈ´ý¶ÓÁеȴýµÄ²ßÂÔ£¬¶øspin_lockʵÐеÄÈ´ÊÇÈ´½ø³ÌÔÚÔ­µØ¿Õת£¬µÈ×ÅÁíÒ»¸ö½ø³Ì½áÊøµÄ²ßÂÔ¡£

    ϱ߿¼ÂÇÖж϶ÔÁÙ½çÇøµÄÓ°Ïì¡£Òª»¥³âµÄ»¹Óнø³ÌºÍÖжϷþÎñ³ÌÐòÖ®¼ä¡£µ±Ò»¸ö½ø³ÌÔÚÖ´ÐÐÒ»¸öÁÙ½çÇøµÄ´úÂëʱ£¬¿ÉÄÜ·¢ÉúÖжϣ¬¶øÖжϺ¯Êý¿ÉÄܾͻáµ÷ÓÃÕâ¸öÁÙ½çÇøµÄ´úÂ룬²»ÈÃËü½øÈëµÄ»°¾Í»á²úÉúËÀËø¡£Õâʱһ¸öÓÐЧµÄ·½·¨¾ÍÊǹØÖжÏÁË¡£


    #define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ;
    cli":
    "=g" (x): /* no input */ :"memory")
    #define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /*
    no
    output */ :"g" (x):"memory")
    #define local_irq_disable() __asm__ __volatile__("cli": : :"memory")
    #define local_irq_enable() __asm__ __volatile__("sti": : :"memory")
    #define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0)
    #define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0)
    #define local_bh_disable() cpu_bh_disable(smp_processor_id())
    #define local_bh_enable() cpu_bh_enable(smp_processor_id())


    ¶ÔÓÚUPÀ´Ëµ£¬ÉÏÃæÒѾ­ÊÇ×ã¹»ÁË£¬²»¹ý¶ÔÓÚSMPÀ´Ëµ£¬»¹Òª·ÀÖ¹À´×ÔÆäËücpuµÄÓ°Ï죬Õâʱ½â¾öµÄ·½·¨¾Í¿ÉÒÔ°ÑÉÏÃæµÄspin_lock»úÖÆÒ²×ۺϽøÀ´ÁË¡£


    #define spin_lock_irqsave(lock, flags) do {
    local_irq_save(flags); sp
    in_lock(lock); } while (0)
    #define spin_lock_irq(lock) do { local_irq_disable();
    spin_lock(lo
    ck); } while (0)
    #define spin_lock_bh(lock) do { local_bh_disable();
    spin_lock(loc
    k); } while (0)
    #define spin_unlock_irqrestore(lock, flags) do { spin_unlock(lock); local_i
    rq_restore(flags); } while (0)
    #define spin_unlock_irq(lock) do { spin_unlock(lock);
    local_irq_enable();
    } while (0)
    #define spin_unlock_bh(lock) do { spin_unlock(lock);
    local_bh_enable();
    } while (0)


    Ç°Ãæ˵¹ý£¬¶ÔÓÚUPÀ´Ëµ£¬spin_lock£¨£©Êǿյģ¬ËùÒÔÒÔÉϵĶ¨Òå¾ÍÒ»ÆðÊÊÓÃÓÚUP ºÍSMPµÄÇéÐÎÁË¡£


    read_lock_irqsave(lock, flags) , read_lock_irq(lock),
    read_lock_bh(lock) ºÍ
    write_lock_irqsave(lock, flags) , write_lock_irq(lock),
    write_lock_bh(lock
    )


    ¾ÍÊÇspin_lockµÄÒ»¸öССµÄ±äÐͶø¼ºÁË¡£

  5. augustnov ÓÚ 2006-11-16 09:31:56·¢±í:

    µ±È»£¬»¹ÓÐÁíÒ»ÖÖÇé¿ö£¬¾ÍÊÇup()²Ù×÷ºÍdown()²Ù×÷Êǽ»*³öÏֵģ¬Ò»°ãµÄ¹æÂɾÍÊÇ£¬Èç¹û½ø³ÌÔÚÁÙ½çÇøÆÚ¼äÓÖÓнø³Ì£¨ÎÞÂÛÊÇÄĸö½ø³Ì£¬ÐÂÀ´µÄ»¹ÊǸձ»»½ÐѵÄÄǸö£©½øÈë˯Ãߣ¬¾Í»áÁîcountµÄÖµ´Ó0±äΪ-1£¬´Ó¶ø½ø³ÌÔÚ´ÓÁÙ½çÇø³öÀ´Ö´ÐÐup()Àï¾Í±ØÐëÖ´ÐÐÒ»´Îwake_up()£¬ÒÔÈ·±£ËùÓеĽø³Ì¶¼Äܱ»»½ÐÑ£¬ÒòΪ¶à»½ÐѼ¸¸öÊÇû¹ØϵµÄ¡£Èç¹û½ø³ÌÔÚÁÙ½çÇøÆÚ¼äûÓбðµÄ½ø³Ì½øÈë˯Ãߣ¬Ôò´ÓÁÙ½çÇø³öÀ´Ö´ÐÐup()ʱ¾ÍÓò»×ÅÈ¥Ö´ÐÐwake_up()ÁË£¨µ±È»£¬Ö´ÐÐÁËҲûʲôӰÏ죬²»¹ý¶àÓà°ÕÁË£©¡£¶øΪʲôҪ°Ñwake_up()ºÍcount++·Ö¿ªÄØ£¬¿ÉÒÔ´ÓÉÏÃæµÄup1¿´³öÀ´£¬ÀýÈ磬½ø³Ì2µÚÒ»´ÎµÃµ½»ú»áÔËÐÐʱ£¬±¾À´Õâʱ»½ÐÑËüµÄ½ø³Ì»¹Ã»Ö´ÐÐup()µÄ£¬µ«ÓпÉÄÜÆäËü½ø³ÌÖ´ÐÐÁËup()ÁË£¬ËùÒÔÕæÓпÉÄܻᷢÏÖcount==1µÄÇé¿ö£¬ÕâʱËü¾ÍÕæµÄ²»ÓÃ˯¾õÁË£¬Áîcount=sleepers=0£¬¾Í¿ÉÒÔ½Ó×ÅÍùÏÂÖ´ÐÐÁË¡£»¹¿É¿´³öÒ»µã£¬Ò»°ãµÄ£¬( count ,sleepers)µÄÖµµÄÈ¡Öµ·¶Î§Îª(n ,0)[n>0] ºÍ(0 ,0)ºÍ (1 ,-1)¡£Ï±߿´¿´spin_lock»úÖÆ¡£

    Spin_lock²ÉÓõķ½Ê½ÊÇÈÃÒ»¸ö½ø³ÌÔËÐУ¬ÁíÍâµÄ½ø³ÌæµÈ´ý£¬ÓÉÓÚÔÚÖ»ÓÐÒ»¸öcpuµÄ»úÆ÷(UP)ÉÏ΢¹ÛÉÏÖ»ÓÐÒ»¸ö½ø³ÌÔÚÔËÐС£ËùÒÔÔÚUPÖУ¬spin_lockºÍspin_unlock¾Í¶¼ÊÇ¿ÕµÄÁË¡£ÔÚSMPÖУ¬spin_lock()ºÍspin_unlock()¶¨ÒåÈçÏ£º


    typedef struct {
    volatile unsigned int lock;
    } spinlock_t;
    static inline void spin_lock(spinlock_t *lock)
    {
    __asm__ __volatile__(
    "\n1:\t"
    "lock ; decb %0\n\t"
    "js 2f\n" //lock->lock< 0 ,jmp 2 forward
    ".section .text.lock,\"ax\"\n"
    "2:\t"
    "cmpb $0,%0\n\t" //wait lock->lock==1
    "rep;nop\n\t"
    "jle 2b\n\t"
    "jmp 1b\n"
    ".previous"
    :"=m" (lock->lock) : : "memory");
    }
    static inline void spin_unlock(spinlock_t *lock)
    {
    __asm__ __volatile__(
    "movb $1,%0"
    :"=m" (lock->lock) : : "memory"); //lock->lock=1
    }


    Ò»°ãÊÇÈç´ËʹÓÃ:


    #define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
    spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
    spin_lock_(&xxx_lock)
    ...
    critical section
    ...
    spin_unlock (&xxx_lock)

  6. augustnov ÓÚ 2006-11-16 09:31:36·¢±í:

    ¼ÙÉ迪ʼʱ£¬count=1;sleepers=0¡£µ±½ø³ÌAÖ´ÐÐdown()ʱ£¬ÒýÓüÆÊýcount--£¬Èç¹ûÕâʱËüµÄÖµ´óÓÚµÈÓÚ0£¬Ôò´Ódown()ÖÐÖ±½Ó·µ»Ø¡£Èç¹ûcountÉÙÓÚ0£¬ÔòAµÄstate¸ÄΪTASK_INTERRUPTIBLEºó½øÈëÕâ¸öÐźÅÁ¿µÄµÈ´ý¶ÓÁÐÖУ¬Í¬Ê±Ê¹sleepers++;È»ºóÖØмÆËãcount=sleepers - 1 + count,ÈôÕâʱÒýÓüÆÊýÈÔСÓÚ0£¨Ò»°ãÇé¿öÏÂӦΪ-1£¬ÒòΪcount = - sleepers,²»¹ýÔÚSMP½á¹¹ÖУ¬ÆÚ¼ä±ðµÄ½ø³Ì¿ÉÄÜÖ´ÐÐÁËup()ºÍdown()´Ó¶øʹµÃÒýÓüÆÊýµÄÖµ¿ÉÄܱ仯£©£¬ÔòÖ´Ðнø³ÌÇл»¡£

    µ±½ø³ÌAÓÖ»ñµÃ»ú»áÔËÐÐʱ£¬ËüÏÈÖ´ÐÐwake_up(&sem->wait)²Ù×÷£¬»½Ðѵȴý¶ÓÁÐÀïµÄÒ»¸ö½ø³Ì£¬½Ó×ÅËü½øÈëÁÙ½çÇø£¬´ÓÁÙ½çÇø³öÀ´Ê±Ö´ÐÐup()²Ù×÷£¬Ê¹sem->count++,£¨Èç¹û½ø³ÌAÊÇ´Ódown()ÖÐÖ±½Ó·µ»Ø£¬ÒòΪÕâʱµÈ´ý¶ÓÁÐÒ»¶¨Îª¿Õ£¬ËùÒÔËü²»ÓÃÖ´ÐÐwake_up()²Ù×÷£¬Ö±½Ó½øÈëÁÙ½çÇø£¬ÔÚ´ÓÁÙ½çÇø³öÀ´Ê±Ò»ÑùÖ´ÐÐup()²Ù×÷£¬Ê¹ sem->count++£©¡£ÕâʱÈç¹ûcountµÄֵСÓÚµÈÓÚ0£¬Õâ±íÃ÷ÔÚËüÔÚÁÙ½çÇøÆÚ¼äÓÖÓÐÒ»¸ö½ø³Ì£¨¿ÉÄܾÍÊÇËü½øÈëÁÙ½çÇøʱ»½ÐѵÄÄǸö½ø³Ì£©½øÈë˯ÃßÁË£¬ÔòÖ´ÐÐwake_up()²Ù×÷£¬·´Ö®£¬Èç¹ûcountµÄÖµÒѾ­´óÓÚ0£¬Õâ±íÃ÷ÔÚËüÔÚÁÙ½çÇøÆÚ¼äûÓбðµÄ½ø³Ì£¨°üÀ¨ÔÚËü½øÈëÁÙ½çÇøʱ±»Ëü»½ÐѹýµÄÄǸö½ø³Ì£©½øÈë˯Ãߣ¬ÄÇôËü¾Í¿ÉÒÔÖ±½Ó·µ»ØÁË¡£

    ´Ó±»»½ÐѵÄÄǸö½ø³Ì¿´¿´£¬Èç¹ûÔÚ»½ÐÑËüµÄ½ø³ÌûִÐÐup()֮ǰËü¾ÍµÃµ½ÁËÔËÐлú»á£¬ÕâʱËüÓÖÖØмÆËãcount=sleepers - 1 + count=-1£»´Ó¶øsleepers±»¸³Öµ1£»ÕâʱËüÓÖ±ØÐë½øÐе÷¶ÈÈóöÔËÐеĻú»á¸ø±ðµÄ½ø³Ì£¬×Ô¼ºÈ¥Ë¯Ãß¡£ÕâÕýÊÇ·¢ÉúÔÚ»½ÐÑËüµÄ½ø³ÌÔÚÁÙ½çÇøʱÔËÐеÄʱºò¡£Èç¹ûÊÇÔÚ»½ÐÑËüµÄ½ø³ÌÖ´ÐÐÁËup()²Ù×÷ºóËü²ÅµÃµ½ÁËÔËÐлú»á£¬¶øÇÒÔÚ»½ÐÑËüµÄ½ø³ÌÔÚÁÙ½çÇøÆÚ¼äʱû±ðµÄ½ø³ÌÖ´ÐÐdown()£¬ÔòcountµÄÖµÔÚ½ø³ÌÖ´ÐÐup()֮ǰÒÀȻΪ0£¬ÕâʱÔÚup()ÀïÃæ¾Í²»±ØÒªÔÙÖ´ÐÐwake_up()º¯ÊýÁË¡£¿ÉÒÔͨ¹ýÒ»¸öÀý×ÓÀ´ËµÃ÷¾ßÌåµÄʵÏÖ¡£É迪ʼsem->count=sem->sleepers=0¡£Ò²¾ÍÊÇÓÐËøµ«Î޵ȴý¶ÓÁÐ £¨Ò»¸ö½ø³ÌÒѾ­ÔÚÔËÐÐÖУ©¡£ÏȺó·Ö±ð½øÐÐ3¸ödown()²Ù×÷£¬ºÍ3¸öup()²Ù×÷£¬ÈçÏ£ºÎªÁ˲ûÊö·½±ã£¬Ö»±£ÁôÁËһЩ»á¸Ä±äsleepersºÍcountÖµµÄ²½Ö裬²¢ÇÒ×ñÑ­´Ó×óµ½ÓÒÒÀ´Î½øÐеÄÔ­Ôò¡£


    down1:
    count(0->-1),sleepers(0->1),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È
    down2:
    count(-1->-2),sleepers(1->2),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È

    down3:
    count(-1->-2),sleepers(1->2),sleepers-1+count(-1),count(-1),sleepers(1),µ÷¶È



    up1:
    count(-1->0),»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ1£©,£¨½ø³Ì1µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(0),count(0),sleepers(0),break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©£¬£¨½ø³Ì2µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(-1),count(-1),sleepers(1),
    µ÷¶È£¨Ã»´ïµ½Ìõ¼þ£¬ÓÖµÃ˯¾õ£©Ò²¿ÉÄÜÊÇÕâÑùµÄ£º
    up1`:
    count(-1->0),»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ1£©,£¨½ø³Ì1µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(0),count(0),sleepers(0),break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©£¬½ø³Ì2ÔÚÒÔºó²ÅµÃµ½»ú»áÔËÐУ©
    up2:
    count(-1->0),£¨ÒòΪcount<=0£©»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ2£©,½ø³Ì2µÃµ½»ú»áÔËÐУ©
    sleepers-+count(0) , count(0) , sleepers(0) ,break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ3£©£¬½ø³Ì3µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(-1),count(-1),sleepers(1),
    µ÷¶È£¨Ã»´ïµ½Ìõ¼þ£¬ÓÖµÃ˯¾õ£©¶ÔÓ¦ÉÏÃæµÄ1`£º
    up2`:
    count(0->1),£¨ÒòΪcount>0,ËùÒÔÖ±½Ó·µ»Ø£©½ø³Ì2µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(0),count(0),sleepers(0),break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¬£¨ÉèΪ3£©
    up3:
    count(-1->0),£¨ÒòΪcount<=0£©»½ÐÑÒ»¸ö˯Ãß½ø³Ì£¨ÉèΪ3£©,½ø³Ì3µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(0),count(0),sleepers(0),break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨Õâʱ¶ÓÁÐÀïû½ø³ÌÁË£©
    ½ø³Ì3ÔËÐнáÊø£¬Ö´ÐÐup(), ʹcount =1 ,Õâʱ±ä³ÉûËø״̬ £©
    ¶ÔÓ¦ÉϱߵÄ2`£º
    up3`:
    count(0->1),£¨ÒòΪcount>0,ËùÒÔÖ±½Ó·µ»Ø£©½ø³Ì3µÃµ½»ú»áÔËÐУ©
    sleepers-1+count(0),count(0),sleepers(0),break,
    »½ÐÑÁíÒ»¸ö˯Ãß½ø³Ì£¨Õâʱ¶ÓÁÐÀïû½ø³ÌÁË£©
    ½ø³Ì3ÔËÐнáÊø£¬Ö´ÐÐup(), ʹcount =1 ,Õâʱ±ä³ÉûËø״̬ £©