Форум программистов, компьютерный форум, киберфорум
Наши страницы
С под Linux
Войти
Регистрация
Восстановить пароль
 
den25
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 5
1

Загружаемый модуль ядра зависает

03.01.2018, 11:39. Просмотров 375. Ответов 6
Метки нет (Все метки)

Добрый день. Пишу загружаемый модуль ядра, который должен через заданный интервал времени отправлять данные устройству. Однако после первого срабатывания таймера вся система зависает и приходится перезагружать компьютер. При этом светодиод на устройстве загорается, т.е. данные должны были отправиться. Подскажите, пожалуйста, в чем может быть проблема.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
 
/*---------------------------------------------------------------------------*/
/*                               DEVICE DECLARATIONS                         */
/*---------------------------------------------------------------------------*/
 
#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/hidraw.h>
 
#define VENDOR_ID 0x03EB
#define PRODUCT_ID 0x204F
#define DRIVER_NAME "blm_driver"
 
static struct hid_device *blm;
 
static int blm_probe(struct hid_device *hdev,
    const struct hid_device_id *id);
static void blm_remove(struct hid_device *dev);
 
static const struct hid_device_id blm_id_table[] =
{
    { HID_USB_DEVICE(VENDOR_ID, PRODUCT_ID) }, {}
};
 
static struct hid_driver blm_driver =
{
    .name = DRIVER_NAME,
    .id_table = blm_id_table,
    .probe = blm_probe,
    .remove = blm_remove
};
 
/*---------------------------------------------------------------------------*/
/*                               TIMER DECLARATIONS                          */
/*---------------------------------------------------------------------------*/
 
#include <linux/timer.h>
#include <linux/interrupt.h>
 
#define IO_PERIOD 1000
 
static struct timer_list io_timer;
static unsigned long io_timer_data;
 
static void init_io_timer(void);
static void delete_io_timer(void);
static void restart_io_timer(unsigned period);
static void io_timer_func(unsigned long data);
 
/*---------------------------------------------------------------------------*/
/*                               DEVICE OPERATIONS                           */
/*---------------------------------------------------------------------------*/
 
static int blm_probe(struct hid_device *dev,
                            const struct hid_device_id *id)
{
    printk(KERN_INFO "Device connected.\n");
 
    int err = hid_parse(dev);
    if (err)
    {
        printk(KERN_ERR "Parse failed.\n");
        return err;
    }
 
    err = hid_hw_start(dev, HID_CONNECT_HIDRAW);
    if (err)
    {
        printk(KERN_ERR "Start failed.\n");
        return err;
    }
 
    err = hid_hw_open(dev);
    if (err)
    {
        printk(KERN_ERR "Cannot open hidraw.\n");
        return err;
    }
 
    blm = dev;
 
    init_io_timer();
    restart_io_timer(IO_PERIOD);
 
    return 0;
}
 
static void blm_remove(struct hid_device *dev)
{
    printk(KERN_INFO "Device disconnected.\n");
 
    hid_hw_close(dev);
    hid_hw_stop(dev);
 
    delete_io_timer();
}
 
/*---------------------------------------------------------------------------*/
/*                               TIMER OPERATIONS                            */
/*---------------------------------------------------------------------------*/
 
static void init_io_timer(void)
{
    init_timer(&io_timer);
    io_timer.function = io_timer_func;
}
 
static void delete_io_timer(void)
{
    del_timer(&io_timer);
}
 
static void restart_io_timer(unsigned period)
{
    io_timer.expires = jiffies + period;
    add_timer(&io_timer);
}
 
