<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bappoy&#039;s blog &#187; kernel</title>
	<atom:link href="http://bappoy.pp.ru/tag/kernel/feed" rel="self" type="application/rss+xml" />
	<link>http://bappoy.pp.ru</link>
	<description>Линуксоид на велосипеде с моторчиком</description>
	<lastBuildDate>Fri, 02 Dec 2011 11:44:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Разделение аргументов в shebang</title>
		<link>http://bappoy.pp.ru/2009/12/28/shebang-args.html</link>
		<comments>http://bappoy.pp.ru/2009/12/28/shebang-args.html#comments</comments>
		<pubDate>Sun, 27 Dec 2009 20:29:25 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[shebang]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=870</guid>
		<description><![CDATA[<p>В <a href="http://bappoy.pp.ru/2008/12/29/bash-pitfalls-part05.html#comment-8577">комментариях</a> к прошлогоднему <a href="http://bappoy.pp.ru/tag/bash-pitfalls">переводу Bash Pitfalls</a> внимательный <b>flavi</b> задался вопросом, почему при попытке выполнить скрипт, в начале которого написано </p>
<pre>#!/bin/bash --posix --verbose</pre>
<p>выдаётся ошибка </p>
<pre>/bin/bash: --posix --verbose: invalid option</pre>
<p>в то время как в интерактивном режиме bash нормально запускается с такой комбинацией опций; более того, если в shebang&#8217;е оставить только одну из этих опций, то скрипт также запускается без ошибок.</p>
<p>Поначалу я предположил, что <code>--posix</code> запрещает    опции, не определённые <a href="http://www.opengroup.org/onlinepubs/009695399/utilities/sh.html">стандартом POSIX на sh</a>. Но тогда попытка выполнить <code>bash --posix --norc</code> также приводила бы к ошибке, и конструкция <code>#!/bin/bash --verbose --norc</code> работала бы нормально, а это не так.</p>
<p>Пришлось разбираться более плотно. В <code>bash (1)</code> я вычитал следующее (выделение — моё):</p>
<blockquote><p>If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the  program.  The shell executes the specified interpreter on operating systems that do not handle this  executable format themselves.  The arguments to the interpreter consist of a  <b>single</b><b>  optional  argument  following  the  interpreter  name on the first line of the program, followed by the name of the program, followed by the command arguments, if any.</b></p></blockquote>
<p>Т.е. в shebang можно задавать только один аргумент; кроме того, bash самостоятельно анализирует shebang и вызывает указанный интерпретатор только в случае, если система сама не может выполнить этот скрипт.</p>
<p>Сам файл передаётся на выполнение с помощью системного вызова <code>execve (2)</code> (это я вычитал в файле <code>execute_cmd.c</code> в исходном коде bash), в man-странице которого и разъясняется политика партии по поводу разбиения аргументов интерпретатора:</p>
<blockquote><p>On Linux, the entire string following the interpreter name is passed as a single argument  to  the  interpreter, and this string can include white space.</p></blockquote>
<p>Таким образом, в самом первом примере у bash в argv оказывается  не два аргумента <code>--verbose</code> и <code>--norc</code>, а  один <code>--verbose --norc</code>, что и приводит к ошибке, и вина bash лишь в том, что он не разбивает свои аргументы на части, как это делает, например, Perl.</p>
<p>Причина такого странного поведения операционной системы (казалось бы, что сложного в том, чтобы просто разбить строку на части по пробелам или символам табуляции) описана, например, <a href="http://lkml.indiana.edu/hypermail/linux/kernel/0812.0/02503.html">в этой дискуссии LKML</a> или, более подробно, в <a href="http://unix.derkeiler.com/Mailing-Lists/FreeBSD/arch/2005-02/0039.html">письме Garance A Drosihn</a> в рассылку freebsd-arch. Вкратце, если бы механизм механизм обработки shebang (в Linux — <a href="http://lxr.linux.no/#linux+v2.6.32/fs/binfmt_script.c">linux/fs/binfmt_script.c</a>) передавал все аргументы интерпретатору, то для некоторых из них было бы затруднительно отделить аругменты интерпретатора от собственно аргументов  вызываемого скрипта. По крайней мере, так было еще на заре развития Unix и с тех пор <a href="http://www.in-ulm.de/~mascheck/various/shebang/#results">большая часть Unix-систем</a> передаёт все аргументы как единую строку.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/12/28/shebang-args.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Как распаковать vmlinuz и вытащить оттуда версию компилятора</title>
		<link>http://bappoy.pp.ru/2008/09/05/extracting-vmlinux.html</link>
		<comments>http://bappoy.pp.ru/2008/09/05/extracting-vmlinux.html#comments</comments>
		<pubDate>Fri, 05 Sep 2008 08:00:54 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[kernel]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=294</guid>
		<description><![CDATA[<p>Иногда бывает необходимо узнать полную версию ядра Linux, не имея возможности или желания грузиться с него. Например, сегодня мне нужно было перекомпилировать ядро с незначительными изменениями в .config и самым тщательным образом убедиться, что новый vmlinuz ничем не отличается от старого. Один из ключевых моментов &#8212; это строчка vermagic, которая должна совпадать у ядра и загружаемых модулей. Эта строчка выводится в начале загрузки ядра, например:</p>
<pre>Linux version 2.6.24-19-generic (buildd@terranova) (gcc version 4.2.3 (Ubuntu 4.2.3-2ubuntu7)) #1 SMP Fri Jul 11 23:41:49 UTC 2008 (Ubuntu 2.6.24-19.36-generic)</pre>
<p>Интересующихся смыслом vermagic отправляю к <a href="http://www.opennet.ru/docs/RUS/lkmpg26/#BUILDINGMODULESFORAPRECOMPILEDKERNEL">главе 2.8</a> <a href="http://www.opennet.ru/docs/RUS/lkmpg26/">The Linux Kernel Module Programming Guide</a> и описанию опции <code>--force-vermagic</code> в <code>man modprobe.</p>
<p>Vermagic незагруженного модуля, находящегося в текущем каталоге, можно узнать по команде </code><code>modinfo ./module_name.ko</code> (работает, даже если модуль собран для другой архитектуры, например, если мы работаем в i386, а модуль &#8212; для x86_64, и наоборот). С ядром такой фокус не пройдет: во-первых, ядро, как правило, находится в сжатом виде, а исходники ядра не всегда доступны; во-вторых, сжатое ядро представляет собой загрузчик и распаковщик, за которым следует собственно сжатый алгоритмом zlib vmlinux (вопреки распространенному мнению, bzImage &#8212; это не ядро, сжатое bzip&#8217;ом, а сжатое ядро, которое можно загружать в несвязанные между собой области памяти), и необходимо отделить сжатое ядро от загрузчика.</p>
<p><a href="http://www.codeguru.com/forum/archive/index.php/t-415186.html">Решение</a> нашлось на форуме <a href="http://codeguru.com">CodeGuru</a>.</p>
<p>Заголовок gzip начинается с байт <code>1f 8b 08 00</code>, их и будем искать. По ссылке выше рекомендуют использовать команду <code>od -A d -t x1 vmlinuz|grep "1f 8b 08 00"</code>, и в некоторых случаях это действительно помогает, однако, во-первых, остаётся много трудноалгоритмизируемой ручной работы (необходимо отсчитать количество байт от смещения первого байта в строке до начала собственно заголовка gzip); во-вторых, две части искомого фрагмента могут находиться в разных строках, как, например, в текущей версии generic-ядра Ubuntu: </p>
<blockquote><pre><font color="#808080"><em>0011376</em> 00 fd f3 a4 fc 5e 81 c5 ff ff 0f 00 81 e5 00 00</font>
<em>0011392</em> f0 ff 8d 83 90 01 1d 00 ff e0 01 01 1d 00 <b>1f 8b</b>
<em>0011408</em> <b>08 00</b> 26 a1 ac 48 02 03 ec 3a 6d 74 14 55 96 af
<font color="#808080"><em>0011424</em> 3b d5 49 77 e8 58 15 a7 5b 5b b6 19 1a 2d 30 19</font></pre>
</blockquote>
<p>В данном случае, чтобы вычислить актуальное смещение заголовка gzip, необходимо к смещению первого байта в строке (11392) прибавить еще 14 байт. Поэтому мы пойдём немного другим путём.</p>
<p>Как я уже писал <a href="http://bappoy.pp.ru/2008/03/28/advice-country.html">ранее</a>, в состав исходников ядра Linux входит программа <code>binoffset</code>, с помощью которой можно находить сколь угодно длинные последовательности байт в бинарном файле. Ей и воспользуемся, благо она присутсвует также и в пакете linux-headers в Ubuntu:</p>
<pre><strong>$ gcc -o binoffset /usr/src/linux/scripts/binoffset.c</strong>
<strong>$ /binoffset /vmlinuz 0x1f 0x8b 0x08 00 2>/dev/null</strong>
11406</pre>
<p>Теперь &laquo;вытащим&raquo; из vmlinuz сжатое ядро и распакуем его:</p>
<pre><strong>$ dd if=/vmlinuz skip=11406 bs=1|gzip -d &gt;vmlinux</strong></pre>
<p>В vmlinux уже можно искать нужные строки:</p>
<pre><strong>$ strings vmlinux |grep gcc</strong>
Linux version 2.6.24-19-generic (buildd@terranova) (gcc version 4.2.3 (Ubuntu 4.2.3-2ubuntu7)) #1 SMP Wed Aug 20 22:56:21 UTC 2008 (Ubuntu 2.6.24-19.41-generic)
%s version %s (buildd@terranova) (gcc version 4.2.3 (Ubuntu 4.2.3-2ubuntu7)) %s
</pre>
<p>Как видно, получили почти то, что нам нужно. Теперь сократим все вышенаписанное в одну строчку:</p>
<pre>(dd if=/vmlinuz skip=`./binoffset /vmlinuz 0x1f 0x8b 0x08 0x00` bs=1|gzip -d |strings|grep &quot;^Linux version&quot;) 2&gt;/dev/null</pre>
<p>Оптимизацию и рефакторинг этой команды оставляю в качестве самостоятельной работы для читателей.</p>
<p>P.S. Примерно то же самое делает скрипт <code>/usr/src/linux/scripts/extract-ikconfig</code>, только нужно слегка его модифицировать, чтобы он выдавал не конфиг, а распакованное ядро, но мне было интересно изобрести очередной велосписед и разобраться самостоятельно :-)</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2008/09/05/extracting-vmlinux.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Страна советов</title>
		<link>http://bappoy.pp.ru/2008/03/28/advice-country.html</link>
		<comments>http://bappoy.pp.ru/2008/03/28/advice-country.html#comments</comments>
		<pubDate>Thu, 27 Mar 2008 21:21:33 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[mc]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/2008/03/28/advice/</guid>
		<description><![CDATA[<p>Иногда при работе в midnight commander появляется сообщение &laquo;The shell is already running the command&raquo;, не дающее выполнить команду в текущем каталоге. Стандартный способ обхода &#8212; Ctrl+O, Ctrl+C, Enter приводит к тому, что mc возвращается в каталог, где была выполнена предыдущая команда, и приходится еще раз переходить в нужный каталог. Проблема обсуждается чуть ли не с самого первого релиза mc, но по каким-то причинам принципиально не может быть решена.</p>
<p>В этом случае помогает выполнение команды &laquo;cd -&raquo; (после Ctrl+O, Ctrl+C, Enter, Ctrl+O), которая меняет каталог на предыдущий (т.е. в котором мы находились до первого Ctrl+O).</p>
<hr />В случае, если при сборке ядра была включена опция &laquo;Kernel .config support&raquo; (CONFIG_IKCONFIG), файл ядрёной конфигурации .config добавляется в бинарник ядра в гзипованном виде. А если дополнительно отметить еще и &laquo;Enable access to .config through /proc/config.gz&raquo; (CONFIG_IKCONFIG_PROC), то этот конфиг доступен через /proc/config.gz.Иногда хочется посмотреть, чем одно ядро отличается от другого в плане конфигурации, но перезагружаться или городить виртуальную машину ради того, чтобы посмотреть /proc/config.gz, не хочется. В таком случае помогут два скрипта, входящих в состав архива с исходными текстами ядра. Первый из них, служебный, называется binoffset и предназначен для определения смещения бинарного фрагмента от начала файла. Второй называется extract-ikconfig и служит непосредственно для поиска и извлечения из бинарника ядра гзипованного конфига. Перед запуском необходимо скомпилировать binoffset:</p>
<blockquote>
<pre lang="bash">cd /usr/src/linux/scripts
gcc -o binoffset binoffset.c</pre>
</blockquote>
<p>После чего можно натравливать extract-iconfig на ядро:</p>
<blockquote>
<pre lang="bash">scripts/extract-ikconfig /path/to/bzImage</pre>
</blockquote>
<hr />Регулярное чтение избранных частей из man bash просветляет и приносит несомненную пользу. Недавно поразил коллегу генератором паролей на основе <code>/usr/share/dict/words</code>:</p>
<blockquote>
<pre lang="bash">#!/bin/bash
passwords_count=3
test $1 &#038;&#038; echo $1 | grep -q ^[0-9]*$ &#038;&#038; passwords_count=$1

words=/usr/share/dict/words
words_count=3
symbols=("," "*" "-" "(" ")" "_" '"' ',' ',')

# prepare words array
declare -a allwords
exec 10< $words
while read LINE <&#038;10; do
    allwords[${#allwords[*]}]=$LINE
done

nwords=${#allwords[@]}

for ((k=0;$k<$passwords_count;k++));
do
    declare -a words_array
    for w in `seq 0 $words_count`; do
        words_array[${#words_array[*]}]=${allwords[$(($nwords*$RANDOM/32767))]}
    done

    passwd=${words_array[0]}
    for ((c=1;$c<${#words_array[@]}-1;c++));
    do
        symbol=${symbols[(($RANDOM*${#symbols[*]}/32767))]}
        passwd="${passwd}${symbol}${words_array[$c]}"
    done
    echo $passwd
    unset passwd
    unset words_array
done</pre>
</pre>
</blockquote>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2008/03/28/advice-country.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Linux kernel: построение списка совместимости устройств для своего ядра</title>
		<link>http://bappoy.pp.ru/2008/01/30/linux-building-hcl.html</link>
		<comments>http://bappoy.pp.ru/2008/01/30/linux-building-hcl.html#comments</comments>
		<pubDate>Wed, 30 Jan 2008 17:48:51 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[kernel]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/2008/01/30/linux-building-hcl/</guid>
		<description><![CDATA[<p>В <a href="http://bappoy.pp.ru/2008/01/29/linux-hw-compat/"> предыдущей заметке</a> был рассмотрен способ ручного определения совместимости драйвера с железом. Однако в случае, когда необходимо получить список полный всех устройств, с которым может работать наше многажды пропатченное и перекроенное ядро, лазить руками по каждому драйверу и смотреть, какие PCI и USB ids в него зашиты, очень неудобно.</p>
<p>На наше счастье, кое-кто (итальянец Giacomo Catenazzi) уже озаботился этой проблемой и в какой-то степени её решил. Встречайте: <a href="http://cateee.net/lkddb/index.html">Linux Kernel Driver Database (LKDDb)</a>. Основная цель этого проекта, цитирую: &laquo;попытка построения понятной пользователю базы данных устройств и протоколов, известных ядру linux. База данных включает в себя цифровые идентификаторы железа, опции конфигурации ядра, необходимые для включения модуля в ядро, и названия модулей, получающихся на выходе. База составляется на основе исходников ядра и поэтому всегда актуальна&raquo;</p>
<p>На сайте представлен <a href="http://cateee.net/lkddb/web-lkddb/">пример</a> того, что получается в результате работы этого скрипта. Для каждой опции ядра указывается, поддержка каких PCI IDs добавляется в систему с включением этой опции, как называется результирующий модуль и от какой опции зависит. Например, <a href="http://cateee.net/lkddb/web-lkddb/SATA_NV.html">вот</a> страница, посвящённая упоминавшемуся в прошлой заметке драйверу sata_nv.</p>
<p>Но нас в первую очередь интересует собственно база данных, lkddb.list &#8211; текстовый файл относительно простого для парсинга <a href="http://cateee.net/lkddb/format.html">формата</a>, на основе которого и строится работа программы. Разобраться в формате не составляет никакого труда. Приведу лишь пример записей для неоднократно здесь упоминавшегося драйвера sata_nv:</p>
<blockquote><p><code>lkddb   module  libata  "NVIDIA SATA support"   :: CONFIG_SCSI_SATA_NV  :: drivers/scsi/Kconfig<br />
lkddb   module  sata_nv "NVIDIA SATA support"   :: CONFIG_SCSI_SATA_NV  :: drivers/scsi/Kconfig<br />
lkddb   pci     10de .... .... .... 0101..      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de .... .... .... 0104..      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 0036 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 003e .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 0054 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 0055 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 008e .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 00e3 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 00ee .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 0266 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 0267 .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 037e .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c<br />
lkddb   pci     10de 037f .... .... ......      :: CONFIG_SCSI_SATA_NV CONFIG_SCSI      :: drivers/scsi/sata_nv.c</code></p></blockquote>
<p>Все строки в этом файле начинаются с lkddb; далее следует тип записи: <code>pci</code>, <code>usb</code>, <code>ieee1394</code>, <code>eisa</code>, <code>pcmcia</code> и т.д. для устройств, <code>i2c</code>, <code>platform</code>, <code>fs</code> или <code>module</code> для различной информации, связанной с самим ядром. Далее для pci-устройств идут device id, vendor id, device class; затем, через разделитель &laquo;::&raquo;, опция ядра, которую нужно включить для того, чтобы данный модуль скомпилировался, а также опции, от которой зависит данная опция; и, наконец, файл, в котором был найден данный pci id.</p>
<p><code>lkddb.list</code> может быть сгенерирован с помощью <a href="http://cateee.net/sources/lkddb-sources/">генератора</a>, который, собственно, и является ядром программы. Нужно скачать последнюю версию, распаковать, указать в Makefile путь к исходникам своего ядра; для экономии 500 килобайт трафика можно в этот же каталог скопировать из<code> /usr/share/hwdata</code> файлы <code>pci.ids</code> и <code>usb.ids</code>, после чего выполнить команду make <strike>откинуться на спинку кресла</strike> и подождать две-три минуты, пока парсятся немаленькие исходники и генерируется БД. Возможно, потребуется еще кое-что подпилить напильником, в зависимости от ситуации.</p>
<p>После дюжины экранов отладочных сообщений будет создан нужный нам файл <code>lkddb.list</code> и, в качестве бонуса, около 35 мегабайт описаний модулей в формате HTML в папке <code>web-lkddb</code>. До создания HCL остаётся полтора шага, не составляющих проблемы для знакомых с основами shell-программирования &#8212; из конфигурационного файла ядра нужно извлечь список всех включённых опций и для каждой скопировать информацию из <code>lkddb.list</code>, попутно преобразовав PCI ID устройства (в процессе работы скриптов преобразованного в более читаемую форму) к человекочитаемому виду.</p>
<p><a href="http://feeds.feedburner.com/bappoy" target="_blank">Следите за обновлениями :)</a></p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2008/01/30/linux-building-hcl.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

