LINUX.ORG.RU

Избранные сообщения tchspprt

chroot и монтирование proc, sys, dev

Форум — General

Запутался совсем с тем, как монтировать proc, sys и dev. Помогите плиз.

Ситуация такова: есть chroot-песочница, которая должна жить полностью своей жизнью. Все, что ей нужно от хоста — это несколько устройств из /dev. Собственного ssh и других «потребителей» pts у нее нет.

Тут есть два варианта:
1. монтирование (mount -t proc proc $CHROOT/proc)
2. биндинг (mount -o bind /dev $CHROOT/dev)
Какие каталоги как монтировать?

Плюс вопрос в том, откуда это делать? Что нужно монтировать на хосте, а что уже из-под chroot?

У меня после «неудачного» монтирования /dev почему-то отвалился /dev/pts и стоило больших усилий вернуть контроль над сервером.

 

quwy
()

Написание свободной(Free as in Freedom) книги-самоучителя по программированию: планы, цели, задачи

Форум — Development

Итак, я решил написать(или как вариант, собрать из кусочков) книгу-самоучилель по программированию, в которой бы не было глупых и нелепых ограничений на распространение. Однако копилефт я все же считаю приемлемым в данном случае. Общественным достоянием это не будет т.к. вполне могут найтись желающие использовать результат в своих проприетарных книгах, а проприетарные книги — плохо. Лицензия самого текста книги-учебника будет или Creative Commons Attribution-ShareAlike (что позволит без каких-либо проблем переиспользовать текст из википедии) или что-то вроде GNU Free Documentation License (без неизменяемых разделов естественно).

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

Теперь к теме того, на кого книга ориентирована, какие начальные знания предполагаются, чему книга будет учить, какой первый ЯП взять и каков будет авторский самысел: С этим моментом я пока что не определился окончательно, и тут есть что обсудить. В частности, я не вижу особого смысла объяснять какие-то базовые понятия комбинаторики, об этом можно доступным языком прочитать из школьных учебников. Системы счисления(СС), перевод из одной СС в другую - вот это еще можно. One's и two's complement представления знаковых чисел — про это тоже можно написать. Если же человек не понимает комбинаторику, он ее быстро поймет на примере кода, который будет достаточно наглядно это показывать, и который всенепременно будет.
Пока что в качестве первого языка я склоняюсь к Си, и тому есть причины. Все прочие распространенные языки (кроме ассемблера, хотя его трудно назвать распространенным) не настолько близки к аппаратному уровню. Про нужность понимания на низком уровне написано тут http://russian.joelonsoftware.com/Articles/BacktoBasics.html https://habrahabr.ru/company/piter/blog/271347/ , не вижу смысла повторяться. Приведу лишь цитату:

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

Притом еще один важный момент: Си будет изучаться параллельно с ассемблером. Если речь идет об изучении ассемблера, необходимо четко зафиксировать то, на какой архитектуре это все происходит и в какой ОС. Так вот, ОС будет GNU/Linux а архитектура x86-64. Будут постоянно проводиться параллели между тем, что из себя представляет код на Си в текстовом виде, и тем, в какой текст на ассемблере его превращает компилятор. В связи с этим, первым делом будет рассказано о goto и конструкции if(условие) goto метка;. Про конструкции вида

if(условие)
{
  что-то_делаем;
}
else
{
  что-то_другое_делаем;
}
Будет рассказано немного позже, притом это будет рассказано и словами, и через написание эквивалентного кода через if(условие) goto метка;. Циклы, for(){} while{}, do{}while(), конструкция switch-case и break continue внутри них будут так же объясняться через все тот же if(условие) goto метка; притом будет делаться явный акцент на том, что намного лучше использовать нормальные циклы, чем лепить всюду этот условный goto. Кроме того, будет так же рассказано про Labels as Values. Почему так важна эта странная штука, if(условие) goto метка;? Потому что она имеет наипрямейшее отношение к тому, как работают ЭВМ, а всякие циклы СКРЫВАЮТ это. Рекурсия в Си будет объясняться только после того, как будет объяснено, что такое стекфрейм и соглашения вызова, будет сказано про оптимизацию хвостовой рекурсии, и о проблеме забивания стека, если такая оптимизация не происходит, притом это будет наглядно показано в ассемблере. Учиться отлаживать код надо будет тоже «с пеленок», притом отлаживать и ассемблер, и всякие там Си. Будет и про асм-вставки в Си, clobber list. В качестве ассемблера будет рассматриваться GAS, а никакой не NASM т.к. GCC умеет выплевывать ассемблер именно в GAS синтаксисе. Насчет выбора Intel или AT&T синтаксиса - тут я склонюсь пожалуй к тому, что надо ЗНАТЬ И УМЕТЬ ПОНИМАТЬ ОБА. Кроме того, GAS давно уже умеет в оба синтаксиса, так что проблем с этим не будет. Единственная проблема с GAS в том, что это однопроходной ассемблер, так что можно освоить и какой-нибудь NASM, YASM.

