我想卸载一个有线程的模块。我已经引用了dev/random中的代码,我的代码是这样的:
$ 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);