1
我想卸載一個有線程的模塊。我曾經引用的開發/隨機碼,和我的代碼是這樣的:如何卸載在FreeBSD中創建kproc/kthread的內核模塊
$ cat tmp.c
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kthread.h>
/*
* $ ps auxH | grep kproc
*/
static int kproc_control = 1;
#define output_id(p, td, fmt, args...) \
printf("%s[%d]:%s[%d]:[%s] %s\n", p->p_comm, p->p_pid, \
td->td_name, td->td_tid, __func__, msg)
static void thread_routine(void *arg)
{
char *msg = arg;
struct thread *td = curthread;
struct proc *p = td->td_proc;
output_id(p, td, msg);
pause("-", hz * 100);
output_id(p, td, msg);
kthread_exit();
}
static void proc_routine(void *arg)
{
char *msg = arg;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct thread *ntd;
int error;
output_id(p, td, msg);
error = kthread_add(thread_routine, "I'm kthread", p, &ntd,
0, 0, "kthread");
if (error)
printf("error: %d\n", error);
while (kproc_control >= 0) {
pause("-", hz/10);
}
wakeup(&kproc_control);
kproc_exit(0);
}
static int foobar_init(void)
{
int error;
struct proc *p;
error = kproc_create(proc_routine, "I'm kproc", &p, 0, 0, "kproc");
uprintf("error: %d\n", error);
return error;
}
static void foobar_fini(void)
{
kproc_control = -1;
tsleep(&kproc_control, 0, "term", 0);
//pause("delay", 2 * hz);
}
static int
foobar_modevent(module_t mod __unused, int event, void *arg __unused)
{
int error = 0;
switch (event) {
case MOD_LOAD:
error = foobar_init();
break;
case MOD_UNLOAD:
foobar_fini();
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
static moduledata_t foobar_mod = {
"foobar",
foobar_modevent,
NULL
};
DECLARE_MODULE(foobar, foobar_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
當我通過kldunload卸載它,我的內核崩潰,系統重新啓動。什麼是解決這個問題的正確方法?任何意見將不勝感激! ;-)
PS。我可以睡& p-> p_stype嗎?我在exit1()中看到以下代碼:
/*
* Note that we are exiting and do another wakeup of anyone in
* PIOCWAIT in case they aren't listening for S_EXIT stops or
* decided to wait again after we told them we are exiting.
*/
p->p_flag |= P_WEXIT;
wakeup(&p->p_stype);
PS。更新代碼:
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/mutex.h>
/*
* $ ps auxH | grep kproc
*/
static int kproc_control = 1;
static struct proc *foobar_proc;
static struct mtx mtx;
#define output_id(p, td, fmt, args...) \
printf("%s[%d]:%s[%d]:[%s] %s\n", p->p_comm, p->p_pid, \
td->td_name, td->td_tid, __func__, msg)
static void thread_routine(void *arg)
{
char *msg = arg;
struct thread *td = curthread;
struct proc *p = td->td_proc;
output_id(p, td, msg);
pause("-", hz * 100);
output_id(p, td, msg);
kthread_exit();
}
static void proc_routine(void *arg)
{
char *msg = arg;
struct thread *td = curthread;
struct proc *p = td->td_proc;
struct thread *ntd;
int error;
output_id(p, td, msg);
error = kthread_add(thread_routine, "I'm kthread", p, &ntd,
0, 0, "kthread");
if (error)
printf("error: %d\n", error);
mtx_lock(&mtx);
while (kproc_control >= 0) {
mtx_unlock(&mtx);
pause("-", hz/10);
mtx_lock(&mtx);
}
mtx_unlock(&mtx);
kproc_exit(0);
}
static int foobar_init(void)
{
int error;
mtx_init(&mtx, "foobar_mtx", NULL, MTX_DEF);
error = kproc_create(proc_routine, "I'm kproc", &foobar_proc, 0, 0, "kproc");
uprintf("error: %d\n", error);
return error;
}
static void foobar_fini(void)
{
mtx_lock(&mtx);
kproc_control = -1;
//mtx_sleep(foobar_proc, &mtx, 0, "waiting", 0);
mtx_sleep(&foobar_proc->p_stype, &mtx, 0, "waiting", 0);
}
static int
foobar_modevent(module_t mod __unused, int event, void *arg __unused)
{
int error = 0;
switch (event) {
case MOD_LOAD:
error = foobar_init();
break;
case MOD_UNLOAD:
foobar_fini();
break;
default:
error = EOPNOTSUPP;
break;
}
return (error);
}
static moduledata_t foobar_mod = {
"foobar",
foobar_modevent,
NULL
};
DECLARE_MODULE(foobar, foobar_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
非常感謝您的寶貴意見。但我認爲睡在&sc-> m_proc-> p_stype上會更好。由於'wakeup(sc-> m_proc)'是在任何其他線程退出之前在kproc_exit()中執行的,而其他線程退出時會在exit1()中執行'wakeup(&sc-> m_proc-> p_stype)'。我試着睡在sc-> m_proc上(實際上mtx_sleep(foobar_proc,&mtx,0,「waiting」,0);),但是內核再次崩潰。也許這是由於在thread_routine()中'暫停(「 - 」,hz * 100)'。但是,如果我使用mtx_sleep(&foobar_proc-> p_stype,&mtx,0,「waiting」,0),則內核仍然崩潰。 ;-( – user1907234
是否需要在'void proc(whatver){}'中'kproc_exit(0);'之前添加'mtx_unlock(&sc-> m_lock);' – user1907234
你需要等待你開始的所有事情。在你的情況下,我認爲你叫kthread_add()和kproc_create()。你應該等待這兩個退出。我沒有詳細通過你的其他代碼,但你依賴於定時器,而不是有一個正確的同步機制。 – janm