LINUX.ORG.RU

Lunatik v3.6 — релиз среды исполнения Lua в пространстве ядра Linux

 , , , ,

Lunatik v3.6 — релиз среды исполнения Lua в пространстве ядра Linux

0

4

Lunatik — это фреймворк для написания сценариев для ядра Linux на Lua. Разрабатывается LabLua в рамках Lua in kernel с явными ссылками на опыт использования Lua в ядре NetBSD.

Основные компоненты

  • интерпретатор Lua, модифицированный для работы в ядре;
  • драйвера устройства (написаны на Lua);
  • средства командной строки для запуска сценариев и управления средами выполнения из пользовательского пространства;
  • C API для загрузки и запуска сценариев и управления средами выполнения из ядра;
  • Lua API для привязки средств ядра к Lua-скриптам.

Новые возможности


Группа разработчиков Lunatik выражает благодарность контрибуторам, благодаря которым стал возможен этот релиз: sav и marcelstanley из Ring-0 Networks, sheharyaar, jperon, vincentmli, rustedusted, glk0, ну и конечно же всем другим участникам, работающими над Lunatik.

Пример драйвера устройства для генерации простых «паролей»

-- /lib/modules/lua/passwd.lua
--
-- implements /dev/passwd for generate passwords
-- usage: $ sudo lunatik run passwd
--        $ head -c <width> /dev/passwd

local device = require("device")
local linux  = require("linux")

local function nop() end -- do nothing

local s = linux.stat
local driver = {name = "passwd", open = nop, release = nop, mode = s.IRUGO}

function driver:read() -- read(2) callback
	-- generate random ASCII printable characters
	return string.char(linux.random(32, 126))
end

-- creates a new character device
device.new(driver)

>>> Исходный код релиза

>>> Документация, исходный код и примеры проекта

>>> Сопутствующие проекты

>>> Анонс в официальной группе Lua

★★★★★

Проверено: CrX ()
Последнее исправление: hobbit (всего исправлений: 9)
Ответ на: комментарий от LightDiver

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

Для тебя эта новость в ядре примерно аналогична тому, что в игровой сервер завезли Lua для своих внутренних нужд. Но тебе от этого ни горячо, ни холодно. Разве что, на весь твой юнит вдруг кто-то скастовал заклинание «жираф». И до всего юнита информация от сервера начинает доходить так же, как до жирафа. С задержками :)

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

Ну если ты такие вопросы задаешь...

Да Си не лучше и не хуже. Интерпретатор Lua тоже на Си написан. В двух словах на эту тему не напишешь. Тут ликбез нужен на тему «компиляторы vs интерпретаторы» и про то, как интерпретаторы писать.

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

Вся проблема только в компиляции? Серьезно?! Мне сейчас чтобы проверить код, приходится перезагружать весь интерфейс. По сути выходить из игры и входить заново, а им сложно скомпилировать?!

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

Да, я перевожу, но работать же всеравно надо с этим…. СТОП! Ты гений. Я же могу транслитерировать и работать с однобайтным текстом. А когда надо, переодить обратно!!! У меня же была мысль переводит в транслит на хранение, почему я развил ее?

Спасибо огромное, пойду попробую.

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

Ну, тем для кого это запилили. Кому нужна интерпретация, а не компиляция. Что то же это упрощает. Как я понимаю, как минимум компиляцию не нужно делать. Но это же такие мелочи, которые даже учитывать не стоит.

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

Усложняет, на самом деле. И сильно.

Мы теряем контекст. Твоя проблема состоит в том, что есть некая среда исполнения скриптов на Lua, которая при некоторых условиях работает медленно. Ты говоришь, а давайте мы будем писать не на Lua, а на Си и вгружать компилированные куски. Давайте. А какими функциями будут пользоваться скомпилированные куски? Тебе нужны биндинги исполняющей системы в Си, средства загрузки скомпилированных библиотек (dll, so, whatever), средства вызова функций из этих библиотек... Кстати, а кто твою dll-ку позовет? Попробуй ответить для себя на эти вопросы и построить архитектуру всего вот этого в голове.

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

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

