LINUX.ORG.RU

Продемонстрирована возможность разработки частей Linux на Rust

 , ,


4

9

Французский программист написал статью, в которой рассмотрел возможность переписывания ядра Linux на Rust.

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

В качестве «Proof of Concept» была приведена реализация системного вызова, содержащая вставки на Assembler внутри unsafe-блоков. Код компилируется в объектный файл, не связанный с библиотеками и интегрируемый в ядро во время сборки. Работа производилась на основе исходного кода Linux 4.8.17.

>>> Статья



Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 5)
Ответ на: комментарий от www_linux_org_ru

да, сам (хотя тебе бы следовало иметь в виду более широкую перспективу); но так почему это маразм?

Что и следовало доказать.

ты школьник что ли, чтобы на словарик ссылаться?

Да нет, мы уже определил, что я грудничёк, который явно разумнее некоторых индивидуумов.

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

Правильно, это не ты ошибаешься, а словарь... Маразм крепчал...

если тебе это не ясно — вот пример: производный класс является уточнением класса-предка, и это уточнение может достигаться с помощью method overriding в производном классе, т.е. фактически с помощью «опровержения» поведения этого метода на более узком круге объектов

Пытаешься втянуть меня в пучину своего безумия? Это называется специализацией. Метод должен соответствовать сигнатуре (обещанию), то есть он не может что-либо опровергать.

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

Если такие задачи не превышают по сложности «hello, world», то на их основе нельзя делать выводы о преимуществах конкретного языка над альтернативами.

в общем да, но некоторые языки ужасны даже на уровне «hello, world» — если что, я про perl в стиле «набор из 10-20 отдельных утилиток до 50 строк каждая с исключительно простыми структурами данных»;

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

Да нет, мы уже определил, что я грудничёк, который явно разумнее некоторых индивидуумов.

нет

Метод должен соответствовать сигнатуре (обещанию), то есть он не может что-либо опровергать.

ты хоть видишь, что «он не может что-либо опровергать» не следует из «Метод должен соответствовать сигнатуре (обещанию)» ?

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

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

да, сам (хотя тебе бы следовало иметь в виду более широкую перспективу); но так почему это маразм?

Что и следовало доказать.

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

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

привнесение более широкой перспективы в дискуссию

Так вот как ты называешь опровержение своих же вымыслов.

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

Раст гарантировал Феде что это точно не его косяк. И опираясь на эту гарантию, Федя знает кому пойдет бить морду.

хорошо... а что делать, если в проекте несколько библиотек с unsafe? как определить, идти бить морду надо кому?

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

unsafe-ов то много, и путь, кмк, тот же, что и с++... да, кстати, как там valgrind в расте?

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

привнесение более широкой перспективы в дискуссию

Так вот как ты называешь опровержение своих же вымыслов.

ты совсем с голосами в своей голове стал говорить

давай-ка приводи код на с++ с *разумным* поведением метода производного класса, при котором он настолько «опровергает», что нарушает даже LSP

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

з.ы. хотя может это тяжеловатая задача для тебя, сойдет и просто хороший пример method overriding-а

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

В левом углу ринга те кто знаком с rust

А расскажите про свое знакомство с Rust-ом? Вы коммерческие проекты на нем делаете? Или OpenSource? Или hello_world-ы для себя?

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

давай-ка приводи код на с++ разумным поведением метода производного класса, при котором он нарушает даже LSP

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

numas13

Метод должен соответствовать сигнатуре (обещанию), то есть он не может что-либо опровергать.

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

есть и валгринд и калгринд, и санитайзеры есть, все как у людей.

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

А разве в Rust-е это есть?

Нет. Опять же, я об этом не говорил, не скатывайся до его ( www_linux_org_ru) уровня. Вся дискуссия из-за его неправильного трактования слов уточнять и опровергать. «мой автомобиль едет по земле» и «не все автомобили ездят по земле» является уточнением для него, а не опровержением не относящемся к обсуждению.

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

Я не очень следил за вашим спором, но вот эта фраза:

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

Как по мне, 1-в-1 соответствует тому, что мы имеем сейчас в Rust-е. Т.е. если есть какой-то трейт Foo и в нем метод bar, то никто не может доказать, что я для своей структуры S реализую Foo.bar именно так, как это было задумано авторами Foo.

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

Раст гарантировал Феде что это точно не его косяк. И опираясь на эту гарантию, Федя знает кому пойдет бить морду.

есть и более интересные случаи: условный unsafe

дело в том, что иногда что-то safe, но только при определенных условиях

например, ЕСЛИ известно, что массивы х и у имеют одинаковую длину, и массив у порезан на две части у1 и у2, ТО тогда можно безопасно in-place порезать х на две часть х1 и х2, длины которых равны длинам у1 и у2

