LINUX.ORG.RU

не компилируется с _syscall

 ,


0

3

Добавил в ядро функцию, сделал обьявление в нескольких файлах.

#include <stdio.h>
#include <asm/unistd.h>
#include <linux/unistd.h>
#define __NR_getdevirq 548
_syscall1(char *,getdevirq, char *, irqdev)
int main()
{
        char *a = (char *)getdevirq("cpu");
        printf("%s\n",a);
}
В ответ
main.c:5:18: error: unknown type name ���getdevirq���
 _syscall1(char *,getdevirq, char *, irqdev)
                  ^
main.c:5:37: error: unknown type name ���irqdev���
 _syscall1(char *,getdevirq, char *, irqdev)
В System.map
c1066e40 T SyS_getdevirq
c1066e40 T sys_getdevirq

Похоже тебе нужно использовать функцию, описанную в man 2 syscall.

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

А что так не сработает? Да и вообще, вот я написал с изменениями системный вызов. Чтобы хотя бы вернула строку.

SYSCALL_DEFINE0(getdevirq)
{
        char *name = "hello_from_kernel";
        size_t len = strlen(name);
        char *result = kmalloc(len+1, GFP_USER);
        strncpy(result, name, len);
        return result;
}
Добавил в несколько файлов информацию о вызове.
arch/x86/include/generated/uapi/asm/unistd_32.h:#define __NR_getdevirq 548
arch/x86/include/generated/uapi/asm/unistd_x32.h:#define __NR_getdevirq (__X32_SYSCALL_BIT + 548)
arch/x86/include/generated/asm/syscalls_32.h:__SYSCALL_I386(548, getdevirq, )
include/linux/syscalls.h:asmlinkage long sys_getdevirq(void);
И строка не возвращается. Что же делать-то?

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

нет. Книга 2013 года о разработке ядра. Ядро Линукс. Описание процесса разработки.

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

Ты бы хоть про виртуальную память почитал, наверное. char * возвращает указатель, а не объект «строка» (в сишке объектов, как известно, нет). Теперь вопрос: куда он будет указывать после получения?

XMs ★★★★★
()
Последнее исправление: XMs (всего исправлений: 1)
Ответ на: комментарий от XMs

Ну так вот же создаётся для простанства пользователя.

        char *result = kmalloc(len+1, GFP_USER);
И должен вернуться указатель на начало result. Но у меня так не получилось( не получал указатель на строку в памяти).

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

А где это я упоминал про объекты? Ты вообще понимаешь что я написал? Если я указателю присваиваю адрес, то он указывает на строку.

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

GFP_USER выделяет *для* пространства пользователя, а не *в* пространстве пользователя.

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

И должен вернуться указатель на начало result

А теперь вопрос на засыпку: в контексте какого адресного пространства? Оно у каждого процесса своё, в том числе и у ядра, и один и тот же адрес у разных процессов будет указывать совершенно на разные участки памяти. Повторюсь, почитай про виртуальную память.


А где это я упоминал про объекты?

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

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

Обьясни тогда как правильно написать. Или хотябы ссылку на нормальное обьяснение дал бы. Но я и так знаю что такое [виртуальная] память. И как она работает.

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

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

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

Обьясни тогда как правильно написать

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


Или хотябы ссылку на нормальное обьяснение дал бы

STFW. В первых двух ссылках Яндекса есть вся информация для дальнейшего поиска по более специфичным вопросам. Только что проверил, четыре способа там точно есть, плюс один (хоть и извращённый и очень плохой) подсказали тут.


Но я и так знаю что такое [виртуальная] память

Плохо знаешь, иначе бы таких вопросов не задавал.


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

Если ты заглянешь в мой профиль, то обнаружишь, что на ЛОРе я зарегистрирован с 2010-го и пять лет писал только из-под анонимуса, а тем так и вовсе не создавал до сих пор. Если бы мне нужен был скор, он бы у меня уже был в любых количествах

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