Я НЕ программист. Я сбоку примазался два года назад с нуля. И пишу для себя только на си, питоне и в 99% на луа. В основном. Иногда баш.

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

tcc, например, тоже можно запихать в ядро и использовать как «интерпретатор» С и экспериментировать без перекомпиляции всего. И он даже будет не больше чем lua, и гораздо быстрее, даже при отсутсвии каких-либо оптимизаций. Им, кстати, когда-то можно было вообще ядро целиком собрать https://bellard.org/tcc/tccboot.html (привет, RfL)

Но вот в песочницу его, в отличии от lua, посадить не получится. И что тут лучше, возможность быстро уронить вообще всё или «медленный», но безопасный lua ещё вопрос

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

Бро, интересно стало. Смотри, развоплощение строки в таблицу дает буст x2, а узкое место я комментами пометил. Очень странное поведение, но что есть, то есть:

function mylen(s,n)
    local count = 0
    for a = 1, n do
        local i = 1
        count = 0
        while s[i] do
---            if s[i] < 128 or s[i] >= 192 then
                count = count + 1
---            end
            i = i + 1
        end
    end
    return count
end

function mylen2(s,n)
    local count = 0
    local len = #s
    for a = 1, n do
        count = 0
        for i = 1, len do
            byte = s:byte(i)
            if byte < 128 or byte >= 192 then
                count = count + 1
            end
        end
    end
    return count
end


local time = os.clock()
local bytes = { string.byte("Привет мир!", 1, -1) }
print(mylen(bytes, 100000))
print("Прошло: " .. os.clock()-time)

time = os.clock()
print(mylen2("Привет мир!", 100000))
print("Прошло: " .. os.clock()-time)
20
Прошло: 0.036844
11
Прошло: 0.168108
Anoxemian ★★★★★
()
Последнее исправление: Anoxemian (всего исправлений: 1)

Панеслась по кочкам. Жду Visual Basic.

dimgel ★★★★★
()
Ответ на: комментарий от Anoxemian
[09:03]Прошло: 0.00099999969825149
[09:04]Прошло: 1.0639999997802
[09:07]Прошло: 2.7550000003539
[09:09]Прошло: 2.4739999999292
  1. Штатный #

  2. Моя регулярка

  3. Первая твоя функция

  4. Вторая твоя функция.

Я тут задумался над концепцией транслита. Перевести все в однобайтовую кодировку и с этим работать. Только понять как сделать это оптимальнее. Мне ведь не надо тут и сразу все декодировать обратно - можно точечно. А работать с таким текстом станет гораздо проще и быстрее.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)

Пример драйвера устройства для генерации простых «паролей»

Зочем это в ядре?

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

Прототипы на живом ядре никто не отлаживает.

кроме этих ребят https://www.netbsd.org/~lneto/bsdconbr15.pdf

кстати советую всем кто первый раз слышит о Lunatik (первое упоминание 2008 год!) посмотреть ссылку, часть вопросов в треде отпадут сами собой

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

Ты чет, не то намерял. В приведенном мной коде (с комментами) разница вообще x4. Т.е. быстрее даже чем с регулярками. Скинь тестовую строку.

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

Я примерно понял боль которую вы испытываете с lua, и могу сказать, что парсить логи, utf-8 строчки и хранить в lua - это не очень правильное использование lua как скритового языка самого по себе.

Самая большая проблема в которой вы оказались, это видимо поприетарщина которая завязана на обрезанной с lua5.1

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

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

Давайте объективно рассмотрим, что мы имеем в экосистеме Rust:

  1. Реально пассионарные фанбои
  2. Жесткое нарушение принципа KISS везде, где можно и где нельзя (следствие п.1)
  3. Каждая первая библиотека тащит proc-macro2 и свой собственный DSL (следствие наличия Lisp-подобной макросистемы помноженное на п.1.)

Как Вы думаете, Вы бы действительно хотели видеть Rust в ядре Linux будь бы Вы Линусом Торвальдсом?

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

