проект книги: "Модули ядра Linux"

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

Модераторы: Olej, vikos

Правила форума
Запрещается помещать сообщения, не имеющие отношения к обсуждаемой статье. Все такие сообщения будут удаляться непосредствено после обнаружения.
Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 06 мар 2012, 18:41

bose писал(а): И этот негодняй ещё надсмехается над нами :evil:
Из всех ихних намудряченных случаев меня интересовал бы только один: чтение (ну и запись) очень коротких сообщений (чаще всего, символьного представления целочисленного значения - всего то ;)) - то, что нужно практическому разработчику драйверов для отладки, диагностики ... каких-то управляющих взаимодействий.

Всякие заумные случаи - пусть с ними колхоз "Linux-ядро" во главе со своим председателем Линус Торвальдс - разбирается :lol:

bose
Писатель
Сообщения: 107
Зарегистрирован: 23 фев 2012, 14:41
Откуда: Киев
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение bose » 06 мар 2012, 19:58

Olej писал(а):

Код: Выделить всё

[olej@notebook proc]$ cat /proc/mod_node
Hello from module!
[olej@notebook proc]$ dmesg | tail -n30 | grep -v ^audit
! /proc/mod_node installed
! read: 3072 [buffer=f1f3f000, off=0, *eof=0]
! return bytes: 19
! EOF
! read: 3072 [buffer=f1f3f000, off=19, *eof=0]
! return bytes: 19
! EOF
Просто анализируя полученное в запросе eof, и сравнивая его с тем смещением, которое уже успели передать раньше, не нужно передавать данные (по-новой: адрес buffer не поменялся!), а нужно сразу отправлять EOF.
Я уверяю вас это не так - то что адрес не поменялся - ЧИСТАЯ СЛУЧАЙНОСТЬ! Просто ядро выделила новую страницу из кэша. Если вы поэксперементируете несколько раз - вам так не повезёт.

Вот тот участок кода в generic.c(__proc_file_read):

Код: Выделить всё

if (!(page = (char*) __get_free_page(GFP_TEMPORARY)))
		return -ENOMEM;
Т.е. каждый раз при вызове функции выделяется новая страница! И в конце освобождается:

Код: Выделить всё

free_page((unsigned long) page);
В доказательство - вот результаты двух последовательных вызовов на моей машине (ваш код в proc_node_read я модифицировал для своих целей):
[109819.908472] Buf: ffff88001479b000; Start: (null); Off: 18; Count: 3072; Eof(ffff8800748f3e24): 0;
[109819.908474] Buf: ffff88001479b000; Start: (null); Off: 19; Count: 3072; Eof(ffff8800748f3e24): 0;
[109819.908475] Finish transfer 18 bytes with eof
[109819.908492] Buf: ffff88001479b000; Start: (null); Off: 19; Count: 3072; Eof(ffff8800748f3e24): 0;
[109819.908494] Finish transfer 18 bytes with eof
Совпали!
[109873.059918] Buf: ffff880067ba3000; Start: (null); Off: 18; Count: 3072; Eof(ffff8800748f3e24): 0;
[109873.059920] Buf: ffff880067ba3000; Start: (null); Off: 19; Count: 3072; Eof(ffff8800748f3e24): 0;
[109873.059921] Finish transfer 18 bytes with eof
[109873.059933] Buf: ffff8800083c1000; Start: (null); Off: 19; Count: 3072; Eof(ffff8800748f3e24): 0;
[109873.059934] Finish transfer 18 bytes with eof
Оп! А тут нет...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 06 мар 2012, 21:49

bose писал(а): Я уверяю вас это не так - то что адрес не поменялся - ЧИСТАЯ СЛУЧАЙНОСТЬ! Просто ядро выделила новую страницу из кэша.
Да это и не так важно!
Для мной заявленных целей (малые, меньше 1 стр. данные!) у меня практически готов новый пример, всё понятно и просто ... а более сложные премудрости я собираюсь оставить в стороне.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 06 мар 2012, 23:34

Olej писал(а):
bose писал(а): И этот негодняй ещё надсмехается над нами :evil:
Из всех ихних намудряченных случаев меня интересовал бы только один: чтение (ну и запись) очень коротких сообщений (чаще всего, символьного представления целочисленного значения - всего то ;)) - то, что нужно практическому разработчику драйверов для отладки, диагностики ... каких-то управляющих взаимодействий.
То что они там намудрячили - напоминает полный идиотизм :lol: :
- ведь (вы обратили внимание???) что read_proc_t - не имеет передачи между kernel-space & user-space...
- передача происходит между нашим буфером и некоторым промежуточным буфером ядра, откуда уже внутренними механизмами это путешествует в user-space...
- в чём и состоит радикальное отличие от файловых операций из fops - там мы сами всё копируем в user-space...
- такое впечатление, что с помощью read_proc_t считается, что считать данные нужно все за один раз, ...

- если у меня буфер 34 байт...
- а POSIX read() запросит 40, то происходят удивительные вещи:
- запрос на 40 -> ответ 34, который и получит read(), запрос на 6 (остаток), который явно генерится внутри kernel-space и никуда не доходит, и следующий запрос read() возвращает 0, EOF и всё ОК...
- т.е. 2 запроса read() превращаются в 3 вызова read_proc_t ... как-то вот так:

Код: Выделить всё

! read: 40 (buffer=e2d72000, off=0)
! return bytes: 34 
! read: 6 (buffer=e2d72000, off=34)
! EOF1
! return bytes: 0  ... EOF
! read: 40 (buffer=e2d72000, off=34)
! EOF1
! return bytes: 0  ... EOF
- а при запросе меньше, по частям:

Код: Выделить всё

[olej@notebook proc]$ ./mcat 31
read + 31 bytes, input buffer: Hello from: read_proc_t functio
read + 00 bytes, input buffer: Hello from: read_proc_t functio
- получаем вызовы

Код: Выделить всё

! read: 31 (buffer=f6f88000, off=0)
! return bytes: 31 
! read: 31 (buffer=f6f88000, off=31)
! return bytes: 3 
т.е. второй, остаток в 3 байта, не создающий EOF, до read() не доходит, и создаёт ему ситуацию EOF.

Резюме:
- прочитать этими их делами весь объём данных за раз - запросто!
- а читать как-то последовательно, по частям (по людски) - я в гробу видел...
В конце концов, на то есть файловые операции fops!

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 07 мар 2012, 02:29

Olej писал(а): Резюме:
- прочитать этими их делами весь объём данных за раз - запросто!
Что-то типа:

Код: Выделить всё

ssize_t proc_node_read( char *buffer, char **start, off_t off,
                        int count, int *eof, void *data ) {
   static char buf_msg[ LEN_MSG + 1 ] =
          ".........1.........2.........3.........4.........5.........6\n";
   int i = 0;
   LOG( "read: %d (buffer=%p, off=%ld)", count, buffer, off );
   if( off != 0 ) {  // EOF
      *eof = 1;
      goto end;
   }
   for( i = 0; ( i < count ) && ( off + i < strlen( buf_msg ) ); i++ )
      *( buffer + i ) = *( buf_msg + off + i );
   if( i < count )   // EOF
      *eof = 1;
end:
   LOG( "return bytes: %d %s", i, *eof != 0 ? " ... EOF" : ""  );
   return (ssize_t)i;
};
- это неправильно, но вполне достаточно для чтения короткого значение "за раз":

Код: Выделить всё

[olej@notebook proc]$ cat /proc/mod_node
.........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ dmesg | tail -n30 | grep -v ^audit
! /proc/mod_node installed
! read: 3072 (buffer=f15d1000, off=0)
! return bytes: 61  ... EOF
! read: 3072 (buffer=f15d1000, off=61)
! return bytes: 0  ... EOF
- здесь никаких противоречий: 1-е чтение возвращает 61 байт + 2-е чтение возвращает 0 (EOF).

P.S. Кстати, любопытно, почему независимо от того, сколько запрашивает read() (а cat запрашивает за раз 32767 байт), read_proc_t функция получает единичный запрос 3072 - это ровно 3Kb ... но это не страница (4Kb), которая везде фигурирует у них в невнятных обсуждениях.
Если redad() запрашиват короткие порции данных, например 40b, то read_proc_t функция получит запрос точно на эти же 40b.

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

Код: Выделить всё

[olej@notebook mod_dir]$ cat /proc/mod_dir/mod_node
.........1.........2.........3.........4.........5
[olej@notebook mod_dir]$ echo new string > /proc/mod_dir/mod_node
[olej@notebook mod_dir]$ cat /proc/mod_dir/mod_node
new string
[olej@notebook mod_dir]$ dmesg | tail -n30 | grep -v ^audit
! read: 8192 bytes
! return 51 bytes
! read: 8141 bytes
! EOF
! read: 32768 bytes
! return 51 bytes
! read: 32768 bytes
! EOF
! write: 11 bytes
! put 11 bytes
! read: 32768 bytes
! return 11 bytes
! read: 32768 bytes
! EOF
Всё совершенно чистенько ;)

P.P.S. Конечно, интересно бы довести примеры работы с read_proc_t функцией для разных случаев (нескольких последовательных коротких вызовов "по частям" + суммарным объёмом больше страницы 4Kb ... или 3Kb???) ... но это можно уже оставить "на свободное от основных занятий время" :mrgreen:

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 07 мар 2012, 11:32

Olej писал(а): P.P.S. Конечно, интересно бы довести примеры работы с read_proc_t функцией для разных случаев (нескольких последовательных коротких вызовов "по частям" + суммарным объёмом больше страницы 4Kb ... или 3Kb???) ... но это можно уже оставить "на свободное от основных занятий время" :mrgreen:
Достаточно любопытные вещи вылазят... :-o
("Неисповедимы дела Твои, Линус Торвальдс")

Маленькая программка mcat.c, уместная вообще ко всем примерам в /proc: подобна cat, но запрашивает в цикле чтений разовую длину порции, которую можно указать параметром запуска:

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "common.h"

static int get_proc( void ) {
   char dev[ 80 ];
   int df;
   sprintf( dev, "/proc/%s", NAME_NODE );
   if( ( df = open( dev, O_RDONLY ) ) < 0 ) {
      sprintf( dev, "/proc/%s/%s", NAME_DIR, NAME_NODE );
      if( ( df = open( dev, O_RDONLY ) ) < 0 )
         printf( "open device error: %m\n" ), exit( EXIT_FAILURE );
   }
   return df;
}