хоть и извращённый и очень плохой

А что, с использованием указанной у ТС сигнатуры есть менее извращённые способы? Сходу не смог придумать, поэтому и влез в тему.

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

(если не считать, что первый char* аргумент — это место, куда нужно записать строчку)

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

Ну, можно создать символьное устройство и читать из него, можно создать файл в /sys/ и читать из него, можно использовать relayfs… И забить на текущую сигнатуру, конечно, в таком виде она не нужна никому, даже ТСу, в чём он когда-нибудь убедится

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

Тебе нужно сделать примерно следующее - выделить память для userspace скопировать туда нужные данные, замапить этот кусок памяти в адресное пространство пользовательского процесса и отдать указатель на область в адресном пространстве процесса.

Как эту память корректно освободить - я уже честно говоря не знаю, там могут быть нюансы.

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

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

Да что ты там знаешь? Способы? А писал ли ты хоть раз?
Попробуй.
Скачай линукс с сайта kernel.org.
Распакую операционную систему.
Посмотри что там есть, увидишь среди каталогов kernel, вот в kernel есть файл sys.c, где можно добавить свою системную функцию.
Если ты этого не делал, то чем ты мне можешь помочь писатель?

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

Я и выделять память пробывал и так делал

SYSCALL_DEFINE1(getdevirq, char __user *, message)
{
        char *name = "hello_from_kernel";
        size_t len = strlen(name);
        int a;
        a = copy_to_user(message,name,len);
        return len;
}
Ничего не возвращается.

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

Да, намекаю, делать свой syscall - очень плохая музыка.

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

Dark_SavanT ★★★★★
()
Последнее исправление: Dark_SavanT (всего исправлений: 1)
Ответ на: комментарий от Dark_SavanT
SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
{
        int error = 0;

        if (!name)
                return -EFAULT;

        down_read(&uts_sem);
        if (copy_to_user(name, utsname(), sizeof(*name)))
                error = -EFAULT;
        up_read(&uts_sem);

        if (!error && override_release(name->release, sizeof(name->release)))
                error = -EFAULT;
        if (!error && override_architecture(name))
                error = -EFAULT;
        return error;
}

Вот в этой функции всё работает, а у меня нет.

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

знаешь, там написано всё

Знаю, не поверишь. Глупо предполагать, что ты единственный читал Танненбаума.


да и ещё на английском языке

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


А писал ли ты хоть раз?

Не поверишь.


Скачай линукс с сайта kernel.org.
Распакую операционную систему

На kernel.org нет исходного кода операционной системы. Там только ядро, о чём красочно говорит его название.


чем ты мне можешь помочь писатель?

Я глубоко и искренне убеждён, что решать за тебя твои задачи за бесплатно — вопрос исключительно моей доброй воли. Обычно я подсказываю общее решение, и если вопрошающий включил мозг, попробовал (либо обосновал, почему оно не подходит) и предоставил код/лог, с которым у него проблемы, разбираюсь дальше. Выше по треду я объяснил тебе, как получить способы передачи данных из ядра процессу, а чуть ниже даже выписал некоторые из них, то есть выполнил первый пункт. Более того, ещё ниже тебе подсказали пошаговое решение, до которого ты, если бы разбирался в вопросе, допёр бы сам. И только если ты предоставишь код/напишешь пошаговый алгоритм, который у тебя не работает, посмотрю и может быть подкину рабочее решение (а может опять подкину общее)

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

попробую

sizeof(*name)
наверное это правильное решение.

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

Без контекста нихрена не понятно на самом деле. Что за define SYSCALL_DEFINE1, что за тип структуры name и т.д.

Ещё раз, если ты объявляешь свой syscall - ты делаешь что-то капитально не так.

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

Тебе нужно сделать примерно следующее - выделить память для userspace скопировать туда нужные данные, замапить этот кусок памяти в адресное пространство пользовательского процесса и отдать указатель на область в адресном пространстве процесса.

Шта? На каждый вызов отображение добавлять? На них вообще-то лимиты есть. И не могу вспомнить ни одного вызова, который бы так делал. Обычно память должен выделить user-space, а ядро в этот буфер будет писать.

i-rinat ★★★★★
()
Ответ на: комментарий от XMs

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

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

Эх,вот смотри.
SYSCALL_DEFINE[n], там где [n] можно поставить число, обозначающее сколько аргументов примет функция.
Правила именования SYSCALL в линуксе такие, SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) Первое uname, название функции.
struct old_utsname __user *, name, это
struct old_utsname __user * name
Ну __user как ты уже наверное догадался, предназначен для аргументов из пространства пользователя.

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

что-то аж в голосину. Я тебе про одно, ты мне совсем про другое.

ну и

struct old_utsname __user *, name, это struct old_utsname __user * name

ты как-то уж очень вольно интерпретируешь синтаксис дефайна. http://lxr.free-electrons.com/source/include/linux/syscalls.h?v=3.0#L234

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

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

Менеджер памяти находится отдельно от ядра, но всё равно всё это скомпилируется в одну большую программу.

facepalm.vmlinuz

i-rinat ★★★★★
()
Ответ на: комментарий от Dark_SavanT

как правильно вернуть из ядра в юзерспейс массив байт неизвестной заранее длины?

Думаю, стоит делать по аналогии с существующими функциями. Вот, скажем, getdents. Она принимает указатель на структуру, в которой указана длина этой структуры. Если места не хватает, чтобы вернуть имя, системный вызов возвращает EINVAL. Тогда user-space может выделить буфер большего размера и повторить вызов.

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

Вот собственно и сама функция

COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
                struct compat_linux_dirent __user *, dirent, unsigned int, count
)
{
        struct fd f;
        struct compat_linux_dirent __user * lastdirent;
        struct compat_getdents_callback buf = {
                .ctx.actor = compat_filldir,
                .current_dir = dirent,
                .count = count
        };
        int error;

        if (!access_ok(VERIFY_WRITE, dirent, count))
                return -EFAULT;

        f = fdget_pos(fd);
        if (!f.file)
                return -EBADF;

        error = iterate_dir(f.file, &buf.ctx);
        if (error >= 0)
                error = buf.error;
        lastdirent = buf.previous;
        if (lastdirent) {
                if (put_user(buf.ctx.pos, &lastdirent->d_off))
                        error = -EFAULT;
                else
                        error = count - buf.count;
        }
        fdput_pos(f);
        return error;
}
Здесь только создаётся пользовательский указатель на структуру, буду пробывать так.

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

Ядро находится в линуксе

б-жечки ты инопланетянин какой-то. Загугли понятие monolithic kernel. Так вот, ядро или нет выяснить очень просто: выполняется в адресном пространстве ядра, значит, ядро.

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

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

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

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

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

Да. А ты хочешь отделить ос от ядра. Ты ничего не забыл?
Вот например ты пишешь ядро. Что в него будет входить? И что будет входить в операционную систему?
Если ты действительно знаешь как это делать, то это лишь будет твоя реализация программы, тоесть как ты понимаешь так и сделаешь. А если ты знаешь только обрывки фраз, и говоришь мне о том, чего никогда не писал. Может если не лень то напишешь твоё соображение о том как ты знаешь.

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

Есть ОС Debian GNU/Linux, которая использует в качестве ядра наш любимый Linux. Но есть и ОС Debian GNU/kFreeBSD, в которой используется ядро от FreeBSD. Ещё есть ОС Debian GNU/Hurd с ядром Hurd. Можно сказать, что одну и ту же ОС Debian можно использовать с разными ядрами. Да даже если забыть об этих альтернативных ядрах, ведь при апдейте с 4.6 на 4.7 при следующей загрузке предоставляется возможность выбрать, с каким ядром (4.6 или 4.7) загрузить ОС.

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