как оформить в виде функции

unsafe порезать_х_на_два_массива_длиной_как_y1_и_у2(x, y1, y2) { .... } ???

варианты:

1. эта функция не проверяет в рантайме «длина(х) == длина(у1) + длина(у2)»; тогда, вообще говоря, использующий ее safe-раст-код будет опасным, т.е. определять такую функцию нельзя (конечно, правильно написанный использующий ее код будет безопасным, но чем это лучше си?)

2. эта функция проверяет в рантайме «длина(х) == длина(у1) + длина(у2)», и если не так, то выбрасывает исключение; тогда, если компилятор не допрет, что эту проверку в рантайме можно optimize out (а это вероятно), то будут тормоза и дополнительное исключение в сигнатуре функции, которое на самом деле при правильном вызове этой функции никогда не реализуется

оба варианта плохи

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

Лавировали лавировали да не вылавировали.

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

Как по мне, 1-в-1 соответствует тому, что мы имеем сейчас в Rust-е. Т.е. если есть какой-то трейт Foo и в нем метод bar, то никто не может доказать, что я для своей структуры S реализую Foo.bar именно так, как это было задумано авторами Foo.

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

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

Если твоя реализация метода не соответствует ожидаемому поведению, то могу только посочувствовать твои коллегам.

давай че-нить попроще: приведи пример, когда для реализации ожидаемого поведения метод потомка нужно override-ить

можно на яве и шарпе, не обязательно плюсы

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

оба варианта плохи

Как страшно жить.

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

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

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

«мой автомобиль едет по земле» и «не все автомобили ездят по земле» является уточнением для него, а не опровержением не относящемся к обсуждению

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

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

ты мне не политинформацию читай, а напиши простейший растовский код под эту задачу, и объясни, где ставить unsafe, а где нет, и почему

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

нет чувак, ты ни-хре-на не понял

я веду речь о том, что для специализации иногда нужен именно overriding, а просто отнаследовать метод предка недостаточно

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

жаль, не успел исправить на «их РЖАВОЕ ведро с болтами»

Я и без этого уже понял, что ты отправился на МКС.

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

варианты:

Если исходить из того, что Rust позиционируется как безопасный нативный язык, то я бы лично выбирал бы Rust именно из-за соображений безопасности. А значит меня бы вполне устроили проверки в run-time, поскольку за безопасность нужно платить. Т.е. я бы выбрал вариант 2.

Другое дело, что для этой микрозадачки в Rust-е меня смущает то, что здесь непонятно, что предпочесть: возврат Result-а или иницирование паники.

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

как должен вести себя malloc(0)? Как затем должен вести себя free? Ну и в чем здесь логика?

Дык, это опять «логика сишника». Я её, в общем-то понимаю, но почему новые языки должны быть к этому привязаны?

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

Если «длина(х) == длина(у1) + длина(у2)» - инвариант алгоритма, в котором эта функция используется, не выставлять эту функцию во внешний интерфейс и паниковать при нарушении инварианта. Если данные приходят откуда-то снаружи - возвращать Result.

Если такая функция торчит из библиотеки, то выставлять оба варианта с соответствующими комментариями. Что тут такого уж нетривиального?

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

Дык, это опять «логика сишника».

Дык, если Rust претендует на нишу C, то должна же быть какая-то понятная мотивация для C-шника. Мол, вот в С у вас были такие-то бенефиты, но вы платили за них такую-то цену. А сейчас вам предоставляется возможность получить дополнительно еще и вот такие бенефиты, но гораздо дешевле.

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

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

Если «длина(х) == длина(у1) + длина(у2)» - инвариант алгоритма, в котором эта функция используется, не выставлять эту функцию во внешний интерфейс и паниковать при нарушении инварианта.

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

Если такая функция торчит из библиотеки, то выставлять оба варианта с соответствующими комментариями. Что тут такого уж нетривиального?

Увеличение количества работы.

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

А значит меня бы вполне устроили проверки в run-time, поскольку за безопасность нужно платить.

пойнт в том, что за безопасность надо платить слишком много

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

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

возврат Result-а или иницирование паники.

Я считаю, что panic! — используют чтобы убрать шум от ошибок, после которых в большинстве случаев невозможно продолжить исполнение или это не имеет смысла. Для всех остальных случаев используют Option/Result, в зависимости от необходимости оповещения о типе ошибки.

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

вот код на с++; как inplace_split_x_by_length_of_y1_and_y2 написать на расте, не теряя скорости, но приобретя безопасность?

#include <iostream>

struct String
{
  char* start;
  int length;
  String(char* start, int length): start(  start), length(  length) {}
  String(const String& s):         start(s.start), length(s.length) {}
};

std::ostream& operator << ( std::ostream& out, const String& s )
{
  for( int i=0; i<s.length; ++i )
  {
    out << s.start[i];
  }
  return out;
}

std::pair<String,String> inplace_split_x_by_length_of_y1_and_y2( String x, String y1, String y2 )
{
  return std::make_pair( String(x.start,y1.length), String(x.start+y1.length,y2.length) );
}

const int k=2;
const int l=3;

char u[k+l] = {'1','2','3','4','5'};
char v[k+l] = {'a','b','c','d','e'};

int main()
{
  String x (u,  k+l);
  String y1(v  ,k);
  String y2(v+k,l);
  std::pair<String,String> x1x2 = inplace_split_x_by_length_of_y1_and_y2( x, y1, y2 );
  String x1 = x1x2.first;
  String x2 = x1x2.second;

  std::cout << x1 << "\n";
  std::cout << x2 << "\n";
  std::cout << y1 << "\n";
  std::cout << y2 << "\n";
  return 0;
}

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

Если «длина(х) == длина(у1) + длина(у2)» - инвариант алгоритма, в котором эта функция используется,

да

не выставлять эту функцию во внешний интерфейс и паниковать при нарушении инварианта.

это как «не выставлять»? допустим, у нас несколько алгоритмов, которым нужна эта функций, причем их могут добавлять совершенно посторонние люди (которые в курсе про инвариант из доков)

и паниковать при нарушении инварианта.

для паники (или ее отсутствия) придется считать каждый раз длину; а если подсчитать длину долго (например, нужно пройти по всему массиву), а вот найти точку где длина(х1) == длина(у1) можно быстро (например бинарным поиском — такова специфика задачи) ?

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

Если такая функция торчит из библиотеки, то выставлять оба варианта с соответствующими комментариями. Что тут такого уж нетривиального?

выставлять первый вариант нельзя, т.к. это нарушает хоть слабенькую, но гарантию «если что-то в программе пошло не так, то виноват именно unsafe код» — в первом варианте виноват может быть тот, кто этот unsafe код *вызвал*, либо даже вообще юзер, задавший необычные данные — и это при том, что unsafe-код написан 100% верно

отсюда видно, что даже сами растаманы принимают разговоры о «гарантиях» за чистую монету...

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

Элементарно:

fn split<'a>(x: &'a str, y1: &str, y2: &str) -> (&'a str, &'a str) {
    (&x[..y1.len()], &x[y1.len()..y1.len() + y2.len()])
}

fn main() {
    let x = "12345";
    let y1 = "ab";
    let y2 = "cde";
    
    let (x1, x2) = split(x, y1, y2);

    println!("{} {}", x1, x2);
}

И в три раза короче.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon
fn split<'a>(x: &'a str, y1: &str, y2: &str) -> (&'a str, &'a str) {
    (&x[..y1.len()], &x[y1.len()..y1.len() + y2.len()])
}

А вот и нет. Ты наверно забыл, что str это UTF-8? Вот вариант со срезами, если проверки можно опустить во время компиляции, то большой разница не будет.

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

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

Смысл перехватывать, если было нарушение инварианта? Ассерты тоже перехватывать прикажете? Грохать нить, писать в лог, звонить разработчику.

Увеличение количества работы.

Дык. Как обычно. Наносекунды сами по себе не срежутся.

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

Смысл перехватывать, если было нарушение инварианта?

Предположим, что Федя Иванов написал библиотеку, с кучей полезных для пользователя функций. Внутри этой библиотеки активно используется inplace_split_x_by_length_of_y1_and_y2. Но публичные функции библиотеки выставляют наружу Result.

Пользователю Фединой библиотеки без разницы, что там у Феди поломалось и какие инварианты в своем коде Федя не соблюл. Но если уж Федя возвращает Result, то с какого перепугу пользователь должен думать о паниках из-за нарушения инвариантов внутри Фединого кода. Ладно, когда паники из-за OOM возникают. Но из-за того, что Федя где-то у себя +1 с -1 перепутал...

Если уж пользователь ждет Result из-за невозможности выполнить работу, то плевать в дополнение еще и панику — это порастомански :)

Дык. Как обычно. Наносекунды сами по себе не срежутся.

Речь не про наносекунды, а про код, который нужно написать, протестировать, задокументировать и сопровождать.

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

А там и нет копирования. А если вам нужно редактировать этих строки в дальнейшем - то без копирования никак. Даже в C++.

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

Да там гораздо интереснее, если:

let y2 = "cdeg";

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

любое описание типов нагружает восприятие

Зато упрощает разработку и уменьшает время втыкания в документацию

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