static void io_timer_func(unsigned long data)
{
    printk(KERN_INFO "Interrupted %d times.\n", io_timer_data++);
 
    __u8 *io_data = kmalloc(1, GFP_KERNEL);
    if (!io_data)
    {
        printk(KERN_ERR "Out of memory.\n");
        return;
    }
 
    io_data[0] = 0b10000000;
    int err = hid_hw_raw_request(blm, 0, io_data, 1,
        HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
    if (err < 0)
    {
        printk(KERN_ERR "Could not send data to device.\n");
    }
    else
    {
        printk(KERN_INFO "Sent data to device.\n");
    }
 
    kfree(io_data);
 
    if (err > 0)
    {
        restart_io_timer(IO_PERIOD);
    }
}
 
/*---------------------------------------------------------------------------*/
/*                               MODULE OPERATIONS                           */
/*---------------------------------------------------------------------------*/
 
module_driver(blm_driver, hid_register_driver, hid_unregister_driver);
 
MODULE_LICENSE("GPL");
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.01.2018, 11:39
Ответы с готовыми решениями:

Написать простейший модуль ядра
Привет. Необходимо написать простейший модуль ядра. Имеются следующие...

Модуль ядра, работа с мышью
Здравствуйте, нужно написать модуль ядра Linux,который будет при нажатии...

Модуль ядра, вывод сообщения в dmesg
Я реализовал это таким образом, но msleep вешает консоль. int record(void) {...

Модуль ядра, создающий файл с текстом
Здравствуйте. Файл proc_module.c. Его задача создать файл, в котором будет...

Модуль ядра и прерывания от сетевой карты
Здравствуйте! Учусь писать модули ядра. Посоветуйте, каким образом можно...

6
peter_irich
41 / 41 / 14
Регистрация: 18.10.2017
Сообщений: 362
03.01.2018, 18:48 2
Я не могу ответить, т.к. сам драйверов не писал, но какое из printk() последнее?
И почему заголовочные файлы не из linux-headers? Для драйверов должны браться оттуда:
/lib/modules/$(uname -r)/build/include/linux

Пётр.
0
den25
0 / 0 / 0
Регистрация: 15.05.2016
Сообщений: 5
03.01.2018, 19:11  [ТС] 3
Цитата Сообщение от peter_irich Посмотреть сообщение
Я не могу ответить, т.к. сам драйверов не писал, но какое из printk() последнее?
И почему заголовочные файлы не из linux-headers? Для драйверов должны браться оттуда:
/lib/modules/$(uname -r)/build/include/linux

Пётр.
Пётр, все заголовочные файлы из linux-headers. Модуль собирается и устанавливается. Функция blm_probe отрабатывает без ошибок (проверял отдельно без таймера). Для сборки использую такой makefile:
Код
obj-m := blm_driver.o
KVERSION := $(shell uname -r)
KDIR := /lib/modules/$(KVERSION)/build
PWD := $(shell pwd)
modules modules_install clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) $@
install: modules_install
	install -D -m 0644 blm.conf /etc/modprobe.d/blm.conf
	depmod -a
uninstall:
	bash uninstall.sh
0
peter_irich
41 / 41 / 14
Регистрация: 18.10.2017
Сообщений: 362
03.01.2018, 20:54 4
Не могу сказать. Разве что установка io_data меня смущает, должно быть явное приведение "void *" к типу.
Во всяком случае, в обычных программах так требуется.

Пётр.
0
tmpValue
41 / 74 / 15
Регистрация: 04.10.2017
Сообщений: 284
05.01.2018, 07:56 5
Цитата Сообщение от den25 Посмотреть сообщение
система зависает и приходится перезагружать компьютер
Типичная проблема ошибки выхода из цикла. Выявляется отладкой.
0
rosten
23 / 5 / 1
Регистрация: 05.01.2017
Сообщений: 56
05.01.2018, 08:06 6
io_data[0] = 0b10000000;


затирается участок памяти, где находится указатель.

Не проверял свои рассуждения, но всёравно пишу.

io_data это указатель на динамически выделенную память. находящийся по адресу 0x123450 и указывающий на 0x555555
если обращаться к io_data ,как к массиву. То компилятор воспримет это как обращение к массиву, чей первый элемент (под индексом ноль) находится по этому адресу - 0x123450.

делая так : io_data[0] = 0b10000000;
ты превращаешь
io_data == 0x555555
в
io_data = 0b10000000


ну а далее через kfree освобождаешь память по адресу 128 (могбы хоть код упростить, убрать двоичное значение)
естественно такое освобождение памяти приводит к зависанию.
1
Olej
322 / 170 / 24
Регистрация: 25.03.2012
Сообщений: 712
10.01.2018, 21:13 7
Цитата Сообщение от den25 Посмотреть сообщение
Пишу загружаемый модуль ядра, который должен через заданный интервал времени отправлять данные устройству. Однако после первого срабатывания таймера вся система зависает и приходится перезагружать компьютер.
Это обычная практика при начальном вхождении в этот предмет (ядро Linux).
Никто детально рыться в вашем конкретном коде не станет ... зато я, как писавший множество целевых модулей для Linux (в отличие от общих рассуждений), могу вас подбросить вот такие 2 (но они сильно похожи) руководства по написанию модулей ... больше 400 стр. каждое + несколько сот примеров кода - это может вам сильно помочь.
Вот они:
Практикум по Linux Kernel
Драйверы и модули ядра Linux (очередной цикл обновлений)
Вы там найдёте самые разнообразные примеры работающего кода.
1
10.01.2018, 21:13
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.01.2018, 21:13

Модуль ядра линукс ошибка make файла
Помогите пожалуйста.Первый раз пытаюсь написать ядро,и ничего не получается....

Написать модуль ядра, который будет блокировать определённые кнопки мыши
Здравствуйте! По заданию нужно написать модуль ядра Linux,который будет...

Написать модуль ядра, который сохраняет в файле журнала все операции изменения файлов внутри заданного каталог
Написать модуль ядра, который сохраняет в файле журнала все операции изменения...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru