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