内核编程-互斥体

时间:2018-09-27 16:03:56

标签: linux multithreading kernel-module

因此,我尝试使用mutex_init()mutex_lock()mutex_unlock()进行线程同步。

我当前正在尝试以循环方式调度线程(但是一次可以运行多个线程),我将线程的当前状态设置为TASK_INTERRUPTIBLE,然后唤醒另一个线程我的PID在列表中

我需要为我的逻辑遍历此列表。

据我了解,我需要在访问列表元素时锁定该列表,否则在我对其进行更改时另一个线程可能会丢失一个新条目。另外,由于一个互斥锁已锁定资源,因此其他互斥锁无法解锁该资源,直到原始互斥锁释放该资源为止。

但是,我仍然不确定是否正确锁定了它。 (我在致电schedule()之前先解除锁定,然后再重新锁定)

我在线程内本地声明了一个互斥锁并锁定了列表。在我当前的线程锁定之后

mutex_lock(&lock); 

然后我遍历该列表,直到找到某物(或者如果找不到则结束),然后解锁。

mutex_unlock(&lock);

我认为在进行迭代时锁定是合法的。我从未见过这样的例子。

此外,当进程持有互斥锁时,它的状态为(TASK_UNINTERRUPTIBLE是正常的吗?

编辑::我将根据以下答案添加更多信息。

我的程序有可能在具有单核的虚拟机上运行。因此,我不想冒险使用spin_lock()进行无限轮询。

我正在尝试维护具有特定ID的线程之间的调度。例如,如果有4个线程。 “ A”组中为2个,“ B”组中为2个。我在每个集中只允许运行1个线程。但是我在给定集中的线程之间切换。但是,集合'A'中的线程不应切换到集合'B'中的任何线程

(我知道内核调度程序不会是完美的,因此可以进行近似切换)。

我对TASK_STATE的推理

1)创建的初始线程正在运行。

2)如果同一组中的另一个线程正在运行(并且该线程在给定时间内未执行)。在调用TASK_INTERRUPTIPLE的同时将其他线程设置为schedule()注意:每组中可以有2个以上的线程,但现在仅考虑2个就可以保持简单。

3)如果执行了足够的时间,则将此任务设置为TASK_INTERRUPTIPLE,同时调用TASK_RUNNING时将同一任务中的另一个任务设置为schedule();

所有这些逻辑发生在我访问由(现在)全局互斥锁锁定的某些数据结构时。我在致电schedule()之前就解锁了互斥锁,此后立即重新锁定。完成逻辑部分后,我将完全解锁互斥锁。

这种方法有根本的错误吗?

1 个答案:

答案 0 :(得分:1)

  

据我了解,我需要在访问其元素时锁定此列表

是的,是的。但是,如果您使用互斥锁,您将很难过,因为对lock / unlock 的调用是对调度程序的调用。因此,从调度程序内部调用它会导致死锁。您需要做什么取决于您的处理器是多核还是(神话般的)单核。 (这是一个虚拟系统吗?)在单核处理器上,您可以禁用中断。在多核处理器上,禁用中断是不够的(仅禁用一个内核的中断,而另一个内核可能仍被中断)。在多核上最简单的操作是使用自旋锁。与互斥锁不同,这两种锁定机制都可以从不同的线程解锁。

  

我将线程的当前状态设置为TASK_INTERRUPTIBLE

线程是否已从CPU移走?如果是这样,它就没有运行,因此我怀疑TASK_INTERRUPTIBLE是错误的状态。如果您可以为我列出可能的状态,或者可以描述状态应该指示的内容,则将很有帮助。因为对我来说,“ TASK_INTERRUPTIBLE”听起来像是一个正在运行的任务。

  

我在线程本地声明一个互斥锁并锁定列表

本地互斥锁是一个危险信号!您锁定的资源应由具有相同作用域的互斥锁保护。如果列表是全局的,则它应该具有全局互斥来保护它。想要使用该列表的线程必须首先获取其互斥量。当然,正如我已经说过的那样,您可能想使用另一种类型的锁定来保护准备运行的进程列表。

  

我认为迭代合法时会锁定

这是完全合法的(当然,假设您的互斥方案没有错误)。实际上,这是必需的。例如,如果允许另一个线程在读取列表时从列表中删除一个节点,则最终可能会取消引用已删除的节点。

  

此外,当进程持有互斥锁时,其状态为TASK_UNINTERRUPTIBLE是否正常?

否,如果该进程当前在CPU上运行,则不持有该锁。互斥锁可用于用户代码。如果持有互斥锁使进程不间断,则意味着进程可以通过简单地锁定互斥锁而从不释放它来劫持系统。现在,您将发现lockunlock函数在单核处理器上需要不间断。但是,为进程设置状态没有任何意义,因为实际上是调度程序,不能被中断。