LINUX.ORG.RU

отладка работы sys_read() -> file->f_op->read()


0

0

Есть модуль (тестовый)

....
static int hello_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data)
{
...
}

static int __init hello_init(void)
{
	/*
	 * Create an entry in /proc named "hello_world" that calls
	 * hello_read_proc() when the file is read.
	 */
	if (create_proc_read_entry("hello_world", 0, NULL, hello_read_proc, NULL) == 0) {
		printk(KERN_ERR
			"Unable to register \"Hello, world!\" proc file\n");
		return -ENOMEM;
	}
	return 0;
}

module_init(hello_init);
....
Суть его создать в /proc/ устройство hello_world из которого можно прочитать строчку «hello world». Нужно на примере этого модуля проследить работу ядра начиная от sys_read до непосредственно вызова функции read реализованной модулем для этого устройства (через file->f_op->read()).

Отлаживаю в связке qemu+gdb. Делаю так: в вирт машине набираю строчку cat /proc/helloworld (не нижамаю enter). Ставлю бряк на sys_read, и теперь из фирт машины нажимаю enter, но слишком много остановок и не могу толком понять как мне таким способом можно изучить работу ядра по вызову функции реализованных в модулях.

PS. нужно изучить именно механизм ядра отвечающий за вызовы модульных функций которые навешиваются через file_operations в качестве обработчиков для конкретных устройств.


> как мне таким способом можно изучить работу ядра

imho, так не надо изучать. text_editot + grep наше все ;)

проследить работу ядра начиная от sys_read до непосредственно

вызова функции read



не уверен, что понял вопрос. потому, что в данном случае
все тривиально: sys_read()->vfs_read()->f_op->read

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

С этого я как раз и начал, и думал что все понял... думал до первой тестовой отладки :) С виду все легко

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
	struct file *file;
	ssize_t ret = -EBADF;
	int fput_needed;

	file = fget_light(fd, &fput_needed);
	if (file) {
		loff_t pos = file_pos_read(file);
		ret = vfs_read(file, buf, count, &pos);
		file_pos_write(file, pos);
		fput_light(file, fput_needed);
	}

	return ret;
}
нашли что за файл file, вызвали унифицированную vfs_read
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
	....

	ret = rw_verify_area(READ, file, pos, count);
	if (ret >= 0) {
		count = ret;
		if (file->f_op->read)
			ret = file->f_op->read(file, buf, count, pos);
		else
			ret = do_sync_read(file, buf, count, pos);
проверили что метод read реализован для данного устройства вызвали file->f_op->read, по идеи вот тут мы должны уходить непосредственно на модальный обработчик read, на практике же я в модуль так не разу и не попал. Всегда уходит в глубинные дебри ядра, видимо для вкомпилиных в ядро модулей, ну там аля на ФС или клавы. Для этого и был создан модуль чтобы уж точно знать что есть она модульная read() и точно знать как ее вызвать, но таки и в такой тривиальной задачи столкнулся с выше описанной проблемой, куча раз стопится на sys_read и каждый раз через file->f_op->read уходит не в модульную функцию а в глубинные дебри ядра. Я не спорю, оно так и должно быть, но я не могу успокоиться пока глазами этого не увижу, а вдруг все не так просто как хотелось бы ?

PS. а цель этого эксперимента, попробовать по каким либо косвенным «уликам» попробовать до непосредственного вызова read знать какая именно выховеться, модульная или ядровая. Но об этом и речи быть не может пока не точечным методом из sys_read доходить до модульной функции минуя весь «мусор».

Изучать ядро как я уже на своем опяте понял нужно в комеплексе, по книжкам + по исходникам + в отладке. Иначе всегда что то упустишь не допоймешь.

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

>по идеи вот тут мы должны уходить непосредственно на модальный

обработчик read, на практике же я в модуль так не разу и не попал


Права не пробовал выставлять?

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

Напиши маленькую программу, которая открывает файл и читает из него.
Что напишет strace? Читаются ли в действительности символы?

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

какие права какие символы ? Модуль рабочий :) загружаеться отрабатывает и выгружается. Во время отладки в качеств еотладочной инвы покдлчаюю только ядро (потому что собсно его и отлаживаю). Была идея подлключить еще и модульную инфу чтобы например поставить бряк не на sys_read() а прям на модульной функции, и из нее сделать bt, но незнаю как в связке qemu+gbd еще и отладочную инфу модуля подключить.

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

