2011-01-21 77 views
6

我在阅读“Linux设备驱动程序第3版”,关于并发性和竞争条件的章节。有一个我不完全明白的例子。他们正在讨论内核编程中的一种常见模式,当需要在当前线程之外启动活动(例如,新的内核线程或用户进程,请求现有进程或基于硬件的操作)时,请等待该活动完成。不是非常有效的解决方案的例子是:Linux内核互斥体

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

然后,他们认为外部任务调用(& SEM)时,它的工作就完成了。

我不明白为什么我们不能这样来做:

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

为什么是必要的锁定状态,以创建互斥量,然后获得任务之后互斥体已经开始了吗?

期待您的回音!谢谢。

回答

10

当您调用down()时,您的线程将阻塞,直到另一个线程发出信号指示信号。由于另一个线程尚未启动,线程将无限期阻塞。这就是为什么你需要先启动线程,然后调用down()来阻塞,直到线程完成。

如果线程在调用down()之前完成,那没问题,因为信号量将被发信号,down()将简单地清除信号并返回。

+6

+1,但我认为使用术语`semaphore`而不是`mutex`会更好。 SEMAPHORE:可以通过任何线程上/下。 MUTEX:拥有所有权,只有锁拥有者线程可以启用互斥锁。在这种情况下,我们需要使用信号量,因为它的目的是线程之间的通信... – Vojta 2011-01-21 11:06:39

3

在第一个示例中,down(& sem)将等待external_task调用(& sem)并有效地暂停主线程,直到任务完成。 在你的代码向下()将永远锁定主线程,因为没有任务尚未调用()

1

召唤:

init_MUTEX_LOCKED(&sem); 

中创建初始化为0“互斥模式”的新信号。这意味着呼叫down()将被阻止。一个相应的呼叫:

init_MUTEX(&sem); 

将创建初始化为1

在你初始化信号为0,第1例的旗语,您创建external_task和你打电话down()阻塞,直到你的任务调用up()

在第二个例子中,你不初始化您的旗语,叫down()阻止执行,并没有external_task运行的可调用up()解除阻止你。创建external_task的调用因此从未达到。

顺便说一下,在内核版本2.6.37中,init_MUTEX_LOCKED初始化信号量的过程已被删除。