Я понял. Поэтому и говорю, что не в языке дело. Ты почитай, чем компиляторы от интерпретаторов отличаются, раз уж тебя сюда занесло. А то долго объяснять получится.

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

Первого пункта достаточно. :) Хацкель — это не религия, а тут сплошные евангелисты :)

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

У меня нет вопросов. Статью по ссылке из новости я первым делом по диагонали прочел. Ну можно, наверное, поведение пакетного фильтра прототипировать, а потом переписывать на том же Си, чего нет... Как я понимаю, эта цель не основная. Хотя, для OpenWRT может и хорошо, пересобираться меньше.

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

Я тут задумался над концепцией транслита. Перевести все в однобайтовую кодировку и с этим работать.

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

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

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

function mylen(s, n)
    local count = 0
    for a = 1, n do
        local i = 1
        count = 0
        while i <= #s do
            local byte = s:byte(i)
            if byte < 128 or byte >= 192 then
                count = count + 1
            end
            i = i + 1
        end
    end
    return count
end

function mylen2(s,n)
    local count = 0
    local len = #s
    for a = 1, n do
        count = 0
        for i = 1, len do
            byte = s:byte(i)
            if byte < 128 or byte >= 192 then
                count = count + 1
            end
        end
    end
    return count
end


function test222(n1, n2)
    local temp
    local time1 = GetTime()
    -- for i = 1, n1 do
    --     temp = #ns_chat_log_line_q_p["лог_чат"][10]
    --     --print(temp)
    -- end
    -- print("Прошло: " .. GetTime()-time1)
    mylen(ns_chat_log_line_q_p["лог_чат"][10], 100000)
    print("Прошло: " .. GetTime()-time1)
    time1 = GetTime()
    mylen(ns_chat_log_line_q_p["лог_чат"][10], 100000)
    print("Прошло: " .. GetTime()-time1)
end

То результат:

[29:02]Прошло: 28.206999999937
[29:30]Прошло: 27.356999999844

Если же взять общую идею, то это обычная работа в цикле и там будет при 10 тысячах проходов от 2,5 до 2,7с в среднем.

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

Да, все это пытаются советовать, но оттуда нет доступа в реал. Все это работается в озу в рамках сессии и на диск сохраняется при выходе из игры. Загружается тоже один раз - при входе.

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

Или же переводить в транслит и тут уже скорость перевода печальная.

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

Я понимаю разницу работы. Но скомпилировать это дело секунды. Или я еще что то упускаю?

Стоп.. Или компилировать придется все ядро?

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

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

ns_chat_log_line_q = {
	["лог_чат"] = {
		"Фраза нулеваяФразе перваяФраза вторая",
                "Фраза третьяФраза четвертая"
                }
       }
ns_chat_log_line_q_p = {
	["лог_чат"] = {
		" 13 25 37",
                " 12 27
                }
        }

Вот примерно такой формат.

Первая таблица - данные, вторая - их адреса. Чтобы по адресу вытянуть фразу, мне сейчас приходится работать с кириллицей. Если перевест в однобайтную кодирвку, можнобудет воспользоваться штатными средствами, что ускорит работы на порядки…в теории.

LightDiver ★★★★★
()
Ответ на: комментарий от Minoru
  1. Пассионарные они только на фоне замшелых необучаемых сишных сектантов
  2. Это с плюсцами попутал
  3. Далеко не каждая и не так что-бы проблема

будь бы Вы Линусом Торвальдсом

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

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

Перед этим надо перевести строку в таблицу и все заработает (у меня посмотри перед вызовом все есть). Если не влезает в память - частями. Буст-то есть и неплохой.

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

Interface\AddOns\NSQS\server_functions.lua:297: stack overflow (string slice too long)

Этим нельзя работать с очень длинными строками. На коротких строках разница со штатным:

[17:30]Прошло: 0.00099999969825149
[17:31]Прошло: 0.30799999972805

Мне надо пересматривать подход и думать.

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

Еще прикол, если использовать luajit, то результаты ровно наоборот, только тут x10 оборотов:

78
Прошло: 2.231419
78
Прошло: 3.823456
78
Прошло: 0.180124
78
Прошло: 0.087083
Anoxemian ★★★★★
()
Ответ на: комментарий от LightDiver

Ну так порежь строки, не обязательно же целиком пихать.

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

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

Создаем 10-20 таблиц разных, указываем огранчиение 200 тысяч строк. И следим за переполнением. Переполнилась одна - используем следущую. Максимальная скорость работы. 1мб озу на 10 тысяч сообщений где то.

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

@LightDiver Anoxemian

Попробуйте создать тред в Development или в Games с описанием задачи, что у вас есть и что вы хотите получить.

«Писать кодец» в новостном треде это такое себе занятие.

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

Так, я тут дальше покопался. #s - это не функция. Это свойство типа string, которое сохраняется при присвоении/инициализации. Плюс тотальное кеширование в самом интерпретаторе. Цикл присвоения значения + изменение переменной занимает больше, чем один пробег цикла по таблице. Вобщем в бенче у тебя косяк с твоим #s. Так что ускориться только сменой версии lua выйдет. Я так и понял, что неправдоподобный бенч, так не бывает просто)

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

Да ну, просто интересно стало. Как так в несколько порядков разница на ровном месте, никакого кода.

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

Ты задачу полностью опиши. Пока мы поняли, что у тебя есть какая-то ограниченная песочница с базой данных в памяти, умеющая запускать скрипты на Lua. Что ты компилить в этих условиях собрался? Заменить Lua на С? Ну хорошо, заменил. Получил песочницу, которая умеет грузить кучу внешних библиотек и имеет какой-то программный интерфейс, позволяющий дергать API этой песочницы. Гибкость ты потерял, потому как скрипты на лету перегружать можно. С разделяемыми библиотеками не всегда получается их на лету перегружать. В скорости может и выиграл, а может и нет, как писать будешь. А вот геморрой нажил точно. И в гибкости проиграл.

Вот в твоем случае иметь расширяемый интерпретатор Lua, который может дергать функции из загружаемых dll, so, whatever было бы полезно.

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

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

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

Осталось такой раритет еще где-то откопать, что бы было на чем отлаживаться :)

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

Каким байткодам?

Думается, он хотел сказать «по codepint'ам».

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

Просто скорость луа это вообще не скорость си

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

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

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

Выше вон объяснили, что это нормально и найдет свое применение. Я не очень понял суть, но звучало убедительно.

А скорость в луа это просто моя больная тема, вот и не удержался.

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

Вся проблема только в компиляции?

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

а им сложно скомпилировать?!

Кому им?

sena ★★
()
Последнее исправление: sena (всего исправлений: 1)

Не, братцы, это какая-то шляпа. Вот, читаем статью по ссылке:

4.3 User Interface
The User Interface (UI) has two parts: one running in user space
and the other inside the kernel. The user-level component consists
of a command-line tool and a pseudo-device descriptor file. The
kernel component is the corresponding pseudo-device driver. The
user-level tool resembles a Lua stand-alone interpreter, but instead
of executing Lua scripts in user space, it executes them in the
kernel-embedded Lua interpreter.
The user-level command interface is actually a front-end for
the pseudo-device driver. When a user issues a command, the UI
user-level component forwards it, by invoking an ioctl system call,
to a handler function registered by the pseudo-device driver. This
handler function, running inside the kernel, provides the actual
commands for handling kernel Lua states and for loading and
running scripts inside these states.

То есть, это Вам не BPF. Скрипт существует в юзерспейсе и построчно грузиться в ядро, где и исполняется. Ну ладно, будем думать, что они на лексическом анализе с'экономили.

В общем, оно интересно, конечно, но применимость всего этого ограничена.

Да уж, это как-то не Lunatik, это Lunatic Asylum :)

gns ★★★★★
()
Последнее исправление: gns (всего исправлений: 1)
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.