Первые хеллоуворды будут написаны вообще в особом стиле, без использования printf() и вообще без библиотеки Си; Будут использованы куски на ассемблере, которые делают системный вызов write и read, и с ними можно(нужно) будет линковаться, чтоб что-то вывести на экран. Будет рассказано и про printf естественно, но только когда будет совершенно четко ясно, что такое вообще va_list. Будет куча отсылок к драфту стандарта Си (недрафт почему-то платный). Будет так же рассказано про устройство ОС. В конце скорее всего будет дано задание сделать свою игрушечную ОС так что предполагается что человек к тому моменту должен уже отлично понимать всякие там связные списки, графы, очереди, спинлоки-аллокаторы свои уметь делать на асме при желании. Алгоритмы сортировки, обхода графов, хеш-таблицы, все это будет объяснено на языке Си, и плюсов вообще касаться я не буду.

Насчет графики: работу с протоколом иксов тоже можно будет рассказать, обработку нажатий клавиши. Правда там надо дофига писать про кучу всего, например что есть сокеты, есть AF_LOCAL... Тогда это можно еще и сетевому программированию учить на каких-нибудь беркли-сокетах.

Кроме того, после моей книги предполагается, что человек должен уметь заниматься такими ненужными (в GNU/Linux) на первый взгляд вещами, как крякинг, реверсинг, исправление ошибок в бинарниках, не обладая исходным текстом. Восстановление логики работы программы по дизасму. Ну и программирование в машинных кодах (без ассемблера, одним HEX редактором).

Как-то уж слишком дофига, не находите? Может быть не надо так глубоко во все это нырять? Жду предложений и критики по поводу того, что нужно, а чего не нужно писать. Возможно что я слишком много хочу.

cast ASM be_nt_all mister_VA

UPD: Программирование и отладка на C/ASM - Первые программы. Знакомство с C и ассемблером. Компиляция, линковка, код возврата. Вывод текста.

 , , ,

SZT
()

Выгрузка памяти ядра Linux в swap

Форум — Development

Может ли само ядро Linux свою собственную память хранить/выгружать в swap раздел во время работы? Если да, как эту возможность включить или выключить и как узнать, включена она или выключена?

 ,

SZT
()

inline callback-функций как способ метапрограммирования

Форум — Development

Я вот задумался. Взять например функцию qsort() из стандартной библиотеки сей, ну которая принимает указатель на массив, количество элементов в этом самом массиве, размер одного элемента массива и функцию которая принимает два указателя на элементы массива, делает сравнение и возвращает int. Что если реализовать механизм встраивания всей этой фигни (за исключением разве что указателя на тот самый массив, который сортировать надо) и можно значительно ускорить процесс сортировки. Например, тут https://books.google.com/books?id=RPnWe6QKnCcC&pg=PA201&lpg=PA201&amp... говорят что std::sort быстрее qsort т.к. там компилятор может заинлайнить это. Но это не универсально. Если в компилтайме нам например неизвестен способ сравнивания двух элементов массива(т.е. мы это узнаем только на этапе выполнения), там ничего не заинлайнится. Например, как решать такую задачу : программа читает некий массив чисел(неизвестно заранее сколько, допустим читаем из файла. Пусть это будет тип float), пользователь вводит некую формулу, например y=x*x+2*(x-1) и каждое число из списка подставляются последовательно в эту формулу как x, вычисляется y и записывается потом куда-то в файл. Самый простой способ реализовать подобное на C - генерить в рантайме на основе введенной формулы некий исходник на C, компилировать его как .so, подгружать через dlopen и запустить. Желательно при этом, чтобы сам цикл с последовательным применением формулы был тоже сгенерирован внутри этой самой библиотеки, чтобы не было проседаний на каждый вызов функции. Шаблоны из плюсов тут ничем не помогут в плане оптимизации, они не могут отработать в процессе выполнения кода и что-либо там менять-добавлять. А через inline callback-функции это было бы очень просто сделать без особых проблем. Например, мы получаем от пользователя нуль-терминированную строку вида «x*x+2*(x-1)». Значит нам нужна функция, которая бы принимала указатель на строку, указатель на массив-источник, указатель на массив-назначение и кол-во элементов в массиве, которое надо по этой формуле преобразовать. Назовем эту функцию apply_ar. Получим что-то вроде

void (*apply_arr(char *str, float *src, float *dst, size_t nmemb))(void)
{
    какой-то_код;
    return somestuff;
}