int main( int argc, char *argv[] ) {
   int df = get_proc(),
       len = ( argc > 1 && atoi( argv[ 1 ] ) > 0 ) ?
             atoi( argv[ 1 ] ) : LEN_MSG;
   char msg[ LEN_MSG + 1 ] = "";
   char *p = msg;
   int res;
   do {
      if( ( res = read( df, p, len ) ) >= 0 ) {
         *( p += res )  = '\0';
         printf( "read + %02d bytes, input buffer: %s", res, msg );
         if( *( p - 1 ) != '\n' ) printf( "\n" );
      }
      else printf( "read device error: %m\n" );
   } while ( res > 0 );
   close( df );
   return EXIT_SUCCESS;
};
в "common.h" определены общие константы проекта, ну и оттуда mcat знает имена интересующих /proc/*, чтоб не набирать каждый раз...

А теперь минимально-достаточный код функции чтения в модуле:

Код: Выделить всё

#include "common.h"

static ssize_t proc_node_read( char *buffer, char **start, off_t off,
                               int count, int *eof, void *data ) {
   static char buf_msg[ LEN_MSG + 1 ] =
          ".........1.........2.........3.........4.........5.........6\n";
   LOG( "read: %d (buffer=%p, off=%ld)", count, buffer, off );
   strcpy( buffer, buf_msg );
   LOG( "return bytes: %d%s", strlen( buf_msg ), *eof != 0 ? " ... EOF" : "" );
   return strlen( buf_msg );
};
Всё!
Т.е. в упрощенчестве они дошли до того, что (при передаче объёма данных <=3Kb) в качестве обработчика достаточно одной операции strcpy() ... никаких EOF, разбиения объёма передачи на порции запрашиваемого объёма, позиционирования начала каждой передачи...
Всё делается скрыто внутри kernel кода, который пересылает это в user-space.
Сами себя перемудрили ... это бред! :twisted:

А теперь как это корректно работает:

Код: Выделить всё

[olej@notebook proc]$ ./mcat 10
read + 10 bytes, input buffer: .........1
read + 10 bytes, input buffer: .........1.........2
read + 10 bytes, input buffer: .........1.........2.........3
read + 10 bytes, input buffer: .........1.........2.........3.........4
read + 10 bytes, input buffer: .........1.........2.........3.........4.........5
read + 10 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 01 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ dmesg | tail -n50 | grep -v ^audit
! /proc/mod_node installed
! read: 10 (buffer=f32b1000, off=0)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=10)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=20)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=30)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=40)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=50)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=60)
! return bytes: 61
! read: 9 (buffer=f32b1000, off=61)
! return bytes: 61
! read: 10 (buffer=f32b1000, off=61)
! return bytes: 61
- обратите внимание там на совершенно ... пикантный ;-) запрос на 9 байт...

Код: Выделить всё

[olej@notebook proc]$ ./mcat 70
read + 61 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6

[olej@notebook proc]$ dmesg | tail -n6 | grep -v ^audit
! read: 70 (buffer=f1dfd000, off=0)
! return bytes: 61
! read: 9 (buffer=f1dfd000, off=61)
! return bytes: 61
! read: 70 (buffer=f1dfd000, off=61)
! return bytes: 61

Код: Выделить всё

[olej@notebook proc]$ ./mcat 3
read + 03 bytes, input buffer: ...
read + 03 bytes, input buffer: ......
read + 03 bytes, input buffer: .........
read + 03 bytes, input buffer: .........1..
read + 03 bytes, input buffer: .........1.....
read + 03 bytes, input buffer: .........1........
read + 03 bytes, input buffer: .........1.........2.
read + 03 bytes, input buffer: .........1.........2....
read + 03 bytes, input buffer: .........1.........2.......
read + 03 bytes, input buffer: .........1.........2.........3
read + 03 bytes, input buffer: .........1.........2.........3...
read + 03 bytes, input buffer: .........1.........2.........3......
read + 03 bytes, input buffer: .........1.........2.........3.........
read + 03 bytes, input buffer: .........1.........2.........3.........4..
read + 03 bytes, input buffer: .........1.........2.........3.........4.....
read + 03 bytes, input buffer: .........1.........2.........3.........4........
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5....
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.......
read + 03 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 01 bytes, input buffer: .........1.........2.........3.........4.........5.........6
read + 00 bytes, input buffer: .........1.........2.........3.........4.........5.........6

Код: Выделить всё

[olej@notebook proc]$ cat /proc/mod_node 
.........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ cat /proc/mod_node 
.........1.........2.........3.........4.........5.........6
[olej@notebook proc]$ cat /proc/mod_node 
.........1.........2.........3.........4.........5.........6
Тому, кто понимает толк в извращениях, должно понравиться то, что я показал :mrgreen:

А в сухом остатке:
- если из модуля нужно вычитать <3Kb, то делается это простым strcpy() ...
- а если нужно вычитать >3Kb (но не говорит ли это о симптомах мразма? :-? ), то нужно это делать совсем другими способами...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 07 мар 2012, 13:05

Olej писал(а):- а если нужно вычитать >3Kb (но не говорит ли это о симптомах мразма? :-? ), то нужно это делать совсем другими способами...
Сделал те же самые подчистки для операций из таблицы fops... плюс другое всякое украшательство...

То, что теперь получилось для /proc - прилагается в новом архиве.
Теперь с ним можно поэкспериментировать.
Мне кажется, что в таком виде это уже достаточно.
Текст в описании "Модули ядра..." теперь должен быть изменён...
Вложения
proc.tgz
(4.24 КБ) 406 скачиваний

bose
Писатель
Сообщения: 107
Зарегистрирован: 23 фев 2012, 14:41
Откуда: Киев
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение bose » 07 мар 2012, 14:58

Olej писал(а): Сделал те же самые подчистки для операций из таблицы fops...
Вы слишком часто постите :lol: - я не успеваю реагировать. Не знаю какой ваш пост начать комментировать...
Olej писал(а): P.S. Кстати, любопытно, почему независимо от того, сколько запрашивает read() (а cat запрашивает за раз 32767 байт), read_proc_t функция получает единичный запрос 3072 - это ровно 3Kb ... но это не страница (4Kb), которая везде фигурирует у них в невнятных обсуждениях.
К гадалке ходить не будем:
fs/proc/generic.c:38

Код: Выделить всё

/* buffer size is one page but our output routines use some slack for overruns */
#define PROC_BLOCK_SIZE	(PAGE_SIZE - 1024)
Кстати в fs/proc/base.c:748

Код: Выделить всё

#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
Т.е. тоже самое, но только в профиль...
Теперь вопрос звучит по другому: что имеется ввиду под "slack for overruns" и где в коде его можно увидеть?
Ну и сама логика вычисления кол-ва байт для чтения:
fs/proc/generic.c:__proc_file_read

Код: Выделить всё

	pos = *ppos;
	if (pos > MAX_NON_LFS)
		return 0;
	if (nbytes > MAX_NON_LFS - pos)
		nbytes = MAX_NON_LFS - pos;
.....
        while ((nbytes > 0) && !eof) {
		count = min_t(size_t, PROC_BLOCK_SIZE, nbytes); // !!!!! вот эта строка, которая решает сколько ж байт у нас запросить
.....
                n = dp->read_proc(page, &start, *ppos, count, &eof, dp->data);  // вызывается определённая нами функция
.....
                n -= copy_to_user(buf, start < page ? page : start, n);   а тут данные передаются пользователю
.....
                nbytes -= n;
        }
Есть много вопросов, но ясно одно (без нескольких если) - если мы запросили данных меньше 3К - то это примут во внимание, если больше то - PROC_BLOCK_SIZE
PS:
Как вы после "освещения" этого вопроса прокомментируете утвержение Jerry Cooperstein - "The start argument is a left-over legacy from earlier implementation and isn't used."?
Всяк кто посмотрит в код поймёт что это, мягко говоря, не соответсвует действительности :-?

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 07 мар 2012, 15:30

bose писал(а):
Olej писал(а): Сделал те же самые подчистки для операций из таблицы fops...
Вы слишком часто постите :lol: - я не успеваю реагировать. Не знаю какой ваш пост начать комментировать...
Я делаю для себя записи на черновике, зная где я их потом всегда могу найти.
Вам совершенно не обязательно отвечать на всё.
bose писал(а): К гадалке ходить не будем:
fs/proc/generic.c:38

Код: Выделить всё

/* buffer size is one page but our output routines use some slack for overruns */
#define PROC_BLOCK_SIZE	(PAGE_SIZE - 1024)
Кстати в fs/proc/base.c:748

Код: Выделить всё

#define PROC_BLOCK_SIZE	(3*1024)		/* 4K page size but our output routines use some slack for overruns */
Т.е. тоже самое, но только в профиль...
Это так. И подтверждает то, что наблюдается...
Но!
Я очень не люблю, без крайней на то необходимости, для выяснения нюансов смотреть код реализации.
Он чаще выражает ошибочные представления разработчика, вместо того, как это действительно работает. :lol:
С точки зрения прикладного разработчика, а меня интересует только такая позиция, (... пусть о красотах ядра голова у Линуса Торвальдса болит ;-) ) - очень правильно представлять любой API как чёрный ящик, который по заказанным входным воздействиям должен обеспечивать обещаемую реакцию.
Это очень достоверный способ!

Хотя ... нет никаких абсолютных правил, и когда мало понятно, то лучший способ - это лезть в код реализации.
bose писал(а): Как вы после "освещения" этого вопроса прокомментируете утвержение Jerry Cooperstein - "The start argument is a left-over legacy from earlier implementation and isn't used."?
Всяк кто посмотрит в код поймёт что это, мягко говоря, не соответсвует действительности :-?
Я бы не говорил так категорично ;)
Эта реализация, скорее всего, отражает таки давние-дремучие представления кого-то, как это должно работать... т.е. не ранняя реализация, а давние представления...
Потому как:
- пользоваться этим способом для >3Kb? ... это нужно быть полным безумцем с их реализацией "через задницу"...
- когда рядом лежат ещё 2 альтернативных способа ввода вывода (один из которых даже не назывался, есть в 2 слова в LDD3)...
- та же таблица файловых операций без проблем обеспечивает обмены >4Kb...
- но не нужно, не нужно прикладнику обменивать такие блоки данных!
- а на малых (отладочно-диагностических) данных в качестве функции чтения замечательно работает функция в одну строчку: strcpy() :-o ... (посмотрите архив, что я прикрепил).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: проект книги: "Модули ядра Linux"

Непрочитанное сообщение Olej » 07 мар 2012, 15:40

Olej писал(а): С точки зрения прикладного разработчика, а меня интересует только такая позиция, (... пусть о красотах ядра голова у Линуса Торвальдса болит ;-) ) - очень правильно представлять любой API как чёрный ящик, который по заказанным входным воздействиям должен обеспечивать обещаемую реакцию.
Это очень достоверный способ!
Как там в одно кино говорилось? :
Я табэ одну вэсчь скажу, толко ты не абыжайся!
:lol:

1. Ядро Linux ... (сейчас тут начнётся "вой и скрежет зубовный"(с)) - очень говённая система...
2. ... ку-у-у-уда хуже, чем вся остальная GNU часть системы.
3. это я начал понимать, по несколько лет убив на практические разработки под QNX и Solaris + детально покопав (программирую) MINIX3 Э.Таненбаума...
3. и меня в наибольшей степени занимает то, как гибко и безопасно максимально использовать возможности Linux + все, а не только те, которые мне в своих рекомендациях предоставляют разработчики ядра (вы если дочитаете текст до 2-й половины ;-) - то увидите там эти "рюшечки" ;-) ).

Ответить

Вернуться в «Публикации, книги и обсуждения»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 6 гостей