这种情况下,倒不如想办法终止或减少磁盘IO的频率? 回复 11# nswcfd
我也想等到事件来源,但是现在系统已经不调度了,几乎是卡死状态,没法等到事件来源。
减少磁盘操作是不可能的,原因有两个
其一,这个进程的源码不在我们手上,
其二,这个进程本身是个下载器,不操作磁盘不可能。
所以,我现在期望能达到的最好效果就是,OOM的时候kill这个进程,保证系统不被卡死。 11楼表达的不准确,意思是接管内核的disk io入口(hack/hack/hack),替换成空操作,避免新的io操作产生。
这样,旧的请求才能及时被旧的io模块满足,产生wakeup调用,进程才能结束D状态。
当然,也可以去模拟disk io的complete事件,终极目标是触发wakeup。
不太建议绕过io系统去直接wakeup处于D状态的进程,除非先cancel掉原来的wait。
不建议的原因是出于稳定性考虑。
waitq通常位于等待进程的stack上(类似DEFINE_WAIT),如果自行把进程wakeup,则进程会继续执行。
像楼主的例子,就响应OOM的kill signal结束进程了。
但是io子系统不知道这些事情,当事件完成后,依然会调用wakeup,去修改waitq的状态。
这时候就不知道会touch到谁的内存了。 回复 13# nswcfd
我是这样做的,直接active,但还是杀不掉int kill_etm(void)
{
int ret = 0;
struct task_struct *p;
read_lock(&tasklist_lock);
for_each_process(p){
if(!strcmp("my_process_name", p->comm)){
oom_kill_task(p, NULL);
ret = 1;
break;
}
}
read_unlock(&tasklist_lock);
if(likely(ret) && likely(p!=current)){
printk("%s active %s and schedule()\n", __func__, p->comm);
activate_task_priv(p);
schedule_timeout_uninterruptible(HZ>>2);
}
return ret;
} 不好意思,忽略了一件事情,D状态是不考虑signal的。#define __wait_event(wq, condition) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
finish_wait(&wq, &__wait); \
} while (0)其中的schedule会被楼主显式的wake_up恢复,但是如果继续检查条件(IO未完成等),还是不满足,继续schedule。
关键还是得破坏(或者说满足)condition条件。 回复 15# nswcfd
D状态不响应signal我是知道的,我理解的不响应只是暂时不响应,信号被挂起而已,等到进程退出D状态的时候,就会响应了。难道我理解错了? 本帖最后由 bfdhczw 于 2015-12-29 10:36 编辑
回复 15# nswcfd #define __wait_event(wq, condition) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
if(current->force_quit)\
break;\
schedule(); \
} \
finish_wait(&wq, &__wait); \
if(current->force_quit){\
printk("=========> force_quit at %s\n", __func__);\
force_sig(SIGKILL, current);\
}\
} while (0)我把代码改成了这样,在task_struct里面加了force_quit成员,看起来wait queue上不会出什么问题,不知道会不会引起其他问题。
目前还没有测试结果,等后面有测试结果了,再继续更新状况。 回复 16# bfdhczw
“退出D状态去响应信号”不会平白无故的发生,一定对应某个kernel code path,比如
1)等待的条件满足,结束wait_event循环,在核心态返回用户态的路径上检查信号处理;
2)像wait_event_interruptible那样,在wait循环里面,每次醒来之后显式的检查是否有信号发生,如果有退出循环,在返回用户态的路径上处理signal。
页:
1
[2]