Так оно просто вернет указатель на функцию, которая вообще ничего не принимает т.е. просто встроит в функцию все аргументы. Будет в итоге сгенерирована функция, которая по неким вшитым в код адресам в цикле читает флоаты, применяет вшитую в код формулу и записывает результат в заранее оговоренную область памяти. Получилось очень неуниверсально. Задачу можно изменить, например может потребоваться обрабатывать много массивов разной длины с разными адресами *src *dst но по одинаковой формуле. Тогда надо городить другую функцию, на этот раз принимающую только строку, описывающую формулу преобразования и которая возвращает функцию, принимающую указатель на источник, назначение, количество элементов. Примерно так:

void (*apply_arr(char *str))(float *src, float *dst, size_t nmemb)
{
    какой-то_код;
    return somestuff;
}
Получается что-то вроде каррирования с суперкомпиляцией, специализация программ методом частичных вычислений: http://keldysh.ru/papers/2008/prep12/prep2008_12.html#_Toc193602742

А теперь насчет callback-ов и их встраивания. Можно передавать в нашу функцию еще и код, который бы делал само вычисление по формуле. Для этого можно сделать функцию, в которую если передать например строку вида «x*x+2*(x-1)» вернет указатель на функцию вида

float calculate(float s)
{
    return x*x+2*(x-1);
}
И результат этой функции передавать в функцию apply_arr. Таким образом, если кто-нибудь захочет задавать формулу например в обратной польской записи, то мы просто напишем еще одну функцию и в случае чего будем передавать ее результат. Только тут просто указатель на функцию передать в рантайме не выйдет (нам ведь надо чтобы оно инлайнилось в функцию, которая будет сгенерирована функцией), таким образом нужно вводить некий байткод, промежуточное представление, которое потом бы компилировалось. Можно взять готовое, например формат промежуточного представления от какого-нибудь компилятора. В самой нашей функции apply_arr тогда тоже надо хранить этот байткод, и наша функция должна два эти байткода (свой и тот который в нее передается) уметь комбинировать и выдавать на выходе указатель на функцию с нативным кодом. Что самое интересное, если это все как следует продумать, можно сделать полноценный лисп поверх C, только с ручным управлением памятью. Самое замечательное, что это хоть сейчас можно в какой-то степени реализовать, только вместо байткода надо брать обычный сишный код, а для «встраивания» кода внутрь кода использовать что-то вроде
printf("some code;\n"
"%s\n"
"some code;\n");
, потом кормить этим компилятор и загружать получившийся код в исполняемую область памяти. Для более нормальной реализации всего этого, надо каким-то образом переделать компилятор. Саму специализацию можно делать как на этапе компиляции, так и в рантайме. Если промежуточное представление сделать как AST, это будет вообще замечательно. Всю программу можно собрать из этих коллбеков, и не будет ни одной нормальной привычной функции. Вся программа это функция, в которую передается массив из функций, каждая из функций может быть например оператором сложения int с int, float с float, разыменование указателя, операцией приведения типа, вызов какой-то функции. При том, необязательно все это дело инлайнить. Сами функции могут просто вызываться обычным путем, несмотря на возможность их заинлайнить. Таким образом можно переопределить любое действие, при том в рантайме (например можно сделать, что при попытке записи в или чтения из памяти по такому-то адресу, это событие логировалось. Или смотреть статистику, какие функции с какими аргументами вызываются)

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

 , , , ,

SZT
()

strace не ловит вызовы gettimeofday, clock_gettime

Форум — Development

Сабж. Пример кода:

#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>

inline uint64_t gettime1(void)
{
  struct timespec tm;
  clock_gettime(CLOCK_REALTIME, &tm);
  return (uint64_t)tm.tv_sec * 1000000000ull + tm.tv_nsec;
}

inline uint64_t gettime2(void)
{
  struct timeval tm;
  gettimeofday(&tm, NULL);
  return (tm.tv_sec * 1000000 + tm.tv_usec) * 1000ULL;
}

int main(void)
{
  uint64_t b = gettime2();
  uint64_t a = gettime1();
  printf("%"PRIu64"\n""%"PRIu64"\n", a, b);
  return 0;
}
Система Linux user-MS-7519 3.13.0-49-generic #83-Ubuntu SMP Fri Apr 10 20:11:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Выхлоп strace

strace -c ./a.out 
1433046804438570051
1433046804438568000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 28.99    0.000040           5         8           mmap
 17.39    0.000024           6         4           mprotect
 13.04    0.000018           6         3         3 access
 10.87    0.000015           8         2           write
  7.97    0.000011           6         2           open
  7.97    0.000011          11         1           munmap
  5.80    0.000008           3         3           fstat
  2.90    0.000004           2         2           close
  2.17    0.000003           3         1           read
  1.45    0.000002           2         1           arch_prctl
  0.72    0.000001           1         1           brk
  0.72    0.000001           1         1           execve
------ ----------- ----------- --------- --------- ----------------
100.00    0.000138                    29         3 total

В чем может быть проблема?

 ,

SZT
()