Linux 커널 모듈을 작성하는 동안 세마포를 잠금 해제 할 때까지 기다리지 못하는 동안 kthread에 문제가 발생했습니다. 이로 인해 모듈을 언로드 할 때 스레드가 멈추지 않고 rmmod
이 멈 춥니 다.리눅스 커널 - 세마포어를 기다리는 kthread를 멈추는 방법?
참고 :이 모듈은 3.10 커널에서 실행되며 새로운 버전으로 업데이트 할 수 없습니다
다음은 모듈 소스 코드에서 흥미로운 부분입니다. 이것은 단순한 프로듀서 소비자 문제를 나타내며, 목록의 크기가 제한되지 않으므로 (제작자 세마포어가 필요하지 않음) 뮤텍스가 보호됩니다. 목록에서 뭔가를 가져 오는 기능은 생산자가 올리고 소비자가 중단 한 세마포에 의해 보호됩니다. 생성자 함수는이 코드 조각에 표시되지 않은 외부 이벤트 (사실 char 장치)에서 가능한 한 작게 유지해야합니다. 이 프로세스는 모듈 언로드를 제외하고는 완벽하게 작동합니다.
얼어 붙는 부분은 코드 스 니펫에 주석으로 표시됩니다. 내가 kthread를 막을 수있는 유일한 방법은 kthread_stop
을 호출하는 것인데,이 경우 실패하는 것은 분명히 수면 스레드를 깨울 수 없기 때문입니다. 스레드가 종료 될 때까지 기다리기 때문에 호출이 반환되지 않고 모듈이 언로드되지 않습니다.
모듈을 성공적으로 언로드하기 위해 세마포를 기다리는 kthread를 깨우고 중지 할 수 있습니까?
목록 구현 :
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/semaphore.h>
static LIST_HEAD(list);
DEFINE_MUTEX(list_lock);
DEFINE_SEMAPHORE(sem_list_consumer);
void add_to_list(struct *some_struct) {
int rv = mutex_lock_interruptible(&list_lock);
if(rv != 0) {
return;
}
list_add(&some_struct->list, &list);
mutex_unlock(&list_lock);
up(&sem_list_consumer);
}
struct some_struct * take_from_list() {
int rv;
some_struct *entry;
/* this is where the kthread will freeze when module is unloaded */
rv = down_interruptible(&sem_list_consumer);
if(rv != 0) {
return NULL;
}
rv = mutex_lock_interruptible(&list_lock);
if(rv != 0) {
up(&sem_list_consumer);
return NULL;
}
if (list_empty(&list)) {
mutex_unlock(&list_lock);
return NULL;
} else {
entry = list_last_entry(&list, struct some_struct, list);
if (entry) {
list_del(&entry->list);
}
}
mutex_unlock(&list_lock);
return entry;
}
소비자 kthread는 구현 :
#include <linux/kthread.h>
#include <linux/sched.h>
int consumer_kthread(void *data) {
struct some_struct *entry;
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
/* Here the function including the semaphore is called */
entry = take_from_list();
if(entry != NULL) {
/* Do something with 'entry' here */
} else {
/* Some handling of returned NULL pointers */
}
set_current_state(TASK_INTERRUPTIBLE);
}
set_current_state(TASK_RUNNING);
return 0;
}
모듈 구현 :
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/sched.h>
static struct task_struct *consumer_task;
static int __init initModule(void) {
consumer_task = kthread_run(consumer_kthread, NULL, "list-consumer");
return 0;
}
static void __exit exitModule(void) {
/* this call will cause rmmod to freeze forever */
kthread_stop(consumer_task);
}
module_init(initModule);
module_exit(exitModule);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("My Module");
'take_from_list' 함수에는'NULL '을 반환하는 곳이 세 곳 있습니다. 이 세 곳 중 하나에서'sem_list_consumer' 세마포어를 가지고있는 동안 리턴합니다. 나는이 불일치가 당신의 문제와 관련이 있다고 생각합니다. 그렇지 않으면 호출자가 세마포어를 해제해야하는지 여부를 어떻게 알 수 있습니까? –
나중에 문제가 발생할 수 있지만 프로듀서 코드를 호출하지 않고도 모듈을로드 및 언로드하는 경우에도 문제가 발생합니다. 또한 문제는 뭔가가 kthread를 중단 시키거나 깨우는 경우에만 발생합니다. 그러나 이것이 내가 달성하지 못한 것입니다. – marandus
이미 생산자 코드가 문제가 아니므로 오류가 소비자 코드에 있습니다. 누락 된 코드 때문에 말할 수 없지만,'take_from_list' 함수에서'mutex_unlock (& list_lock);과'return NULL; '줄 사이에'up (& sem_list_consumer);를 호출하면됩니다. 'take_from_list'가'NULL'을 반환 할 때에도'sem_list_consumer' 세마포어가 유지되기를 기대하지 않는다면,'take_from_list'를 다루어야 할 필요가 있습니다. 세마포어를 가지지 않고'NULL'을 반환하는 경우도 있습니다. –