2015-10-25 1 views
1

Я пытаюсь сделать проект программирования из первой главы книги «Концепции операционной системы». Задача состоит в том, чтобы написать модуль ядра Linux, который выполняет итерацию структур, используя структуру данных списка ядра. Я написал следующий код:Ядерный модуль Linux зависает во время разгрузки

#include <linux/init.h> 
#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/list.h> 
#include <linux/slab.h> 

struct birthday { 
    int day; 
    int month; 
    int year; 
    struct list_head list; 
}; 

struct list_head birthday_list; 

struct birthday *createBirthday(int day, int month, int year) 
{ 
    struct birthday *person = kmalloc(sizeof(struct birthday), GFP_KERNEL); 

    person->day = day; 
    person->month = month; 
    person->year = year; 

    return person; 
} 

void printInfo(char *str) 
{ 
    printk(KERN_INFO "OS Module: %s", str); 
} 

int simple_init(void) 
{ 
    struct birthday *person = createBirthday(13, 4, 1987); 
    struct birthday *ptr; 

    printInfo("Loading Module\n"); 

    LIST_HEAD(birthday_list); 

    list_add_tail(&person->list, &birthday_list); 
    person = createBirthday(14, 4, 1987); 
    list_add_tail(&person->list, &birthday_list); 
    person = createBirthday(15, 4, 1987); 
    list_add_tail(&person->list, &birthday_list); 
    person = createBirthday(16, 4, 1987); 
    list_add_tail(&person->list, &birthday_list); 
    person = createBirthday(17, 4, 1987); 
    list_add_tail(&person->list, &birthday_list); 

    list_for_each_entry(ptr, &birthday_list, list) { 
     printk(KERN_INFO "OS Module: Day %d.%d.%d\n", ptr->day, ptr->month, ptr->year); 
    } 

     return 0; 
} 

void simple_exit(void) 
{ 
    struct birthday *tmp; 
    struct list_head *ptr, *next; 

    printInfo("Removing Module\n"); 

    if (list_empty(&birthday_list)) { 
     printInfo("List is empty"); 
     return; 
    } 

    list_for_each_safe(ptr, next, &birthday_list){ 
     tmp = list_entry(ptr, struct birthday, list); 
     printk(KERN_INFO "OS Module: Removing %d.%d.%d\n", tmp->day, tmp->month, tmp->year); 
     list_del(ptr); 
     kfree(tmp); 
    } 

    //list_for_each_entry_safe(ptr, next, &birthday_list, list) { 
    // printk(KERN_INFO "OS Module: Removing %d.%d.%d\n", ptr->day, ptr->month, ptr->year); 
    // list_del(&ptr->list); 
    // kfree(ptr); 
    //} 

    printInfo("Module removed\n"); 
} 

module_init(simple_init); 
module_exit(simple_exit); 

MODULE_LICENSE("GPL"); 
MODULE_DESCRIPTION("Simple Module"); 
MODULE_AUTHOR("MP"); 

После установки и удаления модуля я не видел сообщений об удалении модуля.

~/kernelModule $ sudo insmod simple.ko 
~/kernelModule $ sudo rmmod -f simple 
~/kernelModule $ dmesg | grep 'OS Module' 
[ 386.590198] OS Module: Loading Module 
[ 386.590201] OS Module: Day 13.4.1987 
[ 386.590202] OS Module: Day 14.1.1964 
[ 386.590203] OS Module: Day 2.6.1964 
[ 386.590204] OS Module: Day 13.8.1986 
[ 386.590204] OS Module: Day 10.6.1990 
[ 396.647828] OS Module: Removing Module 
~/kernelModule $ sudo rmmod -f simple 
rmmod: ERROR: ../libkmod/libkmod-module.c:769 kmod_module_remove_module() could not remove 'simple': Device or resource busy 
rmmod: ERROR: could not remove module simple: Device or resource busy 

Как я понимаю, мой модуль висит во время удаления. И я не понимаю, почему. Оба освобождающих кода (прокомментированные тоже) заставляют модуль зависать.

+0

Вы пытались добавить еще несколько трасс 'printk', чтобы выяснить точную строку кода, где находится код? –

+1

в 'simple_init' вам нужно использовать' LIST_HEAD_INIT' вместо 'LIST_HEAD': последний * объявляет и инициализирует локальную переменную вместо инициализации глобальной. – Tsyvarev

+0

может использовать INIT_LIST_HEAD (& birthday_list) или LIST_HEAD_INIT. –

ответ

0

Использование INIT_LIST_HEAD(&birthday_list) вместо LIST_HEAD(birthday_list) помогает решить поблем.