Я хочу изучить программирование ядра Linux.
Что может быть отправной точкой для этого? На какие из более простых проблем можно ориентироваться?
Я хочу изучить программирование ядра Linux.
Что может быть отправной точкой для этого? На какие из более простых проблем можно ориентироваться?
Попробуйте раздобыть книгу Роберта Лава о программировании ядра Linux. Его очень кратко и легко следовать.
После этого или одновременно с этим вы, возможно, захотите взглянуть на «Понимание ядра Linux». Но я бы не рекомендовал его на ранних стадиях.
Кроме того, ознакомьтесь с руководством по программированию ядра Linux. Поскольку при программировании модулей ядра можно многому научиться, это руководство поможет вам. И да, для получения дополнительной информации обратитесь к подкаталогу 'documentation' архива с исходными кодами ядра.
**TODO** +editPic: Linux Kernel Developer -> (Ring Layer 0)
+addSection: Kernel Virtualization Engine
KERN_WARN_CODING_STYLE: Do not Loop unless you absolutely have to.
Рекомендуемые книги для неинициализированных
void *i«Люди не понимают книг, пока не проживут определенное количество жизни, или, во всяком случае, ни один человек не поймет глубокую книгу, пока не увидит и не проживет хотя бы часть ее содержания». – Эзра Паунд
Путешествие в тысячу кодовых миль должно начинаться с одного шага. Если вы не знаете, с какой из следующих книг начать, не волнуйтесь, выберите любую по своему выбору. Не все те, кто бродят теряются. Поскольку все дороги в конечном счете соединяются с шоссе, вы будете исследовать новые вещи в своем путешествии по ядру по мере продвижения страниц, не встречая никаких тупиков, и в конечном итоге соединитесь с code-set. Читайте внимательно и помните: Код — это не литература.
Остается не вещь, не эмоция, не образ, не ментальная картина, не воспоминание и даже не идея. Это функция. Процесс какой-то. Аспект Жизни, который можно описать как функцию чего-то «большего». И поэтому оказывается, что оно на самом деле не «отделимо» от этого чего-то другого. Подобно тому, как функция ножа — резать что-то — на самом деле неотделима от самого ножа. Функция может использоваться или не использоваться в данный момент, но потенциально она НИКОГДА не является отдельной.
Дерандомизированный алгоритм Соловея-Штрассена для проверки простоты:

Читайте, чтобы не противоречить и не опровергать; ни верить и принимать как должное; ни найти разговоры и дискурс; но взвесить и рассмотреть. Одни книги нужно пробовать на вкус, другие проглатывать, а некоторые — жевать и переваривать, то есть одни книги нужно читать только частями, другие — читать, но без любопытства, а некоторые — читать целиком. , и с усердием и вниманием.
static void tasklet_hi_action(struct softirq_action *a)
{
struct tasklet_struct *list;
local_irq_disable();
list = __this_cpu_read(tasklet_hi_vec.head);
__this_cpu_write(tasklet_hi_vec.head, NULL);
__this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head));
local_irq_enable();
while (list) {
struct tasklet_struct *t = list;
list = list->next;
if (tasklet_trylock(t)) {
if (!atomic_read(&t->count)) {
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state))
BUG();
t->func(t->data);
tasklet_unlock(t);
continue;
}
tasklet_unlock(t);
}
local_irq_disable();
t->next = NULL;
*__this_cpu_read(tasklet_hi_vec.tail) = t;
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
__raise_softirq_irqoff(HI_SOFTIRQ);
local_irq_enable();
}
}
Core Linux ( 5 -> 1 -> 3 -> 2 -> 7 -> 4 -> 6 )
«У природы нет ни ядра, ни оболочки; она — все сразу» — Иоганн Вольфганг фон Гёте
Читатель должен хорошо разбираться в концепциях операционных систем; справедливое понимание длительных процессов и их различий с процессами с короткими всплесками выполнения; отказоустойчивость при соблюдении мягких и жестких ограничений реального времени. При чтении важно понимать и n/ack выбор дизайна, сделанный исходным кодом ядра Linux в основных подсистемах.
Потоки [и] сигналы [являются] зависящим от платформы следом страданий, отчаяния, ужаса и безумия (~Энтони Баксте). При этом вы должны быть экспертом по самооценке C, прежде чем погрузиться в ядро. Вы также должны иметь хороший опыт работы со связанными списками, стеками, очередями, красно-черными деревьями, хеш-функциями и т. д.
volatile int i;
int main(void)
{
int c;
for (i=0; i<3; i++) {
c = i&&&i;
printf("%d\n", c); /* find c */
}
return 0;
}
Красота и искусство исходного кода ядра Linux заключается в преднамеренной запутанности кода, используемой вместе с ним. Это часто необходимо, чтобы передать вычислительный смысл, включающий две или более операций, чистым и элегантным способом. Это особенно актуально при написании кода для многоядерной архитектуры.
видеолекции по системам реального времени, Планирование задач, Сжатие памяти, Барьеры памяти, SMP
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
Драйверы устройств Linux ( 1 -> 2 -> 4 -> 3 -> 8 -> ... )
"Музыка не увлекает вас за собой. Вы должны удерживать ее исключительно за счет своей способности действительно просто сосредоточиться на этом маленьком зернышке эмоции или истории". -- Дебби Гарри
Ваша задача в основном состоит в том, чтобы установить высокоскоростной интерфейс связи между аппаратным устройством и программным ядром. Вам следует прочитать справочное техническое описание/руководство по оборудованию, чтобы понять поведение устройства, его управление и состояние данных, а также предоставляемые физические каналы. Знание ассемблера для вашей конкретной архитектуры и хорошее знание языков описания оборудования СБИС, таких как VHDL или Verilog, помогут вам в долгосрочной перспективе.
В. Но зачем мне читать спецификации оборудования?
О: Потому что "существует пропасть между углеродом и кремнием, которую программное обеспечение не может преодолеть", – Рахул Соннад.
Однако это не создает проблемы для вычислительных алгоритмов (кода драйвера - обработка нижней половины), поскольку это может полностью смоделирована на универсальной машине Тьюринга. Если вычисленный результат верен в математической области, можно с уверенностью сказать, что это также верно в физическом домене.
Видео-лекции о драйверах устройств Linux (Lec . 17 и 18), Анатомия встроенного драйвера KMS, Контроль контактов и обновление GPIO, Common Clock Framework, Напишите настоящий драйвер для Linux — Грег К. Х.
static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;
if (PHY_HALTED == phydev->state)
return IRQ_NONE; /* It can't be ours. */
/* The MDIO bus is not allowed to be written in interrupt
* context, so we need to disable the irq here. A work
* queue will write the PHY to disable and clear the
* interrupt, and then reenable the irq line.
*/
disable_irq_nosync(irq);
atomic_inc(&phydev->irq_disable);
queue_work(system_power_efficient_wq, &phydev->phy_queue);
return IRQ_HANDLED;
}
Сеть ядра ( 1 -> 2 -> 3 -> ... )
«Назовите это кланом, назовите это сетью, назовите это племенем, назовите это семьей: как бы вы это ни называли, кем бы вы ни были, вам это нужно». - Джейн Ховард
Понимание обхода пакетов в ядре является ключом к пониманию работы сети ядра. Понимание этого необходимо, если мы хотим понять внутреннее устройство Netfilter или IPSec и многое другое. Двумя наиболее важными структурами сетевого уровня ядра Linux являются: struct sk_buff и struct net_device.
static inline int sk_hashed(const struct sock *sk)
{
return !sk_unhashed(sk);
}
Отладка ядра ( 1 -> 4 -> 9 -> ... )
Если при общении с ним человек не говорит точно, что имеет в виду, это неизбежно приведет к неприятностям. ~Алан Тьюринг, о компьютерах
Брайан В. Керниган в статье Unix для начинающих (1979) сказал: «Наиболее эффективным инструментом отладки по-прежнему является тщательное обдумывание в сочетании с разумно размещенными операторами печати». Знание того, что нужно собирать, поможет вам быстро получить нужные данные для быстрой диагностики. Великий ученый-компьютерщик Эдсгер Дейкстра однажды сказал, что тестирование может продемонстрировать наличие ошибок, но не их отсутствие. Надлежащая практика проведения расследований должна уравновешивать необходимость быстрого решения проблем, необходимость развития навыков и эффективное использование экспертов в предметной области.
Бывают моменты, когда вы достигаете дна, кажется, что ничего не работает, и у вас заканчиваются все варианты. Именно тогда начинается настоящая отладка. Ошибка может обеспечить перерыв, необходимый вам, чтобы освободиться от фиксации на неэффективном решении.
Видео-лекции по отладке и профилированию ядра, Анализ дампа ядра, Отладка многоядерных процессоров с помощью GDB, Управление многоядерными процессорами Условия гонки, Отладка электроники
/* Buggy Code -- Stack frame problem
* If you require information, do not free memory containing the information
*/
char *initialize() {
char string[80];
char* ptr = string;
return ptr;
}
int main() {
char *myval = initialize();
do_something_with(myval);
}
/* “When debugging, novices insert corrective code; experts remove defective code.”
* – Richard Pattis
#if DEBUG
printk("The above can be considered as Development and Review in Industrial Practises");
#endif
*/
Файловые системы ( 1 -> 2 -> 6 -> ... )
"Я хотел иметь виртуальную память, по крайней мере, в сочетании с файловыми системами". -- Кен Томпсон
В системе UNIX все является файлом; если что-то не является файлом, это процесс, за исключением именованных каналов и сокетов. В файловой системе файл представлен inode, своего рода порядковым номером, содержащим информацию о фактических данных, из которых состоит файл. Виртуальная файловая система Linux VFS кэширует в памяти информацию из каждой файловой системы по мере ее монтирования и использования. Необходимо уделять много внимания правильному обновлению файловой системы, поскольку данные в этих кэшах изменяются по мере создания, записи и удаления файлов и каталогов. Наиболее важным из этих кэшей является буферный кэш, который интегрирован в способ, которым отдельные файловые системы обращаются к своим базовым блочным устройствам хранения.
Видео-лекции по системам хранения, Файловая система, поддерживающая Flash
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
int fd = build_open_flags(flags, mode, &op);
struct filename *tmp;
if (fd)
return fd;
tmp = getname(filename);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
fd = get_unused_fd_flags(flags);
if (fd >= 0) {
struct file *f = do_filp_open(dfd, tmp, &op);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f);
fd_install(fd, f);
}
}
putname(tmp);
return fd;
}
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
Безопасность ( 1 -> 2 -> 8 -> 4 -> 3 -> ... )
«UNIX не был разработан для того, чтобы мешать своим пользователям делать глупости, поскольку это также мешало бы им делать умные вещи». — Дуг Гвин
Никакая техника не работает, если она не используется. Этика меняется вместе с технологиями.
"F × S = k" произведение свободы и безопасности является константой. - Законы Нивена
Криптография формирует основу доверия в Интернете. Взлом — это использование мер безопасности с технической, физической или человеческой точки зрения. Защита ядра от других запущенных программ — это первый шаг к безопасной и стабильной системе, но этого явно недостаточно: некоторая степень защиты должна существовать и между различными пользовательскими приложениями. Эксплойты могут быть нацелены на локальные или удаленные службы.
«Вы не можете взломать свою судьбу, грубая сила… вам нужен черный ход, боковой канал в Жизнь». — Клайд Дсуза
Компьютеры не решают проблемы, они реализуют решения. За каждым недетерминированным алгоритмическим кодом стоит решительный разум. -- /var/log/dmesg
видеолекции по криптографии и сетевой безопасности, Пространства имен для безопасности, Защита от удаленных атак, Безопасный встроенный Linux
env x='() { :;}; echo vulnerable' bash -c "echo this is a test for Shellsock"
Исходный код ядра ( 0,11 -> 2,4 -> 2,6 -> 3,18 )
«Как и вино, мастерство программирования ядра со временем созревает. Но, в отличие от вина, в процессе оно становится слаще». -- Лоуренс Мучека
Вы можете не думать, что программисты — художники, но программирование — чрезвычайно творческая профессия. Это логическое творчество. Образование в области информатики не может сделать кого-либо опытным программистом, так же как изучение кистей и пигментов не может сделать кого-то опытным художником. Как вы уже знаете, есть разница между знанием пути и идущим по нему; Крайне важно засучить рукава и запачкать руки исходным кодом ядра. Наконец, с вашими таким образом полученными знаниями ядра, куда бы вы ни пошли, вы будете сиять.
Незрелые кодеры подражают; зрелые кодеры воруют; плохие кодеры портят то, что они берут, а хорошие кодеры делают из этого что-то лучшее или, по крайней мере, что-то другое. Хороший кодер спаивает свою кражу в единое чувство, совершенно отличное от того, из которого она была вырвана.
linux-0.11
├── boot
│ ├── bootsect.s head.s setup.s
├── fs
│ ├── bitmap.c block_dev.c buffer.c char_dev.c exec.c
│ ├── fcntl.c file_dev.c file_table.c inode.c ioctl.c
│ ├── namei.c open.c pipe.c read_write.c
│ ├── stat.c super.c truncate.c
├── include
│ ├── a.out.h const.h ctype.h errno.h fcntl.h
│ ├── signal.h stdarg.h stddef.h string.h termios.h
│ ├── time.h unistd.h utime.h
│ ├── asm
│ │ ├── io.h memory.h segment.h system.h
│ ├── linux
│ │ ├── config.h fdreg.h fs.h hdreg.h head.h
│ │ ├── kernel.h mm.h sched.h sys.h tty.h
│ ├── sys
│ │ ├── stat.h times.h types.h utsname.h wait.h
├── init
│ └── main.c
├── kernel
│ ├── asm.s exit.c fork.c mktime.c panic.c
│ ├── printk.c sched.c signal.c sys.c system_calls.s
│ ├── traps.c vsprintf.c
│ ├── blk_drv
│ │ ├── blk.h floppy.c hd.c ll_rw_blk.c ramdisk.c
│ ├── chr_drv
│ │ ├── console.c keyboard.S rs_io.s
│ │ ├── serial.c tty_io.c tty_ioctl.c
│ ├── math
│ │ ├── math_emulate.c
├── lib
│ ├── close.c ctype.c dup.c errno.c execve.c _exit.c
│ ├── malloc.c open.c setsid.c string.c wait.c write.c
├── Makefile
├── mm
│ ├── memory.c page.s
└── tools
└── build.c
Linux_source_dir/Documentation/*Solovay–Strassen primality test в своем ответе. Я думаю, вы хотите что-то выразить, но я не понял.
- person user565739; 02.07.2015
Ознакомьтесь с проектом Linux Kernel Janitor.
«Мы просматриваем исходный код ядра Linux, проводим проверки кода, исправляем неподдерживаемый код и делаем другие очистки и преобразования API. Это хорошее начало для взлома ядра».
Я бы сказал: «изучайте C». :)
Попробуйте эту бесплатную онлайн-книгу.
Руководство по программированию модуля ядра Linux http://www.linuxhq.com/guides/LKMPG/mpg.html
Следующие книги, которые я прочитал и нашел очень полезными:
Проверьте kernelnewbies.org, подпишитесь на список рассылки Kernelnewbies, перейдите на irc.oftc.org #kernelnewbies
Некоторые ресурсы:
[closed]. - person Seamus   schedule 10.07.2021