黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图

您现在的位置: 黑客风云 >> 黑客文章 >> 操作系统 >> LINIX UNIX >> 正文
·没有路由密码权限时的鸽08-23·上网安全 Vista自我防范10-11
·让濒临崩溃的Windows XP10-11·有备无患,快速自制救急10-11
·要你好看!Windows看图工10-11·空间赞助网提供不同类型10-11
·讨论net.exe和net1.exe的10-10·让3389远程桌面传输更通10-10
·巧妙入侵渗透赌博站10-10·Aspx空间扫权限工具10-10
·Windows2003最新提权工具10-10·易淘乐提供100M免费全能10-10
·系统开机密码忘了不着急10-09·中意网络提供免费100M免10-09
·与众不同 Windows XP开始10-08·让桌面图标翻跟斗 在XP上10-08
·上海宽元站长资助计划-提10-08·个性化Windows XP的任务10-07
·趣盘提供3G免费网络硬盘10-07·秀山热线提供200MB免费全10-07
·一次艰辛的提权过程10-06·成功入侵IT大卖场的渗透10-06
·mysqlhack- MYSQL利用工10-06·lanker一句话PHP后门客户10-06
·WIXI提供3G免费多媒体网10-06·新人网络提供100M/ftp免10-06
·如何利用QQ带来高流量10-05·UuShare提供免费网络文件10-05
[推荐]Linux内核中的同步和互斥分析报告
      ★★★

Linux内核中的同步和互斥分析报告

文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2006-11-21 8:59:50

 当进程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 ,这时变成没锁状态 )

  当然,还有另一种情况,就是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)

 
文章录入:sygbox    责任编辑:cainiaowang 
【字体:
Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
ICP备案:冀06009886