эцсамое, я в ядерной физике конечно не уха не рыла, но почему не поставить break в hello_read_proc и сказать аналог gdb-шного bt?

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

>она то вызывается, я только этого узреть не могу, это и есть проблема

Что не можешь узреть? Если последовательность вызовов то вставь в нее распечатку стека.

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

> file->f_op->read, по идеи вот тут мы должны уходить

непосредственно на модальный обработчик read,


нет, не должно. create_proc_read_entry(hello_read_proc)
использует proc_file_operations, proc_file_read()
(который и есть f_op->read) вызовет
proc_dir_entry->read_proc == hello_read_proc переданный
как параметр.

на практике же я в модуль так не разу и не попал.


должно дойти и до модуля.

но, еще раз, путь от sys_read() до f_op->read() тривиальный.

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

>но, еще раз, путь от sys_read() до f_op->read() тривиальный.

да эт я не спорю. Забудем на время про этот конкретный модуль. Пусть есть некоторый модуль, для какогото устройтва (сетвуха, мыша и т.д.) этот модуль соответственно реализует функцию read для этого устройства. Тогда при обращении sys_read() к этому устройству на этапе

ret = file->f_op->read(file, buf, count, pos);

будет сразу вызвана функция обработчик из модуля или для любого модуля/устройства до непосредственно модульной функции будет вызваны еще какие нибудь интерфейсные функции ядра ?

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

наконецтаки нашел способ как решить проблемму, в виртуальной машине делаем

cat /sys/module/hellodev/sections/.text

получаем ядрес, потом в gdb делаем

add-symbol-file HelloDev/hellodev.o адрес

и усе, ставлю бряк на модульную функцию в тестовой машине читаю из нужного устройства и стопясю на нужной функции и делаю bt радуюся :)

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

Помогите решить еще один важный вопрос

Пусть есть некоторый модуль, для какогото устройтва (сетвуха, мыша и т.д.) этот модуль соответственно реализует функцию read для этого устройства. Тогда при обращении sys_read() к этому устройству на этапе

ret = file->f_op->read(file, buf, count, pos);

будет сразу вызвана функция обработчик из модуля или для любого модуля/устройства до непосредственно модульной функции будет вызваны еще какие нибудь интерфейсные функции ядра ?

Это либо нужно какой то достоверный материал прочитать опровергающий или подтверждающий это, или провести эксперимент на котором можно было бы однозначно увидеть что из file->f_op->read сразу вызывается модульная функция. Не то не другое на знаю как сделать :( подскажите идеи

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

«однозначно увидеть что из file->f_op->read сразу вызывается модульная функция»

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

> модуль соответственно реализует функцию read

...

при обращении sys_read() к этому устройству


...


удет сразу вызвана функция обработчик из модуля



я не понимаю вопроса. потому что дальше написано:

однозначно увидеть что из file->f_op->read сразу вызывается

модульная функция



какая функция? выше же было написано, что модуль реализует
функцию f_op->read ?

запутался.

достоверный материал прочитать

...


или провести эксперимент



да какой там материал/эксперимент ?

еще раз, см fs/read_write.c, там все тривиально.
sys_read(), vfs_read(), фсё!

rtfs, короче говоря.

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

еманарот, неужто я так неясно излагаю мысли ((

Для данного модуля, путь от sys_read() до функции модуля hello_read_proc() которую я регистрирую в качестве функции read() для создаваемого мной устройства /proc/hello_world Я УЖЕ УВИДЕЛ Вот бт из отладчика

(gdb) bt
#0 hello_read_proc (buffer=0xc75ca000 "Hello, world!\n", start=<value optimized out>, offset=0, size=3072, eof=0xc3c13f2c, data=0x0) at /home/cupper/linux-2.6.32.10/HelloDev/hellodev.c:30
#1 0xc02395f1 in __proc_file_read (file=<value optimized out>, buf=<value optimized out>, nbytes=32768, ppos=0xc3c13f98) at fs/proc/generic.c:119
#2 proc_file_read (file=<value optimized out>, buf=<value optimized out>, nbytes=32768, ppos=0xc3c13f98) at fs/proc/generic.c:200
#3 0xc02349a2 in proc_reg_read (file=0xc793bd00, buf=<value optimized out>, count=<value optimized out>, ppos=0xc3c13f98) at fs/proc/inode.c:185
#4 0xc01f3487 in vfs_read (file=0xc793bd00, buf=0x9885000 <Address 0x9885000 out of bounds>, count=<value optimized out>, pos=0xc3c13f98) at fs/read_write.c:292
#5 0xc01f3a8d in sys_read (fd=3, buf=0x9885000 <Address 0x9885000 out of bounds>, count=32768) at fs/read_write.c:381
#6 0xc01031c3 in ?? () at arch/x86/kernel/entry_32.S:449
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
читайте не через пост. Как видите тут после vfs_read() вызывается не сразу функция из модуля, а еще проходя несколько ядровых функций и только из __proc_file_read происходит вызов функции hello_read_proc.

еще раз, см fs/read_write.c, там все тривиально

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

Теперь нужно выяснить, возможна ли эта тривиальность (что из vfs_read сразу вызывается функция обработчик из модуля) для какого нидуть типа модулей/устройств ???

PS. щас то поняли о чем я ?

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

PS. щас то поняли о чем я ?

Ты щас общался с реально крутым пацаном, который сечёт в этой (ядерной) теме, и которого с ядерного раёна все знают и уважают. Если тебе что-то не понятно из сказанного им, то нужно не вскипать говном, а пытаться смиренно осознать его дельные предложения и ценные замечания. Если он сказал, что тривиально, значит, оно на самом деле тривиально. Учись читать и понимать код, дебаггером пошагово только лохи пользуются.

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

не знаю где я успел «вскипеть гавном», но после вашего поста я точно негодую.

возвращаемся опять назад.

еще раз, см fs/read_write.c, там все тривиально.

sys_read(), vfs_read(), фсё!

что значит «фсе» ? То что после vfs_read() мы уходим в функцию реализованную в модуле или я эти две строчки не правильно понимаю ?

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

что значит «фсе» ?

Это значит, что 27 строчек (из них 6 - пустые, либо с одной фигурной скобкой), составляющие тело функции vfs_read(), не понять может только тот, кто не хочет понять.

Если тебе вообще ничего не понятно, то по синтаксису языка читай букварь K&R, а по устройству ядра в целом и vfs в частности - какого-нибудь Р.Лава. Я так лично думаю, что ты просто Си не знаешь, раз в коде vfs_read() запутался.

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

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

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

Аналогично, только с другой стороны (глупые вопросы).

Смотрим vfs_read():

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
	ssize_t ret;

	if (!(file->f_mode & FMODE_READ))
		return -EBADF;
	if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
		return -EINVAL;
	if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
		return -EFAULT;

	ret = rw_verify_area(READ, file, pos, count);
	if (ret >= 0) {
		count = ret;
		if (file->f_op->read)
			ret = file->f_op->read(file, buf, count, pos);
		else
			ret = do_sync_read(file, buf, count, pos);
		if (ret > 0) {
			fsnotify_access(file->f_path.dentry);
			add_rchar(current, ret);
		}
		inc_syscr(current);
	}

	return ret;
}
Как видно, после проверки валидности file operations и буфера происходит вызов метода read из file operations.

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

> еманарот, неужто я так неясно излагаю мысли ((

чесна? по-моему - да ;)

Для данного модуля ... hello_read_proc()

Я УЖЕ УВИДЕЛ Вот бт из отладчика



в данном случае отладчик - это лишняя работа.
см http://www.linux.org.ru/jump-message.jsp?msgid=4979740&cid=4981122
я даже пытался обьяснить, почему будет такой trace.

Где оно тривиально ? Уже кучу раз написал что не так

там все тривиально



потому, что этот модуль НЕ реализует f_op->read, неужели
непонятно?

вы ведь спрашивали про случай, когда

есть некоторый модуль ... реализует функцию read


если это не f_op->read, тогда что? и в этом случае ответ
зависит от этого «что».

create_proc_read_entry() уже разобрали. но, в общем случае,
ответа просто не существует, неужели это тоже не понятно?

блин, ну если нет. вот у нас еще есть debugfs и sysfs, обе
fs позволяют создать файл и передать свой callback для
чтения. путь будет совершенно разным.

если же модуль делает register_chrdev(fops), то эти fops и
будут использоваться непосредственно, и путь будет тривиальным.

все. буду отвечать только на конкретные вопросы, которые сумею
понять (если время будет). пока что я все еще не понимаю.

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

спасибо :) вы как раз ответили на то что я спрашивал и именно то что нужно. Больше вопросов не имею.

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