LINUX.ORG.RU

Динамические масивы в kernel

 , ,


0

1

Господа, прошу помощи!
Есть вот такой кусок кода:

i = 0;
num_line = 0;

list = kmalloc(100, GFP_ATOMIC);

if (!list) {
	logger(3, "tratata");
} else {
	while (i < (int)l) {
		if (buff[i] == 0x0A) {
			if ((int)ksize(list) >= num_line) {
				list[num_line] = (char *)kmalloc((int)(i - offset), GFP_KERNEL);
				if (!list[num_line]) {
					printk (KERN_INFO "Fuck... %d\n", num_line);
				}
			}
			num_line++;
			offset = i + 1;
		}
		i++;
	}
}

Здесь:
l = размер массива buff
0x0A - признак конца строки (\n)

Без этого участка, всё хорошо. А с ним ядро валится то в упс, то в панику... Причём в рандомный момент времени... Может в момент загрузки модуля, может чуть позже, может в момент выгрузки....
Этот код выполняется один раз в момент загрузки модуля....

И теперь вопрос: Что я не так навертел с этим масивом?

вот что в логе: (Здесь по моему грохнулось когда я выгружал модуль...)

Jul  5 13:35:25 test kernel: [  263.678264] Start module filter
Jul  5 13:35:52 test kernel: [  290.720042] num line 100
Jul  5 13:35:52 test kernel: [  290.720428] PGD 183cf067 PUD 1bd77067 PMD 0
Jul  5 13:35:52 test kernel: [  290.720568] Oops: 0000 [#1] SMP
Jul  5 13:35:52 test kernel: [  290.720701] Modules linked in: filter(OF-) xt_nat(F) iptable_nat(F) nf_conntrack_ipv4(F) nf_defrag_ipv4(F) nf_nat_ipv4(F) nf_nat(F) nf_conntrack(F) ip_tables(F) x_tables(F) ext2(F) joydev(F) hid_generic(F) cirrus(F) ttm(F) drm_kms_helper(F) snd_pcm(F) psmouse(F) snd_timer(F) serio_raw(F) drm(F) snd(F) tpm_tis(F) soundcore(F) snd_page_alloc(F) sysimgblt(F) microcode(F) sysfillrect(F) i2c_piix4(F) syscopyarea(F) pcspkr(F) mac_hid(F) usbhid(F) hid(F) floppy(F)
Jul  5 13:35:52 test kernel: [  290.721454] CPU 0
Jul  5 13:35:52 test kernel: [  290.721474] Pid: 1678, comm: rmmod Tainted: GF          O 3.7.6 #1 Bochs Bochs
Jul  5 13:35:52 test kernel: [  290.721724] RIP: 0010:[<ffffffffa01a94e0>]  [<ffffffffa01a94e0>] load_list+0x200/0x2e0 [filter]
Jul  5 13:35:52 test kernel: [  290.721919] RSP: 0018:ffff8800180ade68  EFLAGS: 00010202
Jul  5 13:35:52 test kernel: [  290.722076] RAX: 0000000000000000 RBX: 0000000000000880 RCX: ffffffff81e1eddc
Jul  5 13:35:52 test kernel: [  290.722226] RDX: 000000000000256e RSI: 0000000000000086 RDI: 0000000000000246
Jul  5 13:35:52 test kernel: [  290.722375] RBP: ffff8800180adeb8 R08: 000000000000fffe R09: 0000000000000006
Jul  5 13:35:52 test kernel: [  290.724016] R10: 00000000000001b5 R11: 0000000000000000 R12: ffffffffa01ab000
Jul  5 13:35:52 test kernel: [  290.724016] R13: ffff8800180adf18 R14: 0000000000000000 R15: 0000000000000001
Jul  5 13:35:52 test kernel: [  290.724016] FS:  00007f8815f23700(0000) GS:ffff88001fc00000(0000) knlGS:0000000000000000
Jul  5 13:35:52 test kernel: [  290.724016] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
Jul  5 13:35:52 test kernel: [  290.724016] CR2: 0000000000000000 CR3: 000000001bd51000 CR4: 00000000000006f0
Jul  5 13:35:52 test kernel: [  290.724016] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Jul  5 13:35:52 test kernel: [  290.724016] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Jul  5 13:35:52 test kernel: [  290.724016] Process rmmod (pid: 1678, threadinfo ffff8800180ac000, task ffff88001dff1700)
Jul  5 13:35:52 test kernel: [  290.724016] Stack:
Jul  5 13:35:52 test kernel: [  290.724016]  ffff8800180ade88 ffffffff816b25fe 0000000000000000 ffff8800180adee8
Jul  5 13:35:52 test kernel: [  290.724016]  ffff8800180ade98 0000000000000880 ffffffffa01ab000 ffff8800180adf18
Jul  5 13:35:52 test kernel: [  290.724016]  0000000000000000 0000000000000001 ffff8800180adec8 ffffffffa01a95d0
Jul  5 13:35:52 test kernel: [  290.724016] Call Trace:
Jul  5 13:35:52 test kernel: [  290.724016]  [<ffffffff816b25fe>] ? mutex_lock+0x1e/0x50
Jul  5 13:35:52 test kernel: [  290.724016]  [<ffffffffa01a95d0>] cleanup_module+0x10/0x30 [url_filter]
Jul  5 13:35:52 test kernel: [  290.724016]  [<ffffffff810bd33e>] sys_delete_module+0x19e/0x270
Jul  5 13:35:52 test kernel: [  290.724016]  [<ffffffff816b8ffa>] ? do_page_fault+0x3a/0x50
Jul  5 13:35:52 test kernel: [  290.724016]  [<ffffffff816bd699>] system_call_fastpath+0x16/0x1b
Jul  5 13:35:52 test kernel: [  290.724016] Code: 1a a0 bf 03 00 00 00 e8 0f fc ff ff eb cd 8b 35 97 1d 00 00 48 c7 c7 ca a0 1a a0 31 c0 e8 86 87 50 e1 eb 0f 48 8b 05 88 1d 00 00 <48> 8b 38 e8 58 55 fd e0 83 3d 71 1d 00 00 00 79 e8 48 8b 3d 70
Jul  5 13:35:52 test kernel: [  290.724016]  RSP <ffff8800180ade68>
Jul  5 13:35:52 test kernel: [  290.724016] CR2: 0000000000000000
Jul  5 13:35:52 test kernel: [  290.777684] ---[ end trace 65e338c3db344ba2 ]---

list = kmalloc(100, GFP_ATOMIC);

Выделил 100 байт, да?

list[num_line] = (char *)kmalloc((int)(i - offset), GFP_KERNEL);

В твоей системе размер указателя 1 байт? Крутая система.

uuwaan ★★
()
Ответ на: комментарий от uuwaan

Эм..

А как тогда надо? Подскажите пожалуйста...
Просто где я не читал, вроде везде двумерные массивы делались так...

Inversiya
() автор топика
Ответ на: комментарий от ananas

Неее...
char вроде = 1 байт (везде ли?)...
я получу те же 100 байт

а применение ksize не с проста....
во первых реально выделяется не 100 байт, а 128 (на разных архитектурах может быть по разному, не знаю)
во вторых планируется использование krealloc..

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

Насколько я понял, ты туда ложишь не char, а char*.

cdshines ★★★★★
()
Ответ на: комментарий от Inversiya

Вот скажите пожалуйста...
Если скажем я хочу сделать массив на 100 строк...

char **list;
list = kmalloc(100*8, GFP_KERNEL); // для 64 битной

1. Правилен ли пример? 2. Что-бы записать/прочитать данные первой строки куда мне надо обращаться? list[1] или list[8]?

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

char вроде = 1 байт (везде ли?)...

Почитай, чем отличается char от char*. Это разные типы данных, и размер у них разный. Из-за несоответствия размеров у тебя:

1) записи в list накладываются друг на друга сейчас;

2) при записи последнего элемента захватываются лишние байты нераспределенного пространства. когда выполняется следующий kmalloc, происходит исключительная ситуация, выливающаяся в крах.

Первый раз на C что ли пишешь?

uuwaan ★★
()
Ответ на: комментарий от Inversiya

Нет, неправильный.

list = kmalloc(100 * sizeof (char *), GFP_KERNEL);

И не экономь на пробелах, а то читать тяжело.

akk ★★★★★
()
Ответ на: комментарий от Inversiya

размер char* - не 1 байт, а sizeof(size_t).

size_t на твоей платформе, скорее всего, нечто вроде «typedef _W64 unsigned int size_t;», а sizeof(unsigned int) = 4, т.е. в 4 раза больше.

stevejobs ★★★★☆
()

l = размер массива buff
0x0A - признак конца строки (\n)

олсо проверь, чтобы в buff никак нельзя было заюзать более его ожидаемого размера, а то придет злой хакер и сделает атата

stevejobs ★★★★☆
()
Ответ на: комментарий от akk

Первый раз на C что ли пишешь?

ага... этой мой первый «проект» на Си... :)

Так, начал понемногу вникать...

С выделением памяти под весь массив понятно теперь...
А выделение памяти под массивы строк, как я понял вот так:

list[0] = kmalloc (size_string, GFP_KERNEL); // под 1 строку
list[1] = kmalloc (size_string, GFP_KERNEL); // под 2 строку
Правильно? (тут я хочу уточнить про индекс массива list)

Inversiya
() автор топика
Ответ на: комментарий от stevejobs

олсо проверь, чтобы в buff никак нельзя было заюзать более его ожидаемого размера, а то придет злой хакер и сделает атата

Не совсем понял про что вы.... Ограничить размер массива buff??

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

если туда кто-нибудь strcatнет строку длиннее BUFSIZ или что там у тебя, все данные которые не влезли в буфер просто перезапишут все, что идет в памяти дальше после буфера. Вася Пахомов может переписать стек, адрес возврата, и внезапно вместо твоего кода начнет выполняться какая-нибудь злонамеренная хрень. А когда это в ведре, то атата. Добро пожаловать в Си.

stevejobs ★★★★☆
()
Ответ на: комментарий от Inversiya

И ещё вопрос: Как правильно в момент выгрузки модуля освободить память?

int i = 0;

while (i <= num_line) {
	kfree(list[i]);
}

kfree(list);
Так правильно?

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

бесконечный цикл, i не изменяется. нет кода выделяющего память под массив - недостаточно данных для проверки правильности освобождения памяти.

anonymous
()
Ответ на: комментарий от anonymous

ой.. сори..
Забыл про i++ :)

нет кода выделяющего память под массив - недостаточно данных для проверки правильности освобождения памяти

В первом посту, есть код...
Здесь num_line это кол-во строк.. соответственно list[num_line] это последнее для чего выделялась память...

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

В первом посту, есть код...

простите, тогда есть ошибка. при выделении памяти написаны следующие проверки:

if (!list)
...
if (!list[num_line])
а в коде освобождения памяти их уже нет.

anonymous
()
Ответ на: комментарий от anonymous

Это проверка выделилась ли память.. Я их добавил...
но у меня ядро упсает... подозреваю что в момент kfree(list[0])

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

соответственно list[num_line] это последнее для чего выделялась память...

if(...) {
  list[num_line] = (char *)kmalloc(...);
  ...
}
num_line++;

не последнее, если я правильно понимаю, и вот эта штука:

while (i <= num_line)
проходит по несуществующему последнему элементу

но у меня ядро упсает...

а не в ядре экспериментировать нельзя?

anonymous
()

зачем эта строчка:

if ((int)ksize(list) >= num_line) 
, почему не такая:
if ( num_line < 100 )
и почему эта строчка выполняется в не зависимости от условия, а, следовательно, кода заполнения массива?
num_line++;

anonymous
()
Ответ на: комментарий от anonymous

проходит по несуществующему последнему элементу

Да! Вы правы!! не обратил внимания... :(
В общем разобрался... У меня в этой функции закралась ошибка... Повторное объявление массива list ....
И ещё как я понял освобождать память выделенную под строки нужно со взятием адреса.. Типа:

kfree(&list[i])

, почему не такая:

if ( num_line < 100 )

Я уже писал выше, почему...

и почему эта строчка выполняется в не зависимости от условия, а, следовательно, кода заполнения массива?

Потому как это не конечный вариант и там будут добавлены и запись и другие плюшки...

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

И ещё как я понял освобождать память выделенную под строки нужно со взятием адреса.. Типа:
kfree(&list)

нет

anonymous
()
Ответ на: комментарий от anonymous

а без взятия адреса у меня очередной Упс...
т.е. надо так:

While (i < num_line) {
	if (list[i]) {
		kfree(list[i]);
	}
kfree(list);
}

Правильно?

Inversiya
() автор топика
Ответ на: комментарий от Inversiya
if(list) {
  int i;
  for(i=0;i<num_line;i++)
    if(list[i])
      kfree(list[i]);
  kfree(list);
}
anonymous
()
Ответ на: комментарий от UVV

я тоже фигею, хз сколько лет на С программирую, а в ядро как-то стесняюсь лезть, а тут топикстартер прям на нём пытается С изучать

Harald ★★★★★
()
Ответ на: комментарий от Inversiya

И кто тебя научил перед освобождением проверять указатель на 0? Не доверяешь такие мелочи kfree?

anonymous
()
Ответ на: комментарий от anonymous

Ага.. Спасибо... Упсало оно у меня по другому поводу...
А запись строки как делать в данном случае?

Inversiya
() автор топика
Ответ на: комментарий от anonymous

И кто тебя научил перед освобождением проверять указатель на 0? Не доверяешь такие мелочи kfree?

Не то что-бы не доверяю... Скорее лишняя проверка что-бы всякие неприятности потом не получить...

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

Эта проверка ничего не дает. Но если страшно, то почему проверяешь только один раз? На всякий случай проверяй хотя бы два. ;)

anonymous
()
Ответ на: комментарий от Inversiya

Всё, разобрался... Всем спасибо...

я тоже фигею, хз сколько лет на С программирую, а в ядро как-то стесняюсь лезть, а тут топикстартер прям на нём пытается С изучать

Скорее вспомнить... :)

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

придурок, почитай хоть что-то про адресную арифметику

ananas ★★★★★
()
Ответ на: комментарий от UVV

Торвальдс ожидает его патчи.

Тут можно предположить, конечно, что ТС не знаком с юзерспейсом

panfutij
()
Ответ на: комментарий от dvl36

Вот какого... разводить тут бурление говн?
Нашли тут к чему цепляться...

Тут можно предположить, конечно, что ТС не знаком с юзерспейсом

Можно тоже предположить что товарищ panfutij, не знаком с кернелспейсом...
Если пишу в кернел, значит так надо... не дурней паровоза...

Я вас умоляю. )

Я вас тоже... У меня уже есть рабочий модуль ядра(написанный мной), который работает и выполняет свои ф-ции...

Да я сегодня чего то туплю...
Да у меня маловато опыта в Си и в кернел...

Но вот всё же вопрос, раз такие умные, знаете выражение «Дурак не поймёт, а Умный промолчит»?

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

Я уже писал выше, почему...

хорошо, но тогда 3 замечания:

  • знак равно лишний,
  • к num_line нужно добавлять 1 (проверять место под новый элемент),
  • num_line нужно умножать на sizeof(char*) (на размер элемента).
if ((int)ksize(list) > (num_line+1)*sizeof(char*))
anonymous
()
Ответ на: комментарий от Inversiya

знаете выражение «Дурак не поймёт, а Умный промолчит»?

А что ж ты тогда клованам отвечаешь? Этот самый тоже, чтоль?

Если пишу в кернел, значит так надо

Здесь у нас не советский союз.

anonymous
()
Ответ на: комментарий от anonymous

знак равно лишний

А, да... Вы правы...
Нумерация num_line с нуля же...

к num_line нужно добавлять 1

Тут не совсем понял зачем...
я же проверяю место под текущую строку.. следующей строки может не быть...

num_line нужно умножать на sizeof(char*) (на размер элемента)

Я результат ksize делю на sizeof(char*)) :)

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

И ещё есть у меня очень интересный вопрос...
Сейчас сетевые карты на аппаратном уровне умеют делать несколько потоков... Для того чтобы сетевой трафик можно было размазать по ядрам...
И собственно вопрос:
Как это будет выглядеть «внутри» ядра? я про буфер sk_buff
Мне нужно будет запустить столько копий ф-ций работающих с sk_buff, сколько ядер.. и как-то прилеплять их к ядрам... Или же в ядре этот поток будет один не зависимо от кол-ва ядер и потоков создаваемых сетевой картой??

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

я же проверяю место под текущую строку.. следующей строки может не быть...

давай с примерами, num_line = 0, что получится в этом случае? что сделает существующая проверка?

anonymous
()
Ответ на: комментарий от anonymous

давай с примерами, num_line = 0, что получится в этом случае? что сделает существующая проверка?

У меня проверка выглядит так:

if ((int)ksize(list) / sizeof(char *)) > num_line)
получатся
if( (800 / 8) > 0 ) //num_line = 0 (1 строка), 800 = 100 "строк"
Как то так...

Inversiya
() автор топика
Ответ на: комментарий от anonymous

kthread_create

Получается что на каждом ядре процессора будет своя очередь с одноимённым именем sk_buff
И мне нужно будет создавать отдельные потоки с ф-цией на каждое ядро...

Я правильно вас понял??

Inversiya
() автор топика
Ответ на: комментарий от Inversiya

я не знаю, просто направление указал

anonymous
()
Ответ на: комментарий от Inversiya

Нашли тут к чему цепляться...

Ну так совсем ведь детсад. Тут о Hello, World-е нужно бы подумать.

Я вас тоже... У меня уже есть рабочий модуль ядра(написанный мной), который работает и выполняет свои ф-ции...

Приведенный кусок кода и заданные вопросы позволяют усомниться. Ну... возможно функциональность модуля совсем небольшая.

Да я сегодня чего то туплю...

Возможно.

Да у меня маловато опыта в Си и в кернел...

Очевидно.

«Дурак не поймёт, а Умный промолчит»?

Значит мы где-то посередине, между дураком и умным, что, ИМХО, уже неплохо )

dvl36
()
Ответ на: комментарий от Inversiya

И всё же вопрос для меня остаётся открытым...
Буфер sk_buff единственный в ядре? или же их может быть несколько?(например по 1 на ядро проца)
Здесь я имею ввиду много процессорные/ядерные платформы...

Гугл с Яндексом по этому поводу молчат...

Если поразмышлять, то как мне кажется это (создание нескольких буферов в разных потоках) имеет смысл...

Но вот как это выглядит в ядре.... Остаётся для меня загадкой...

Товарищи подскажите пожалуйста или ткните туда где об этом подробно написано...

Inversiya
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.