Мне крайне непривычно вести подобного рода дискуссии на русском языке, извини. Действительно, ядро является частью операционной системы, но не все части операционной системы обязаны быть в пространстве ядра. Так вот, в случае с линуксом, всё, распространяемое в рамках одного проекта вместе с ядром, либо исполняемое в его адресном пространстве, даже если это бинарный блоб от производителя железяки (прошивки, драйвера), является ядром. А привязанные к этому ядру системные приложения, вокруг которых строятся приложения пользовательские, являются операционной системой. Вот тебя замечательный пример: убунту и андроид. И там и там линукс, однако это разные операционные системы.

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

Ладно, у меня своё представление об операционной системе. Но для удобства copy-paste, приведу несколько цитат не из книги а из страниц. Все эти ubuntu,slackware,archlinux это все волишь распространители.
Операционная система

Операцио́нная систе́ма, сокр. ОС (англ. operating system, OS) — комплекс взаимосвязанных программ, предназначенных для управления ресурсами компьютера и организации взаимодействия с пользователем.

В логической структуре типичной вычислительной системы операционная система занимает положение между устройствами с их микроархитектурой, машинным языком и, возможно, собственными (встроенными) микропрограммами (драйверами) — с одной стороны — и прикладными программами с другой.

Разработчикам программного обеспечения операционная система позволяет абстрагироваться от деталей реализации и функционирования устройств, предоставляя минимально необходимый набор функций (см.: интерфейс программирования приложений).

В большинстве вычислительных систем операционная система является основной, наиболее важной (а иногда и единственной) частью системного программного обеспечения. С 1990-х годов наиболее распространёнными операционными системами являются системы семейства Windows, UNIX и UNIX-подобные системы.

Диструбутив операционной системы

Дистрибути́в операцио́нной систе́мы — это форма распространения системного программного обеспечения. Наличие дистрибутивов вызвано тем, что форма программного обеспечения, используемая для его распространения, почти никогда не совпадает с формой программного обеспечения работающей системы, за исключением использования Live CD.

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

Программа установки позволяет также произвести первичную настройку системы.

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

и организации взаимодействия с пользователем

А ядро, как известно, с пользователем не взаимодействует никак

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

Так операционная система всем управляет.
Ядро это всего лишь каталог в линуксе, где находятся файлы с типичным функционалом.
Так там ещё есть менеджер памяти.
А менеджер всё что связан с памятью, и адресацию к тому же.
Есть каталог файловых систем.
И ещё много чего.
Всё это вместе и называется операционной системой.
Она управляет всем.
Ядро это часть функционала, операционной системы и не больше.
Ты конечно можешь вот так представить, что есть диструбутив, на основе чего? На основе линукс. Ты можешь видеть пользовательские программы и считать что главное в системе файл с названием ядро.
Что типа так выглядит.
пользователь<->операционная система<->ядро.
А можно так.
пользователь<---------------|
операционная система<-|
----------------------------------------
[управление устройствами]
[управление памятью]
[управление процессами]
[управлению сетью]
[управление файловой системой]
[обработка команд пользователя]

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

Ядро это всего лишь каталог в линуксе

Linux — это и есть ядро. Тебе выше даже расписали пример с убунтой и ведроидом (аплодисменты и чай за счёт заведения тому анону). Да, некоторые называют линуксом всю ОС, но это некорректно. О причинах, почему это так, написано на сайте проекта GNU, к слову

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

Тебе сколько не обьясняй ты никак не поймешь.
Ладно давай посмотрим как ты на это ответишь.
Сначала приведу аналогию.
Птица - это летающее животное.
летающее животное - это животное с крыльями.
Пока всё ясно?
Теперь вот.
Линукс - это операционная система.
операционная система - это управление компьютером.
Ну а вот ты продолжи.
Линукс - это ядро.
ядро - это [ вот здесь продолжи ]

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