免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5220 | 回复: 17
打印 上一主题 下一主题

[FreeBSD] 关于创建和取消内核线程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-06-10 16:29 |只看该作者 |倒序浏览
我写了一个简单的内核模块,该模块可以运行,但是卸载该模块的时候,内核总会崩溃,然后自动重启,各位大侠来看看哪里出了错,该如何改正?
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kthread.h>


static struct proc *my_test_proc;
static void my_test_thread(void *);
void my_kthread_init(void *args);
void my_kthread_exit(void *args);

static int exit_flags = 0;



static void my_test_thread(void *args)
{
   int i;
   (void)args;
   for (i = 0; ; ++i) {
      if (exit_flags == 1) {
         break;
         //kthread_exit(0);
      }
      printf("%c", (i % 2) ? 'A' : 'B');
   }
   kthread_exit(0);
}

void my_kthread_init(void *args)
{  
   kthread_create(my_test_thread, NULL, &my_test_proc, 0, 0, "__my_trest_kthread");
}


void my_kthread_exit(void *args)
{  
   exit_flags = 1;
}


SYSINIT(my_daemon_unique, SI_SUB_KTHREAD_BUF, SI_ORDER_FIRST, my_kthread_init,
               NULL);
SYSUNINIT(my_daemon_unique, SI_SUB_KTHREAD_BUF, SI_ORDER_FIRST, my_kthread_exit,
               NULL);

论坛徽章:
0
2 [报告]
发表于 2006-06-10 16:32 |只看该作者
我把代码改为下面这样也不行:
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kthread.h>


static struct proc *my_test_proc;
static void my_test_thread(void *);
void my_kthread_init(void *args);
void my_kthread_exit(void *args);

static int exit_flags = 0;



static void my_test_thread(void *args)
{
   int i;
   (void)args;
   for (i = 0; ; ++i) {
      if (exit_flags == 1) {
         break;
         //kthread_exit(0);
      }
      printf("%c", (i % 2) ? 'A' : 'B');
   }
   kthread_exit(0);
}


static int
my_test_thread_loader(struct module *m, int what, void *arg)
{  
   int err = 0;
   switch (what) {
   case MOD_LOAD:
      kthread_create(my_test_thread, NULL, &my_test_proc, 0, 0, "__my_test_ktread");
      break;
   case MOD_UNLOAD:
      exit_flags = 1;
      break;
   default:
      err = EINVAL;
      break;
   }
   return(err);
}

static moduledata_t my_test_thread_mod = {
   "__my_test_kernel_thread",
   my_test_thread_loader,
   NULL
};

DECLARE_MODULE(my_test_thread, my_test_thread_mod, SI_SUB_KLD, SI_ORDER_ANY);

论坛徽章:
0
3 [报告]
发表于 2006-06-10 16:58 |只看该作者
难道kthread不能用在可卸载模块中?

论坛徽章:
0
4 [报告]
发表于 2006-06-10 21:36 |只看该作者
这种方法肯定是不对的,模块卸载后会导致内存释放,创建的内核线程被调度运行的时候,当然会引起错误.

论坛徽章:
0
5 [报告]
发表于 2006-06-10 23:23 |只看该作者
MOD_UNLOAD处理的时候msleep在kthread的proc上就可以了

[ 本帖最后由 mingyanguo 于 2006-6-11 10:02 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2006-06-11 10:03 |只看该作者
楼上这位大哥说的很对。critical_enter是指临界区处理吧??
现在我已经改好,可以正确退出了:
#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>


struct my_kthread_s {
        unsigned int flags;
#define MKH_THREAD_EXIT                0x01
#define MKH_THREAD_ALIVE        0x02
        struct mtx lock;
        struct proc *my_proc;
} mkh;


static void mkh_run(void *args);
static void mkh_init(void *args);
static void mkh_exit(void);


static void mkh_init(void *args)
{
        (void)args;
        mtx_init(&mkh.lock, "my_mkh_lock", NULL, MTX_DEF);
        mkh.flags = 0;
        mkh.flags |= MKH_THREAD_ALIVE;
}


static void mkh_exit(void)
{
        mkh.flags |= MKH_THREAD_EXIT;
        mtx_lock(&mkh.lock);
        while (mkh.flags & MKH_THREAD_ALIVE) {
                        msleep(&mkh.my_proc, &mkh.lock, PRIBIO, "mkh_exit", 0);
        }
        mtx_unlock(&mkh.lock);
}


static void mkh_run(void *args)
{
        int i;
        (void)args;

        for (i = 0; ; ++i) {
                printf("%c", (i % 2) ? 'A' : '~');
                mtx_lock(&mkh.lock);
                if (mkh.flags & MKH_THREAD_EXIT)
                        break;
                mtx_unlock(&mkh.lock);
        }
        mkh.flags &= ~(MKH_THREAD_EXIT | MKH_THREAD_ALIVE);
        wakeup(&mkh.my_proc);
        mtx_unlock(&mkh.lock);
       
        kthread_exit(0);
}



static int
my_test_thread_loader(struct module *m, int what, void *arg)
{
        int err = 0;
        switch (what) {
        case MOD_LOAD:
                mkh_init(NULL);
                kthread_create(mkh_run, NULL, &mkh.my_proc, 0, 0, "__my_test_ktread");
                break;
        case MOD_UNLOAD:
                mkh_exit();
                break;
        default:
                err = EINVAL;
                break;
        }
        return err;
}

static moduledata_t my_test_thread_mod = {
        "__my_test_kernel_thread",
        my_test_thread_loader,
        NULL
};

DECLARE_MODULE(my_test_thread, my_test_thread_mod, SI_SUB_KLD, SI_ORDER_ANY);

论坛徽章:
0
7 [报告]
发表于 2006-06-11 11:26 |只看该作者
你这样还是不太好,麻烦而且仍然存在一个窗口,如果mtx_unlock中被抢占,那么仍然可能会panic,所以,在MOD_UNLOAD的时候直接msleep在proc上就可以了,在exit1中,如果是kthread,内核会唤醒睡眠在proc上的进程,比较简单,而且稳定.

论坛徽章:
0
8 [报告]
发表于 2006-06-11 14:44 |只看该作者
多谢楼上仁兄一番指点。不过看内核中一些代码也用mutex了,我再考虑一下。

论坛徽章:
0
9 [报告]
发表于 2006-06-12 08:57 |只看该作者
还有疑惑弱弱的问一下,在SMP系统中,多个内核线程会被调度到多个CPU上执行吗?

论坛徽章:
0
10 [报告]
发表于 2006-06-12 12:04 |只看该作者
应该会,不过你可以把他pin(sched_pin)到一个CPU上.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP