所以我试图使用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()
之前将互斥锁解锁,然后立即重新锁定。完成逻辑部分后,我将完全解锁互斥锁。这种方法有什么根本的错误吗?
最佳答案
是的,那是真的。但是,如果您使用互斥锁,您将很难过,因为对lock
/unlock
的调用是对调度程序的调用。因此,从调度程序内部调用它会导致死锁。您需要做什么取决于您的处理器是多核还是(神话般的)单核。 (这是一个虚拟系统吗?)在单核处理器上,您可以禁用中断。在多核处理器上,禁用中断是不够的(仅禁用该一个内核的中断,而另一个内核可能仍被中断)。在多核上最简单的操作是使用自旋锁。与互斥锁不同,这两种锁定机制都可以从不同的线程中解锁。
线程是否已从CPU移走?如果是这样,它就没有运行,因此我怀疑TASK_INTERRUPTIBLE
是错误的状态。如果您可以为我列出可能的状态,或者可以描述状态应该指示的内容,则将很有帮助。因为对我来说,“TASK_INTERRUPTIBLE
”听起来像是一个正在运行的任务。
本地互斥锁是一个危险信号!您要锁定的资源应由具有相同作用域的互斥锁保护。如果列表是全局的,则它应该具有全局互斥来保护它。想要使用列表的线程必须首先获取其互斥量。当然,正如我已经说过的那样,您可能希望使用另一种类型的锁定来保护准备运行的进程列表。
这是完全合法的(当然,假设您的互斥方案没有错误)。实际上,这是必需的。例如,如果允许另一个线程在读取列表时将其从列表中删除,则最终可能会取消引用已删除的节点。
不,如果进程当前在CPU上运行,则不持有锁。互斥锁可用于用户代码。如果持有互斥锁使进程不间断,则意味着进程可以通过简单地锁定互斥锁而从不释放互斥锁来劫持系统。现在,您将发现lock
和unlock
函数在单核处理器上需要不间断。但是,设置进程的状态没有任何意义,因为实际上是调度程序,不能被中断。
关于linux - 内核编程-互斥,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52541014/