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

2008-01-10 11:30:37  作者:barman  来源:华星在线  浏览次数:133  文字大小:【+】【-
简介:Linux内核中的同步和互斥分析报告
关 键 字:内核 同步 互斥 报告

七彩谷商城

先看进程间的互斥。在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标志)。 
};

假设开始时,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,这表明在它在临界区期间没有别的进程(包括在它进入临界区时被它唤醒过的那个进程)进入睡眠,那么它就可以直接返回了。

[1] [2] [3] [4]
七彩谷商城
B20
 
B8

最新文章

更多

· Linux内核中的同步和互斥...
· Linux的I2C驱动架构
· Linux内核崩溃转储机制
· Linux对EXT3分区大小进行...
· 设定Linux操作系统的启动...
· 使用Inotify 监控Linux ...

推荐文章

更多

· Linux内核中的同步和互斥...
· Linux的I2C驱动架构
· Linux内核崩溃转储机制
· Linux对EXT3分区大小进行...
· 设定Linux操作系统的启动...
· 使用Inotify 监控Linux ...

热点文章

更多

相关文章

更多

B11