问题描述
在 wait_event_interruptible
上阅读内核源代码时,我有点困惑,因为考虑到抢占,它看起来并不安全。
下面是源码的主要逻辑:
1: #define ___wait_event(wq_head,condition,state,exclusive,ret,cmd) \
2: ({ \
3: __label__ __out; \
4: struct wait_queue_entry __wq_entry; \
5: long __ret = ret; /* explicit shadow */ \
6: \
7: init_wait_entry(&__wq_entry,exclusive ? WQ_FLAG_EXCLUSIVE : 0); \
8: for (;;) { \
9: long __int = prepare_to_wait_event(&wq_head,&__wq_entry,state);\
10: \
11: if (condition) \
12: break; \
13: \
14: if (___wait_is_interruptible(state) && __int) { \
15: __ret = __int; \
16: goto __out; \
17: } \
18: \
19: cmd; \
20: } \
21: finish_wait(&wq_head,&__wq_entry); \
22: __out: __ret; \
23: })
这个宏没有包含在抢占禁用块中,所以我认为相应的进程可能会在line 10
中被关闭。所以在以下场景下:
因此,此过程将永远停留在 TASK_INTERRUPTIBLE 中。
我想知道是这种情况还是我错过了什么?
我正在查看的 linux 代码:https://elixir.bootlin.com/linux/v5.13.4/source/include/linux/wait.h#L274
解决方法
当然,它会保持挂起,但下次当进程获得计划并恢复时,它会检查条件并发现条件为真并且会中断。
假设条件变坏,因为其他进程修改了值,然后它会挂起,直到有人向它触发信号,这个进程会检查信号并跳出 for 循环。