识别Linux内核模块中的错误

雷伊

我正在标记Michael,因为他是第一个。感谢osgx和当月的员工,以获取更多信息和帮助。

我正在尝试确定使用者/生产者内核模块中的错误。这是我上大学课程时遇到的一个问题。我的助教无法弄清楚,我的教授说,如果我在线上传也可以(他认为Stack无法弄清楚!)。

  • 我已经包含了模块,makefile和Kbuild。
  • 运行该程序并不能保证该错误会自行出现。
  • 我认为问题出在第30行,因为一个线程有可能冲到第36行,而使其他线程饿死。我的教授说那不是他要找的东西。
  • 不相关的问题:40行的目的是什么?在我看来,这似乎不合适,但我的教授说,这是一种目的。
  • 我的教授说,这个错误非常微妙。该错误不是死锁。
  • 我的方法是确定关键部分和共享变量,但是我很困惑。我对跟踪(作为一种调试方法)不熟悉,并被告知尽管这可能会有所帮助,但不必找出问题所在。

档案:final.c

#include <linux/completion.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/module.h>

static int actor_kthread(void *);
static int writer_kthread(void *);

static DECLARE_COMPLETION(episode_cv);
static DEFINE_SPINLOCK(lock);
static int episodes_written;
static const int MAX_EPISODES = 21;
static bool show_over;
static struct task_info {
    struct task_struct *task;
    const char *name;
    int (*threadfn) (void *);
} task_info[] = {
    {.name = "Liz", .threadfn = writer_kthread},
    {.name = "Tracy", .threadfn = actor_kthread},
    {.name = "Jenna", .threadfn = actor_kthread},
    {.name = "Josh", .threadfn = actor_kthread},
};

static int actor_kthread(void *data) {
    struct task_info *actor_info = (struct task_info *)data;
    spin_lock(&lock);
    while (!show_over) {
        spin_unlock(&lock);
        wait_for_completion_interruptible(&episode_cv); //Line 30
        spin_lock(&lock);
        while (episodes_written) {
            pr_info("%s is in a skit\n", actor_info->name);
            episodes_written--;
        }
        reinit_completion(&episode_cv); // Line 36
    }

    pr_info("%s is done for the season\n", actor_info->name);
    complete(&episode_cv); //Why do we need this line?
    actor_info->task = NULL;
    spin_unlock(&lock);
    return 0;
}

static int writer_kthread(void *data) {
    struct task_info *writer_info = (struct task_info *)data;
    size_t ep_num;

    spin_lock(&lock);
    for (ep_num = 0; ep_num < MAX_EPISODES && !show_over; ep_num++) {
        spin_unlock(&lock);

        /* spend some time writing the next episode */
        schedule_timeout_interruptible(2 * HZ);

        spin_lock(&lock);
        episodes_written++;
        complete_all(&episode_cv);
    }

    pr_info("%s wrote the last episode for the season\n", writer_info->name);
    show_over = true;
    complete_all(&episode_cv);
    writer_info->task = NULL;
    spin_unlock(&lock);
    return 0;
}

static int __init tgs_init(void) {
    size_t i;
    for (i = 0; i < ARRAY_SIZE(task_info); i++) {
        struct task_info *info = &task_info[i];
        info->task = kthread_run(info->threadfn, info, info->name);
    }
    return 0;
}

static void __exit tgs_exit(void) {
    size_t i;
    spin_lock(&lock);
    show_over = true;
    spin_unlock(&lock);
    for (i = 0; i < ARRAY_SIZE(task_info); i++)
        if (task_info[i].task)
            kthread_stop(task_info[i].task);
}

module_init(tgs_init);
module_exit(tgs_exit);
MODULE_DESCRIPTION("CS421 Final");
MODULE_LICENSE("GPL");

档案:kbuild

Kobj-m := final.o

文件:Makefile

# Basic Makefile to pull in kernel's KBuild to build an out-of-tree
# kernel module

KDIR ?= /lib/modules/$(shell uname -r)/build

all: modules

clean modules:
迈克尔·伯尔

tgs_exit()函数中进行清理时,在不按住自旋锁的情况下执行以下操作:

    if (task_info[i].task)
        kthread_stop(task_info[i].task);

task_info[i].task在检查和调用之间,即将结束的线程可能会将其设置为NULL kthread_stop()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章