18 ноября, 2008

vi основные команды

vi основные команды

Оригинал: .pdf .odt

Перевод: .pdf .odt


Условия распространения Creative Commons Attribution-ShareAlike 2.5 license
©Copyright 2006-2005, Free Electrons.

16 ноября, 2008

Как пропатчить Linux - Linux patch

Делается это очень просто. Допустим, Вы уже имеете исходники ядра, скачанные с kernel.org. Теперь будем накладывать патч на ядро.

Определите нужную версию ядра и патча с помощью браузера на kernel.org.
http://kernel.org/pub/linux/kernel/v2.6/patch­2.6.27.bz2 (с 2.6.26 на 2.6.27)
http://kernel.org/pub/linux/kernel/v2.6/patch­2.6.27.6.bz2 (с 2.6.27 на 2.6.27.6)

Далее скачиваем патч, сверяем подпись:
wget http://kernel.org/pub/linux/kernel/v2.6/patch-­2.6.27.6.bz2
wget http://kernel.org/pub/linux/kernel/v2.6/patch-­2.6.27.6.bz2.sign
gpg ­­--verify patch-­2.6.27.6.bz2.sign

Накладываем патч:
bzcat patch­-2.6.27.6.bz2 | patch ­p1

Патч наложен.
Откатить патч можно с помощью patch с параметром -R.
Файл patch-2.6.27.6 - это вывод комманды diff. Вот так он выглядит:

diff --git a/Makefile b/Makefile
index 16e3fbb..1ea4453 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@ <-номера строк в файле
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 27
-EXTRAVERSION = <- удаленная строку
-NAME = Rotary Wombat <- удаленная строка
+EXTRAVERSION = .6 <- добавленная строка
+NAME = Trembling Tortoise <- добавленная строка

# *DOCUMENTATION*

Спасибо.

15 ноября, 2008

Crosstool - сборка и тестирование Toolchains

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

Сборка кросс-toolchain'а gcc/glibc для встраеваемых систем есть пэйнфул процесс. Программа (набор скриптов) Crosstool, написанная Dan Kegel, поможет найти рабочие комбинации различных версий gcc, glibc, binutils и заголовочных файлов ядра(см. рисунок выше).
  • Домашняя страница проекта: http://kegel.com/crosstool/
  • Также смотреть: uClibc chaintools http://free-electrons.com/community/tools/uclibc
  • Have fun! http://www.aleph1.co.uk/armlinux/docs/toolchain/toolchHOWTO.pdf

Под ARM:
  • http://www.codesourcery.com/gnu_toolchains/arm/
  • ftp://ftp.handhelds.org/projects/toolchain/
Под MIPS:
  • http://www.linux-mips.org/wiki/Toolchains

Tools list:

  • Crosstool­-ng
  • Buildroot
  • Scratchbox
  • OpenEmbedded
  • PTXdist
  • LTIB
  • Home made tools
  • Firmware Linux
  • Gentoo embedded
  • ELDK
  • другие? коммент.


Спасибо.

02 ноября, 2008

Архитектура ядра UNIX


На диаграмме ниже показаны различные модули ядра и их свзяи. Два главных компонента ядра: файловая подсистема (file subsystem) и подсистема управления процессами (process control subsystem). Также здесь видно три уровня: user, kernel и hardware levels. Интерфейс системных вызовов (system call interface) и библиотеки(libraries) разделяют пользовательский уровень и уровень ядра. Системные вызовы обычно представлены в виде вызовов функций в С программах, библиотеки собирают эти вызовы в примитивы, необходимые для работы ОС.



Блочная диаграмма ядра UNIX

Файловая подсистема управляет файлами, выделяет место под них, управляет свободным пространством, контролирует доступ к файлам, получает данные для пользователей. Процессы взаимодействуют с файловой подсистемой через специфический набор системных вызовов:

  • open открывает файл для чтения и записи
  • close
  • read
  • write
  • stat запрашивает атрибуты файла
  • chown изменяет запись о том, кто владеет файлом
  • chmod управляет доступов к файлу

Файловая подсистема получает доступ к файлам, используя механизм буферизации (buffering mechanism), который устанавливает канал между ядром (kernel) и устройством хранения (storage device). Механизм буферизации взаимодействует с драйвером устройства блочного ввода/вывода (block I/O device) для того, чтобы инициировать перемещение данных в/из ядра. Драйвер устройства - это модуль ядра, который контролирует работу периферийных устройств.
Файловая подсистема также может напрямую взаимодействовать с "сырыми" ("raw") драйверами ввода/вывода без привлечения механизма буферизации. Raw устройства также называют символьными (character). Это все устройства, которые нельзя отнести к блочным.


Подсистема управления процессами


Подсистема управления процессами отвечает за синхронизацию процессов (process synchronization), межпроцессорное взаимодействие (interprocess communication), управление памятью (memory managment) и планировкой процессов (process sheduling). Файловая подсистема и подсистема управления процессами взаимодействуют при загрузке файла в память для его запуска (подсистема процессов прочитывает исполняемый файл в память перед его исполнения).
Некоторые системные вызовы для управления процессами:

  • fork создает новый процесс
  • exec накладывает образ программы на текущий процесс
  • exit заканчивает запущенный процесс
  • wait синхронизирует исполнение процесса с exit предыдущего fork-нутого процесса
  • brk контролирует размер выделенной на процесс памяти
  • signal управляет откликом процесса на экстраординарные события


Модуль управления памятью (memory managment module) управляет выделением памяти. Если системе не хватает физической памяти для всех процессов, ядро перемещает их между основной и вторичной памятью, и так все процессы имеют возможность быть запущенными.

Планировщик (sheduler) выделяет CPU под процессы. Он распределяет запуск процессов пока они добровольно (произвольно) не освободят CPU на/во время ожидания ресурса, либо пока ядро не выгрузит их по истечении кванта времени. После планировщик выбирает процесс с наибольщим приоритетов для его запуска; первичный процесс будет запущен опять тогда, когда он будет являться процессом с наивысшим приоритетом.
Существует несколько видов межпроцессорного взаимодействия, начиная с асинхронной передачи событий (asynchronous signaling of events), заканчивая синхронной передачей сообщений между процессами.


Управление аппаратным обеспечением


И наконец, управление аппаратным обеспечением (hardware control) ответственно за обработку прерываний (handling interrupts) и общения с машиной. Такие устройства как диски или терминалы могут прерывать CPU во время выполнения процесса. В таком случае ядро может продолжить исполнение прерванного процесса после обслуживания прерывания. Прерывания не обслуживаются специальными процессами, а специальными функциями ядра, вызываемыми в контексте текущего запущенного процесса.


Литература:

  • The Design Of the Unix Operating System by Maurice J. Bach, 1986


04 августа, 2008

uClinux - инструменты сборки


Итак, Вы теперь имеете систему разработки uClinux. Вкратце об <установке>

  • набор программ разработки uClinux должен быть установлен в /opt/uClinux

  • m68k-coff использовался для компиляции ядра. Он не связан со стандартной С библиотекой uC-libc.

  • ядро uClinux установленно в /opt/uClinux/linux

  • m68k-pic-coff - это PIC компилятор, который использовался для сборки бинарников пользовательского пространства.

  • стандартная С библиотека uC-libc должна быть скомпилирована как libc.a и crt0.o и скопирована в /opt/uClinux/m68k-pic-coff/lib, а их include файлы в /opt/uClinux/m68k-pic-coff/include

  • стандартная математическая библиотека uC-libm дложна быть скомпилирована как libm.a и math.h, включенные в /opt/uClinux/m68k-pic-coff/lib и /opt/uClinux/m68k-pic-coff/include соответственно.

  • m68k-pic-coffs’ LD заменен скриптом, который вызывает линковщик LD, затем COFF2FLT создает плоский бинарный модуль (Flat Binary Image) из coff файла

  • утилита genromfs должна быть собрана и установлена, и добавлена в path

  • Romdisk извлечен в /opt/uClinux/romdisk

  • коды пользовательского пространства uClinux установлены в /opt/uClinux/src

  • скрипт deftemplate.sh должен быть помещен в /opt/uClinux/

  • скрипт buildenv.sh должен быть помещен в /opt/uClinux/bin/ и добавлен в path



Есть две области разработки: средства ядра uClinux и средства пользовательского пространства. Так как ядро представлено для множества платформ, основным местом разработки будет пользовательское пространство. Как бы там ни было, ядро uClinux должно быть установлено первым.

Сборка ядра uClinux



Ядро должно быть сконфигурировано перед сборкой. Для тех, кто конфигурировал ядро для настольных ПК, эта процедура будет знакома, кроме конечно того, что uClinux не поддерживает загружаемые модули. Для других это будет испытанием.
Для начала перейдите в /opt/uClinux/linux и запустите конфигурационную утилиту

cd /opt/uClinux/linux
make menuconfig

Время конфигурации ядра. Так как Вы будете ссылаться на различные архитектуры и платформы, здесь нет особо выбора. Выберите Ваш процессор и плату из Platform Dependent Setup, и пропустите конфигурацию дополнительных параметров.

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

make dep
make clean
make linux.bin

Make dep говорит make об установке зависимостей. Clean очистит все старые компоненты предыдущих сборок, а linux.bin соберет образ linux.bin, что является ядром в чистом бинарном виде.

По завершении Вы должны иметь парочку файлов в директории linux (/opt/uClinux/linux). Это будут linux.text, linux.data, linux.bin и карта системы (system map).

Процедура сборки ядра



Сбоорка ядра начнется со сборки отдельных компонентов/подсистем ядра. Как только это будет сделано, все объектные файлы подсистемы будут связаны (linked) используя секцию компоновочного файла (.LD), который будет находится в arch/$(ARCH)/platform/$(PLATFORM)/$(BOARD)/$(MODEL).ld, и запускать C asm код (crt0_rom.S) для создания файла linux.

LD -T (MODEL).ld crt0_$(MODEL).o [objs] -o linux

Компоновщик определяет секцию памяти, он сообщает компилятору сколько памяти доступно и где разместить разные куски кода. Загрузочный asm код - это код, который запускается прямо после reset vector или загрузчика (bootloader), который поднимает различные части микроконтроллера, такие как clock dividers, serial port, DRAM, SRAM, memory banks, watchdogs и т.д., которые должны быть установлены перед тем как микроконтроллер сможет запустить ядро linux. Также он поднимает стэк, обнуляет .bss сегмент, копирует .data сегмент в RAM и переходит к start_kernel() который является входной точкой в C Код.

Символьная/системная карта (symbol/system map) генерируется из файла linux. Это удобно для показа отладки, где каждая функция размещена в памяти.

NM $(LINUX) | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map

Linux.data, файл содержащий весь код сегмента данных, создан linux, удаляя все сегменты только-для-чтения и другие ненужные сегменты.

objcopy -O binary --remove-section=.romvec --remove-section=.text \
--remove-section=.ramvec --remove-section=.bss \
--remove-section=.eram linux linux.data

Файл Linux.text также содержит весь text segment код (fixed code и переменные/строки)

objcopy -O binary --remove-section=.ramvec --remove-section=.bss \
--remove-section=.data --remove-section=.eram \
--set-section-flags=.romvec=CONTENTS,ALLOC,LOAD,READONLY,CODE linux linux.text

Сегменты .Text и .Data конкатенируются для синтеза linux.bin

cat linux.text linux.data > linux.bin

Мы закончили с linux.bin, что является бинарным кодом ядра. Теперь он может быть загружен в память и запущен. Однако будет сбой после попытки распаковки ROM filesystem и монтирования нодов устройства (device nodes), содержащихся внутри romfs.

Сборка ядра потребуется единожды до приминения каких-либо модификаций ядра. На каждой сборке системы romfs будет конкатенироваться с linux.bin.

ФС постоянной памяти (ROM filesystem)



Так как есть одна общая исходая директория для ядра linux, Вы можете сложить проекты ФСы rom и бинарников пространства пользователя. Вы можете иметь одно общее ядро на главном сервере, но иметь множество разработчиков, работающих над одной системой и использующих их собственные rom ФС.

Для установки рабочей среды всего лишь нужно создать директорию в подходящем месте, обычно /home/<username>/ для многопользовательской системы и запустить buildenv

cd /home/cpeacock/
mkdir ucsimm
buildenv

buildenv соберет среду разработки uClinux, создавая вначале Makefile в Вашей директории. Теперь если Вы наберете make, среда разработки будет скопирована из директории /opt/uClinux/, и создастся файл image.bin.

make

Теперь директория должна иметь такую структуру

Makefile deftemplate.sh image.bin linux romdisk romdisk.img romdisk.map src

Эта среда содержит бинарники пользовательского пространства в ФС ROM, которая монтирована ядром во время заргузки. Каждый исполняемый файл описанный в /src/makefile скомпилирован и его плоский бинарнкик помещен в /src/bin. Файл deftemplate.sh запущен для копирования конкретных бинарников в дерево виртуального диска постоянной памяти (romdisk), который будет представлять базу нашего romfs образа. Заметим, что скрипт deftemplate только копирует бинаркники в дерево romdisk. Он не удаляет их(бинарники), поэтому чтобы сделать это Вы должны раскамментировать соответствующую строку в скрипте deftemplate и вручную удалить файл из дерева rom диска.

Дерево rom диска также включает конфигурационные файлы и структуру директорий ФС rom

/bin /dev /etc /htdocs /lib /proc ramfs.img /sbin /tmp /usr /var

ФС romdisk.img автоматически генерируется из дерева используя

genromfs -v -V "ROM Disk" -f romdisk.img -d romdisk 2> romdisk.map

romdisk.img затем конкатенируется с /linux/linux.bin (бинарник ядра мы собирали ранее) для создания

cat linux/linux.bin romdisk.img > image.bin

image.bin - файл, который содержит ядро linux плюс ROM FS. Этот образ укомплектован и готов для закачки в Вашу uClinux Систему. Для лучшего представления процесса сборки, типичная карта памяти 2.0.38 uCsimm показана на рисунке ниже.



Память загрузчика (bootloader flash) уже присутствует в системе разработки, которую мы используем (в нашем случае uCsimm). Это модуль dragonball от Lineo. Сегменты ROM Vectors, .TEXT и .DATA созданы как часть компиляции ядра. Эти три секции составляют файл linux.bin, который может быть найдет в /opt/uClinux/linux.

Бинарники скомпилированы как плоские исполняемые и помещены в директорию rom диска. Затем Genromfs пакует это в romfs.img, который конкатенирован с linux.bin для предоставления файла image.bin. Это повысит или понизит размер, в зависимости от того какие файлы Вы включили в ФС ROM. Единственное ограничение накладывается на максимальное пространство вашей системы.

image.bin - это бинарный файл, который загружается в систему разработки через загрузчик (bootloader).

Настройка romfs



В настоящий момент мы собрали достаточно для загрузки image.bin и благополучно зарегистрировались в целевую систему uClinux. Однако мы используем стандартный IP адрес и другие параметры прямо из коробки.

Войдите в директорию с Вашим диском rom (romdisk). Вы должны иметь структуру, похожую на эту:

/bin /dev /etc /htdocs /lib /proc ramfs.img /sbin /tmp /usr /var

Как в любой системе linux, критические конфигурационные файлы могут быть найдены в /etc

inetd.conf inittab issue passwd rc resolv.conf services

Стандартный rc файл выглядит так:

#!/bin/sh
#
# system startup.

# set up the hostname
/bin/hostname uCsimm

# attach the interfaces
/sbin/ifattach
/sbin/ifattach \
--addr 192.168.1.200 \
--mask 255.255.255.0 \
--net 192.168.1.0 \
--gw 192.168.1.100 eth0

# expand the ramdisk
/sbin/expand /ramfs.img /dev/ram0

# mount ramdisk, proc and nfs
/bin/mount -t ext2 /dev/ram0 /var
/bin/mount -t proc proc /proc
/bin/mount -t nfs 192.168.1.11:/home/jeff/kit /usr

# start up the internet superserver
/sbin/inetd &

# that's it... success
exit 0

Вам нужно будет изменить имя хоста (hostname), IP адрес, маску, сетевые параметры и параметры шлюза. Также нужно изменить монтирование nfs, /bin/mount -t nfs 192.168.1.11:/home/jeff/kit /usr

Монтирование NFS тома для Разработки



NFS или Network File System - это путь экспортирования и монтирования директорий в UNIX системах. Это может быть очень удобно во время разработки, позволяя легко выводить Вашу рабочую директорию на uClinux платформу. Это дает возможность компилировать код в linux системе и запускать его на сетевом диске embedded системы без копирования flat бинарников или прошивки новой ROMFS. Можете представить себе какое огромное количество времени Вы экономите.

С утилитой флэш-загзузки/сетевой загрузки для целевой платформы Вы можете производить обновления флэша через кабель. Это также ускорит разработку. Пересылка 1MB image.bin файла через 115,200 serial link не так быстро.

Перед использованием NFS потребуется установить песочницу для разработки, чтобы извлечь нужные Вам директории. Рекомендуется провести некоторое время без внешнего подключения к интернет. NFS exports определены в файле /etc/exports. Надо редактировать от рута.

Типичная запись вывода имеет такой вид

/home (ro)

Это выведет домашнии директории (home) для всех с правами только чтение. Если Вы имеете чувствительную информацию в домашней директории, Вы можете явно указать на среду разработки или уточнить, какие машины имеют доступ к директории вывода, а именно:

/home/cpeacock/ucsimm uCSimm(ro)

где uCsimm - имя хоста uClinux системы. Оно должно быть включено в /etc/hosts, или же должен быть указан явный IP адрес.

После замены директории вывода нужно перезагрузить компьютер (windows way :) ) или перезапустить NFS демоны. Вот так:

/etc/rc.d/init.d/nfs stop
/etc/rc.d/init.d/nfs start

(на многих linux системах)

Как только это сделано, модифицирйуте файл rc и включите сюда данные о монтировании, в моем случае

mount -t nfs 192.168.0.1:/home/cpeacock/ucsimm /usr

Вы также можете зарегистрироваться в вашу uClinux систему и запустить это в коммандной строке. Это удобно после того, как uClinux система приведена в порядок, и теперь нужно быстро сделать некоторые вещи или reimage.

ФС оперативной памяти (RAM FileSystem)



uClinux имеет RAM ФС (ramdisk) для временных областей /tmp и /var в отсутствии жесткого диска (hard disk drive, HDD). romdisk текущиего дистрибутива uClinux идет с ramfs на 256кбайт. /tmp в корне - это символическая ссылка на /var/tmp. var - это точка монтирования RAM ФС.

ramfs распакована и монтирована через скрипт запуска rc,

# expand the ramdisk
/sbin/expand /ramfs.img /dev/ram0

# mount ramdisk, proc and nfs
/bin/mount -t ext2 /dev/ram0 /var

Она содержит ext2 ФС, которая сжата при помощи алгоритма Zero Run Length Encoding (ZRTE). Она распаковывается при помощи утилиты распаковки в блочное RAM устройство /dev/ram0. Как только этот процесс завершен, она монтирована как ext2 ФС с точкой монтирования /var.

Если нужно исправить ссылку на tmp, мы можем просто добавить команду в rc скрипте для создания директории tmp в var после монтирования ramfs. Как бы то ни было, увеличить размер ramdisk будет не так легко. Для этого нужно создать новый ramfs.img. Для некоторых приложений даже необходим больший размер ramdisk. Вы возможно захотите журналировать данные в файл, который затем будет скачан, используя анонимный FTP, HTTP, или другое.

Создаем новую ramfs



Создание новой ramfs - достаточно простая задача. Одна проблема, на которую следует обратить внимание - это порядок следования байт в вашей системы (endianness).

Начнем с обнуления блочного устройства ram. Позже мы будем использовать утилиту сжатия в целях получения более сжатого образа. Вам также нужно выбрать размер диска ramdisk. Большой ramdisk позволит Вам записывать большие журналы и временные файлы, но с затратами на системной RAM. Это зависит от того, какие приложения Вы используете на uClinux системе.

# dd if=/dev/zero of=/dev/ram0 bs=1k count=1024
1024+0 records in
1024+0 records out

Далее сделаем ext2fs. Флаг -v включает вербальный режим, так что мы сможем увидеть некоторую статистику. По умолчанию 5% блоков зарезервировано для суперпользователя. Мы это выключим, используя -m0. Мы также отключим любые другие дополнительные возможности ФС ext2, используя -Onone. На пост 2.2 ядерных системах, опции sparse_super и filetype автоматически включены при создании ext2fs. Однако обе эти возможности некорректно поддерживаются ядром pre 2.2, и как результат mount сообщает о проблеме при монтировании ФС на системе 2.0.38 uClinux.

# mke2fs -vm0 -Onone /dev/ram0 1024
mke2fs 1.19, 13-Jul-2000 for EXT2 FS 0.5b, 95/08/09
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
128 inodes, 1024 blocks
0 blocks (0.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
128 inodes per group

Writing inode tables: done
Writing superblocks and filesystem accounting information: done

На следующем шаге мы добавим дополнительные папки и файлы к ramdisk. Это необязательная процедура, поэтому Вы можете ее пропустить. По умолчанию при создании ФС ext2 добавляется директория lost+found. Она появится в /var/lost+found. Также рекоммендуется создать папку tmp. Чтобы добавить файлы и папки, для начала монтируйте ФС как ext2.

# mount -t ext2 /dev/ram0 /mnt/ramdisk
# cd /mnt/ramdisk
# mkdir tmp

Как только Вы закончили, отмонтируйте ФС для обеспечения чистоты монтирования в будущем

# umount /mnt/ramdisk

Теперь время переместить ФС из блочного ram устройства в локальный файл. Копируем ФС байт-к-байту в ramfsraw.img. Для 1MB ramfs, этот файл будет размером в 1MB.

# dd if=/dev/ram of=ramfsraw.img bs=1k count=1024
1024+0 records in
1024+0 records out

Будет очень неэффективно добавлять файл размером 1Mb к romdisk в его текущей форме, и так как большая часть ФС свободна, мы можем очень эффективно сжать, используя ZRLE (Zero Run Length Encoding). Вы можете поискать документ, описывающий процесс “making a file with holes”.

ZRLE записывает блоки с ненулевыми данными, прибавляя к ним длину блока и ее позицию в файле. Так как в основном файл состоит из нулей, утилита обрезает их. Утилита распаковки просто обнулит всю длину распаковываемого файла, и затем скопирует блоки данных обратно в подходящие ячейки.

Сжатие может быть выполнено при помощи утилиты, называемой holes. Существует пара версий, в зависимости от порядка байт (endian) и/или размера блоков. Вы можете скачать исходные коды с ftp://ftp.beyondlogic.org/uClinux/ramfsutils.tar.gz и скомпилировать их. Эти бинарники запустятся на Linux платформе с обратным следованием байт (little endian platforms).

# /holes/holes ramfsraw.img >ramfs.img
Length of original file 1048576

Листинг двух файлов покажет длину сжатия. Теперь мы можем добавить его на наш romdisk, не затрачивая пространства.

# ls ram* -l
-rw-r--r-- 1 root root 2639 Mar 4 16:00 ramfs.img
-rw-r--r-- 1 root root 1048576 Mar 4 15:59 ramfsraw.img

Вы также можете заметить что сгенерированный ramfs.img меньше, чем uClinux ramfs.img (3340). Еще одна причина почему Вы должны обновлять и генерировать самостоятельно. (По некоторым причинам, размер блока run length на запасной ramfs не должна быть больше 200-300 байт даже если expand.c размещает буфер в 2048 байт при распаковке образа).

Тестируем RAM filesystem

Можно протестировать новую ramfs на Вашей uClinux платформе, сначала отмонтируя существующую ramfs, а затем распаковывая и монтируя новую ramfs.

/bin/umount /var
/sbin/expand /ramfs.img /dev/ram0
/bin/mount -t ext2 /dev/ram0 /var

Также Вы возможно захотите протестировать ее на Вашем настольном linux. Копирование файла expand.c из /src/init/ и перекомпиляция для x86 linux приведет к endianness проблеме. Исправьте define в ntohl(), или используйте прекомпилированный бинарник для x86 отсюда (ramfsutils.tar.gz).

Корневая ФС на NFS



Монтирование директории разработки uClinux в /usr поможет Вам ускорить процесс разработки. Это позволит разработчику компилировать бинарники m68k в linux системе и мгновенно иметь их через монтированный NFS том.

Может случится ситуация когда Вы захотите модифицировать другие файлы на FLASH, например, конфигурационные файлы /etc для инетрнет демонов, http web servers. One option is the flash and burn method - изменить файл, пересобрать образ, закачать образ в uClinux систему, задержать воздух и надеяться на то, что изменения верны.

Наиболее скоростной подход и, таким образом, лучший вариант решения проблемы заключается в монтировании корневой директории uClinux как NFS том, которая вытягивается с машины разработки. Это позволит модифицировать любой файл в ФС и иметь их быстродоступными на uClinux системе. Ясно, что это сохранит львинную долю времени.

Установка корневой ФС NFS заставляет немного подумать над ядром. Для начала редактируем файл setup.c в /arch/{arch}/kernel/ и добавляем следующие строки для установки деталей о NFS сервере и хосте в буффер командной строки ядра.

ROOT_DEV = MKDEV(BLKMEM_MAJOR,0);

+ #ifdef CONFIG_ROOT_NFS
+ strcpy(command_line,
+ "root=/dev/nfs "
+ "nfsroot=192.168.0.2:/ucsimm/romdisk "
+ "nfsaddrs=192.168.0.200:192.168.0.2:192.168.0.1:255.255.255.0:"
+ "ucsimm:eth0:none");
+ #endif

/* Keep a copy of command line */
*cmdline_p = &command_line[0];



memcpy(saved_command_line, command_line, sizeof(saved_command_line));

saved_command_line[sizeof(saved_command_line)-1] = 0;

Формат этих параметров

root=/dev/nfs

Используется для доступа к корню NFS. Это не настоящий том, а псевдо-NFS-том.

nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]

server-ip - это IP адрес NFS сервера, от которого Вы хотите монтировать ФС. Диретория root конкретизирует имя директории на NFS сервере для монтирования корня. Дальше идет запятая и другие страндартные параметры NFS. Парамерты необязательны. Дополнительные параметры могут быть найдены в файле nfsroot.txt как часть документации, которую Вы получаете с ядром.

nfsaddrs=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>

client IP - это IP адрес, который вы хотите присвоить embedded системе uClinux. Обычно присваивается ifattach в rc файле, но это не будет больше доступно локально, Вы должны предоставить эти подробности здесь. server-ip опять конкретизирует IP адрес NFS сервера - шлюз и маска должны быть self explanatory, hostname - это имя Вашей локальной машины, device указывает какой интерфейс устанавливать, тогда как autoconf указывает должны ли BOOTP либо rarp быть использованы.

Эти три параметра связаны вместе. Отделите пробелами каждую команду.

Как только изменения сделаны, и сохранены, начните конфигурировать ядро uClinux для поддержки корневой NFS. Опции можно найти в меню Filesystems - выбрать "NFS filesystem support" и "Root file system on NFS" обе. Затем пересобрать ядро. Как только ФС rom будет монтирована с сервера NFS, уже не нужно генерировать ROM ФС и конкатенировать ее с файлом linux.bin. Просто заргузите файл linux.bin как есть.

Убедитесь что директория, которую Вы указали в exported корректна и сбросьте uClinux. Если все пройдет успешно, загрузка должна быть похожа на

eth0: Attempting TP

eth0: using 10Base-T (RJ-45)

Root-NFS: Got file handle for /ucsimm/romdisk via RPC

VFS: Mounted root (nfs filesystem).

и дать пользователю зарегистироваться в системе как обычно. Если NFS сервер отсутствует, последует следующее сообщение (uClinux будет пытаться соединиться бесконечное количество раз, пока NFS сервер не появится в сети)

eth0: Attempting TP
eth0: using 10Base-T (RJ-45)
NFS server 192.168.0.2 not responding, still trying.

Вы также можете получить сообщение ниже, если exports некорректен или Вы пытаетесь получить директории с другого сервера. В этом случае проверьте файл exports и перезапустите NFS демон. После kernel panic Вам потребуется перезапустить uClinux перед попыткой соединиться снова.

eth0: Attempting TP
eth0: using 10Base-T (RJ-45)
Root-NFS: Server returned error 13 while mounting /ucsimm/romdisk
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device 02:00
Kernel panic: VFS: Unable to mount root fs on 02:00

31 июля, 2008

uClinux - установка среды программирования



Почему встраивать Linux?



Linux быстро набирает популярность как ОС для встраиваемых устройств
Вот несколько преимуществ такой ОС:
  • свободное от цены лицензирование
    Для традиционных встраиваемых платформ сумма на лицензии будет внушительная. Включенные в поставку устройств, сторонние ОС способствуют повышению цены на устройства. Linux же свободна.

  • надежный IP стэк и TCP/IP приложения
    Годами Linux может работать на серверах и рабочих станциях. Также Linux будет работать и на встаиваемых устройствах.

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

  • исходные коды средств разработки открыты
    Средства разработки - это набор необходимых пакетов программ для компиляции и генерации выполняемого кода из исходных текстов программ. Они также открыты.

  • время, необходимое на рынке
    В изобилии открытого исходного кода и приложений, нацеленных на Linux, вы заметите, что "время на рынок" сократилось. Возьмем в качестве примера продукты Memory Fax/Modem, которые появились на рынке несколько лет назад. Это факс/модемы со встроенной памятью, которые позволяют получать факсимильные сообщения, когда компьютер выключен. Для размещения такого продукта на рынок будет необходимой разумный объем работы. Вместе с uClinux, разработчик может основывать свои продукты на продуктах с открытым исходным кодом, таких как efax. Она также позволяет включать IP маскарад (с небольшими усилиями), тем самым добавив больше функциональности продукту. Linux также поддерживает широкий спектр периферийных устройств и файловых систем.


Вдобавок, имеется множество целевых платформ и со временем их количество возрастает. Сейчас uClinux поддерживает серию 68328 dragonball, Coldfire, ARM7TDMI, ETRAX, I960.

Дистрибутив uClinux

uClinux - самая распространенная форма встаиваемого linux. uClinux (MicroController Linux) впервые был портирован на серию процессоров Dragonball 68k в 1998. uClinux отличается от mainstream linux тем, что не имеет поддержки MMU (noMMU). Также uClinux имеет малую базовую основу, что важно для микроконтроллеров с малыми ресурсами и BFLT (Binary Flat) Executable Format.

Linux 2.0.38


Ядро uClinux - это то место, где будет производится вся возня. Оно основано на ядре Linux 2.0.38. Оригинальное ядро Вы должны использовать на вашем настольном ПК. Патч uClinux применяется для работы с микроконтроллерами. Обычно патч включает поддержку устройств и убирает опору на MMU. Скачайте тарболы и поместите их в /opt/uClinux. Распакуйте и пропатчите ядро. Делается это так:
mkdir /opt/uClinux
cd /opt/uClinux
tar –xzf linux-2.0.38.tar.gz
gzip –d uClinux-2.0.38.1pre7.diff.gz
cd linux
patch -p1 < ../uClinux-2.0.38.1pre7.diff

Как только Вы это сделаете, то получите основу ядра uClinux. Теперь Вам нужно собрать компилятор, который сможет компилировать код в M68k. Позже, в сборке uC-libc, попробуем включить файлы из linux/include/asm. "asm" - это символическая ссылка, указывающая на папку asm-, где arch - архитектура ядра. Например, если конфигурировать uClinux для m68k с noMMU, папка asm будет указывать на asm-m68knommu. Посему, это хорошее место для начала конфигурирования ядра, которое может быть сделано без компилятора m68k-coff.

make menuconfig
По дефолту конфигурация для uCSimm, поэтому если Вы имеете другие платы необходимо их переконфигурировать ядро. Нет нужды собирать ядро, фактически Вы не можете собрать его из-за отсутствия средств разработки. make config установит ссылку на asm, которая будет необходима позже для сборки стандартной библиотеки с, uC-libc.

Средства разработки (Toolchains)

Имеется два разных набора необходимых пакетов программ для компиляции и генерации исполняемого кода (Toolchains) для uClinux. Один используется для компиляции ядра и производит 32бит M68k фиксированный двоичный объектный код. Другой используется для компиляции кода пользовательского пространства и производит 32бит M68k PIC код (position independent code).

Toolchains ядра - ничего больше как запуск фабрики gcc 2.7.2.3. diff ядра делает одну маленькую модификацию в файле /config/m68k/t-m68kbare, вставляя TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc для предотвращения нужды в libc.

Toolchains пользовательского пространства другой предмет обсуждения. Он имеет весьма обширные изменения. Эти изменения лежат в требовании иметь разрядо-независимый объектный код (PIC). Нет прямых переходов, но взамен они заменены родственными ветвями. Глобальные данные возвращаются родственно в регистр A5.

Есть два варианта для cборки tool chains. Можно скачать uClinuxgcc-kit-160899.tar.gz, который содержит все патчи и makefile для автоматической сборки binutils и gcc для среды ядра и пользвателя. Другой вариант: пропатчить и собрать средства самостоятельно и изучить, что происходит в процессе. Мы рассмотрим оба способы здесь.

Простая сборка Tool Chains

Скачиваем следующее:

Извлекаем uClinuxgcc-kit-160899.tar.gz. Можно собрать в любой директории, не зависимо от, /opt/uClinux

tar -xzf uClinuxgcc-kit-160899.tar.gz
cd uclinuxgcc-kit-160899

Правим Makefile (первая строка). Изменяем INSTALLDIR на подходящее место - лучше в /opt/uClinux. Соберем m68k-coff и m68k-pic-coff tool chains набрав make Комманда создаст исполняемые файлы в /opt/uClinux/bin. Можно добавить /opt/uClinux/bin в path, или связать новые бинарники с /usr/bin:

cd /opt/uClinux/bin
ln -f * /usr/bin

Это было не сложно. Теперь посмотрим что происходит при ручной сборке.

Ручная сборка Tool Chains - m68k-coff

Начнем со сборки инструментов m68k фиксированной разрядности, m68k-coff. Скачаиваем:

Извлекаем binutils из тарболов в подходящую директорию и входим туда:

tar -xzf binutils-2.9.1.tar.gz
cd binutil-2.9.1

Конфигурируем binutils под свою аритектуру. Начнем сначала с m68k-coff так как этот подход не требует патчей.

./configure --prefix=/opt/uClinux --target=m68k-coff

Собираем m68k-coff bin устилиты:

make
make install

make создаст директорию /opt/uClinux/m68k-coff которая будет содержать 5 поддиректорий, включая bin, include, libs, m68k-coff и man. Они будут содержать хэдеры, которые нужны для создания gcc. Вернитесь обратно в директорию с gcc-2.7.2.3.tar.gz.

Извлеките gcc тарбол, пропатчите и войдите в директорию с исходниками gcc:

tar -xzf gcc-2.7.2.3.tar.g
gzip -d gcc-2.7.2.3.kernel.diff.gz
cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.kernel.diff

Сконфигурируйте gcc для своей архитектуры. Префикс должен быть таким же как для binutils, так gcc будет искать хэдеры предварительно созданные при установке binutils.

./configure --prefix=/opt/uClinux --target=m68k-coff

Теперь скомпилирйуте C кросс компилятор для m68k-coff. LANGUAGES=c говорит make файлу собрать только С компилятор, а не C++, что может повлечет за собой некоторые излишние проблемы.

make LANGUAGES=c
make LANGUAGES=c install

Сейчас вы должны иметь компилятор m68k-pic-gcc для сборки ядра. Исполняемый файлы должны лежать в /opt/uClinux/m68k-coff/bin. Чтобы продолжить и собрать инструментальные средства pic-coff мы должны удалить рабочие директории или переименовать их. Лучше переименовать их, потому как Вы собираете исходники с нуля, не скачивая RPM, поэтому Вы можете позже исправить ошибки и применить патчи. Переименуйте binutil-2.9.1 в binutil-2.9.1.kernel и gcc-2.7.2.3 в gcc-2.7.2.3.kernel

Ручная сборка Tool Chains - m68k-pic-coff (разрядно-независимый код, Position Independent Code)


Теперь повторим те же процедуры для компилятора m68k-pic-coff. В этот раз binutils должны быть пропатчены

tar -xzf binutils-2.9.1.tar.gz
gzip -d binutils-2.9.1.pic.diff.gz
cd binutils-2.9.1
patch -p1 < ../binutils-2.9.1.pic.diff

в этот раз конфигурируем средства разработки для m68k-pic-coff

./configure --prefix=/opt/uClinux --target=m68k-pic-coff

затем делаем бинарные утилиты m68k-coff.

make
make install

Теперь мы готовы собрать gcc компилятор. Извлекаем тарболы с исходными кодами, патчим и входим в директорию с gcc

tar -xzf gcc-2.7.2.3.tar.gz
gzip -d gcc-2.7.2.3.pic.diff.gz
cd gcc-2.7.2.3 patch -p1 < ../gcc-2.7.2.3.pic.diff

Конфигурируем gcc для своей архитектуры. Префикс должен быть таким же как и для binutils, так как gcc будет просматривать те хэдеры с которыми создавались binutils

./configure --prefix=/opt/uClinux --target=m68k-pic-coff

Делаем m68k-coff C кросс компилятор

make LANGUAGES=c
make LANGUAGES=c install

m68k-pic-coff и m68k-coff можно поместить в path, или создать жесткую ссылку в /usr/bin.

cd /opt/uClinux/bin
ln -f * /usr/bin

Жесткие ссылки созданы взамен мягким. Если была попытка создать мягкую ссылку, gcc/evecvp пожалуется на большое количество символических ссылок ("too many levels of symbolic links"). /opt/uClinux/bin содержит мягкие ссылки, которые указывают на директории bin отдельного компилятора.

На данной ступени мы имеем С компилятор, который делает разрядно-независимые COFF бинарники. Чего у нас пока что нет, это стандартной С и стандартных математических библиотек. uClinux также зависит от плоских бинарников (flat binaries), а не только coff (Common Object File Format). Поэтому мы должны добавть конвертер из coff во flat (coff2flt), который конвертирует модули coff, которые генерирует компилятор, во flat бинарники, которые мы сможем запускать на uClinux.

coff2flt (COFF - Common Object File Format to Flat Binary конвертер)

В порядке создавать плоские бинарники одной коммандой, линковщик (LD) заменен скриптом, который сначала запускает линковщик, который генерирует .coff файл, затем запускает утилиту coff2flt для генерации плоского бинарника.

Скачиваем и распаковываем утилиту

tar -xzf coff2flt-0.5.tar.gz
cd coff2flt-0.5
make

make соберет coff2flt. В тарболе скрипт, линковщик. Мы должны заменить pic-coff-ld этим скриптом, в который возвращаются вызовы coff2flt для создания flat бинарника из coff бинарника. Однако перед тем как мы это сделаем, отредактируем строку в LD для установки %prefix% в /opt/uClinux/m68k-pic-coff

mv /opt/uClinux/m68k-pic-coff/bin/ld /opt/uClinux/m68k-pic-coff/bin/gld
install -m 755 coff2flt /opt/uClinux/m68k-pic-coff/bin
cp ld /opt/uClinux/m68k-pic-coff/bin
chmod 755 /opt/uClinux/m68k-pic-coff/bin/ld

Стандартная Библиотека C


При компиляции бинарников пользовательского пространства используются две библиотеки. Это стандартная библитека С и стандартная математическая библиотека. Это статические библиотеки, которые линукются во время компиляции.

Стандартная С библиотека uC всегда имела беду с ошибками. В частности они имеют плохую манеру утечки памяти из-за их функций выделения памяти. Некоторые индивидуумы имеют патчи для malloc функций, которые можно вручную применить и собрать.

uC-libc испытавает очень радикальные изменения в данный момент. Эти экспериментальные изменения доступны через uClinux CVS хранилище. Стабильная библиотека должна быть доступна скоро, она заменит старые версии uC-libc и предоставит наиболее стабильную платформу. На позитивной ноте, должен сказать, что математическая библиотека имеет маленькие проблемы.

Извлекаем тарбол uC-libc в /opt/uClinux

tar -xzf uC-libc-310899.tar.gz

Библиотека uC-libc имеет две символические ссылки (include/linux и include/net), которые должны указывать на хэдеры ядра uClinux. Эти ссылки требуют, чтобы директория linux находилась в том же дереве, что и директория uC-libc. Если одной не существует из-за различных мест инсталляции, Вы можете создать ссылку.

Библиотека uC-libc в нынешнем состоянии не имеет функций setjmp и longjmp, которые позже потребуются sh. Простейший путь поправить это, переместить uC-libc/machine/setjmp.S в uC-libc/sysdeps/ и включить это (setjmp.o) в uC-libc/sysdeps/makefile.objs

cd uC-libc
make

Если Вы получите сообщения об ошибках о пропавших файлах(скорее всего в директориях asm, linux или net) такую как "/asm/types.h - No such file or directory," тогда проверьте сконфигурировали ли Вы ядро (/include/asm ссылки на месте) и что здесь находятся исходный код ядра linux и ссылка на linux в той же директории что и uC-libc оба.

make скомпилирует библиотеку uC-libc (libc.a) и оставит ее в директории uClibc. Теперь мы должны сделать ее доступной для средств m68k-pic-coff. Каждая ссылка может быть создана, а файлы скопированы

cp libc.a /opt/uClinux/m68k-pic-coff/lib/libc.a
cp crt0.o /opt/uClinux/m68k-pic-coff/lib/crt0.o

Хэдеры также должны быть доступны. Chaintool уже поместил assert.h в /opt/uClinux/m68k-pic-coff/include, поэтому можно переименовать текущую директорию

mv /opt/uClinux/m68k-pic-coff/include /opt/uClinux/m68k-pic-coff/include.old
ln -sf include /opt/uClinux/m68k-pic-coff/include

Стандартные математические библиотеки


Стандартные математические библиотеки не такие проблематичные как С библиотеки. Просто извлеките их в /opt/uClinux и соберите

tar -xzf uC-libm-0.9.1.tar.gz
cd uC-libm
make

затем создайте ссылки в m68k-pic-coff/lib для указания на библиотечные файлы и хэдеры. Эти хэдеры будут обычно находится по их пути в директорию uC-libc/include символической ссылкой.

ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libmf.a
ln -f libmf.a /opt/uClinux/m68k-pic-coff/lib/libm.a
ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/mathf.h
ln -f mathf.h /opt/uClinux/m68k-pic-coff/include/math.h

genromfs - ROM FileSystem Generation Utility


Genromfs генерирует ФС с постоянной памятью (ROM Filesystem). Извлеките, пропатчите и соберите так:

tar -xzf genromfs-0.3.tar.gz
gzip -d genromfs-0.3.diff.gz

cd genromfs-0.3
patch -p1 <../genromfs-0.3.diff
make
make install

make install инсталирует genromfs в /usr/bin + положит свою документацию в usr/man/man8 Genromfs теперь может быть вызвана из коммандной строки для генерации своей romfs.

genromfs -v -V "ROM Disk" -f romdisk.img -d romdisk 2> romdisk.map


Genromfs имеет несколько багов относительно нодов устройства (device nodes). Если Ваша romfs не корректна, ядро сообщит об этом (can't open the device node) и тогда запаникует (panics). Чаще всего полезней монтировать Вашу снова сгенерированную romfs чтобы посмотреть все ли корректно. Делается это так:

mount -r -o loop -t romfs romdisk.img /mnt/romfs

Диск с ROM ФС и бинарники пользовательского пространства



Диск с постоянной памятью (romdisk-0.9.1.tar.gz) - сжатый тарбол, который содержит ноды устройства (device nodes). В итоге файл должен быть распакован (от root'а) в /opt/uClinux

tar -xzf romdisk-0.9.1.tar.gz


Диски romdisk образуют базис ФС встаиваемых (embedded) систем. Утслита genromfs создаст romfs.img из данного дерева, таким образом любые изменения в дереве будут отображены в ФС uClinux. Диск romdisk имеет следующие директории и файлы:

bin dev etc htdocs lib proc ramfs.img sbin tmp usr var


Вы заметите, что при входе в каталог bin предварительно скомпилированные бинарники будут видны. Их исходные коды устанавливаются так:

tar -xzf uC-src-0.9.2.tar.gz
cd src
make

Если Вы испытываете проблемы со сборкой из sh - неопределенный указатель на 'setjmp' или 'longjmp', проверьте включили ли Вы setjmp.S в сборку uC-libc.

Запуск make соберет все исходные коды перечисленные в SUBDIR определенные Makefile. Поэтому если вы добавляете экстра код сюда, то должны влкючить их в Makefile. По завершении процедуры сборки, бинарники будут в находится в директориях src/bin. Скрипт deftemplate.sh скопирует необходимые бинарники из /src в /romdisk/bin или sbin.

cp deftemplate.sh /opt/uClinux/


Нужен еще последний файл. buildenv.sh установит среду сборки из чистой директории, копируя необходимый код устанавливая Makefile. Скопируйте buildenv.sh в /opt/uClinux/bin и создайте ссылку на /usr/bin.

cp buildenv.sh /opt/uClinux/bin/
ln /opt/uClinux/bin/buildenv.sh /usr/bin/buildenv


и всё. Теперь если Вы создадите пустую директорию где-либо и введете buildenv, таинственно появится Makefile. Затем введите make, чтобы увидеть исходные коды пространства пользователя, romdisk etc копируется поверх и соберется.

PIC32 патч - 32-битный PIC патч для m68k-pic-coff 2.7.2.3


С текущим компилятором m68k-pic-coff, будет ограничение на сборку исполняемого кода размером свыше 32k. Размер исходит из использования 16-битного знакового сдвига. Эрвин Отрайд (Erwin Authried) выпустил некоторые патчи для m68k-pic-coff-gcc для генерации 32-битных сдвигов, которые снимают эти ограничения. Код может ббыть собран нормально с 16-битными сдвигами без указания дополнительных специфик. Если Ваша программа превышает 32k, тогда можно вызвать компилятор с флагами -fPIC, которые генерируют 32-битные сдвиги.

Код скомпилированный с -fPIC больше размером. В дополнении к патчу компилятора, нужен новый файл запуска C (C startup file, crt0.S). Он дожен быть скомпилирован и добавлен в m68k-pic-coff/lib. Файл запуска не содержит функции _cleanup(), поэтому должен быть включЕн из другого места.

Отладка


Отладка является необязательным дополнением для "башковитых" uClinux программистов. Состоит она из двух компонентов: gdb-4.18, запускаемый на хост машине, сконфигурированной для m68k-coff, и gdbserver, запускаемый на uClinux платформе. Вместе они общаются через сеть (IP). Пока gdb клиент компилирует с небольшими усилиями, gdb сервер нуждается не только в пропатчивании, но также из библиотеки uClibc, библиотеке отладки uClibc и поддержку из ядра uClinux - но это еще не всё.

gdbserver требует прерывание в ядре uClinux для работы. Хорошие новости в том, что это было включено в поздние ядра, и поэтому не требует внимания. Ядро uClinux-2.0.38.1pre7, описанное здесь, уже имеет эту поддержку.

Скачайте и распакуйте gdb-4.18

tar -xzf gdb-4.18.tar.gz
gzip -d gdb-4.18-gdbserver.diff.gz
cd gdb-4.18
patch -p1 <../gdb-4.18-gdbserver.diff

Сконфигурируйте gdb клиент запустив на хосте для отладки m68k-coff кода и соберите

./configure --target=m68k-unknown-coff
make

Для сборки gdbserver потребуются некоторые дополнительные фкнкции, которых нет в стандартной библиотеке uC-Libc. Исходный код есть в библиотеке, но не задан для сборки по дефолту. Зайдем в /uC-libc/sysdeps/m68k и отредактируем ptrace.c так чтобы путь к ptrace.h был корректен. Заменим #include <sys/ptrace.h> на #include<linux/ptrace.h>.

Теперь добавим исходный код для сборки, редактируя /uC-libc/sysdeps/makefile.objs добавив m68k/ptrace.o в конец списка OBJS, чтобы это смотрелось так

waitpid.o \
write.o \
m68k/ptrace.o


Затем пересоберем библиотеку uC-libc и довавим новый libc.a в /m68k-pic-coff/lib

cd gdb-4.18/gdb/gdbserver
../../configure --target=m68k-linux-coff


Затем отредактируем Makefile, изменив CC = gcc на CC = m68k-pic-coff-gcc

make gdbserver
coff2flt -s 32768 -o gdbserver gdbserver.coff

Запуская make, Вы создаете плоский flat бинарный код gdbserver'а, размер стэка которого по умолчанию составляет около 4k. В результате gdbserver может рухнуть или отказать при соединении. Поэтому рекомендуется линковать с размером стэка в 32k

CVS – Concurrent Version System

Хранилище uClinux доступно на http://cvs.uclinux.org. Отсюда можно отслеживать обновления исходного кода и смотреть какие изменения были сделаны и зачем.

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

Чтобы начать, Вы должны зарегистрироваться. Используйте следующую комманду:

echo anonymous > cvs –d:pserver:anonymous@cvs.uclinux.org:/var/cvs login

Тем сымым Вы войдете в CVS хранилище, используя имя anonymous и пароль anonymous.

cvs –z3 –d:pserver:anonymous@cvs.uclinux.org:/var/cvs co –P <dir>


где <dir> - одна из актуальных директорий,

uClibc The uClinux Userland C Library
uClinux-2.0.x 2.0.38 uClinux Kernel
uClinux-2.4.x 2.4.0 uClinux Kernel
userland uClinux Userland Binaries


Используется спецификатор -z3 для сжатия. Это максимальное сжатие. co необходимо для прекращения связи, -P конкретизирует отсеченные директории (убирает пустые директории).

Позже можно обновить исходные коды используя следующую комманду команду в соответствующей директории

cvs -z3 update -d -P


Ссылки:
GNU GCC
Linux
wiki: uClinux
wiki: binary file

30 июля, 2008

"Проблемы" Встраиваемых Систем GNU/Linux


Встраиваемые системы обычно:
  • малые аппараты: сетевые устройства, карманные компьютеры, телефоны и т.д.

  • не х86(arm, armel, ..), без MMU, без дисковые


"Проблемы":
  • Малое финансирование во встаиваемые системы Linux, обычно со стороны вендоров аппаратного/программного обеспечения
  • Нехватка разработчиков на kernel.org, опять же, обычно вовлечены разработчики вендоров аппаратных/программных средств(коммерческие)
  • Во многих встраиваемых устройствах используется одна версия ядра в полном жизненном цикле продукта
    (обычно производится только кастомизация ядра и поставка)
  • Своевременность и выпуски плотны


Технологии:
  • Динамические тики, hr-таймеры
  • DVB
  • улучшение NoMMU
  • Новые архитектуры: FRV, avr32, blackfin


Ядро:
  • kevent: оперативная унифицированная доставка сообщений
  • utrace: перепись кода трассировки процессов
  • syslets/fibrils: асинхронные вызовы, AIO


Welcome to Linux Kernel Development http://www.linux.org/

01 июля, 2008

Стандарты и концепты системного програмирования в UNIX

Определение понятий - это начало ссылок.
Сократ

Ключевые моменты в современном UNIX программировании:
системные вызовы (syscalls), библиотека C (glibc), коллекция компиляторов (gcc), программные интерфейсы (APIs), бинарные интерфейсы (ABIs), ..[добавить нужное]

== стандарты: POSIX, SUS, C ==

UNIX стандарты.

Системное программирование в UNIX - древнее искусство. За 39 лет здесь не обошлось без хаоса и UNIX войн(расхождение линий AT&T и Berkley University в 1979, лишение прав компании Bell в 1984). Чтобы предотвратить хаос, группы выявления стандартов описали системные интерфейсы в официальных стандартах.
POSIX и SUS являются стандартами C API интерфейсов UNIX-подобных ОС.
В 1985 группа IEEE начала работать над стандартизацией интерфейсов системного уровня UNIX систем. Ричард Столлман (RMS) предложил название для даного стандарта: POSIX [произношение pahz-icks, как позитив]. Первый вариант POSIX появился в 1988: IEEE Std 1003.1-1998. (ISO, IEC приняли эти стандарты как ISO/IEC 9945). Версии стандартов описаны здесь.
The Open Group (объединение X/Open и OSF) также принимали участие в разработке стандартов для UNIX. Их главный труд Single UNIX Specification (SUS) (1994). Сегодня SUSv3(UNIX 03, 2002) включен в POSIX (IEEE Std 1003.1-2001).

C стандарты.

История раннего С описана в статье Д. М. Ритчи "The Development of the C Language, 1993".
Опубликованная впервые в 1978 году книга Денниса Ритчи и Брайана Кернигана "The C Programming Language" ("белая книга") стала неформальным стандартом языка, известным как K&R C, или classic C (классический С). В 1983 году ANSI сформировал комитет (X3J11), целью которого была разработка стандарта официальной версии C (хотя реализация С для UNIX скорее становится стандартом де-факто) и включить некоторые особенности из нового языка C++. Процесс был длительным, стандарт был принят в 1989 году. В 1990 ISO приняло стандарт, основанный на ANSI C, с мелкими модификациями (добавлены литеры signed, void). В 1999 году ISO представило новый стандарт на C (ISO C99), в который были добавлены новые возможности: inline функции, типы (_Bool, _Complex, _Imaginary), комментарии в стиле C++, новые библиотеки функций.


== концепты: файлы, процессы, сигналы, IPC ==

Файлы

еще о файлах (начало здесь; ls([2,3]), stat.h)
..прежде чем получить доступ к файлу для чтения, записи, обработки или др. он должен быть открыт. Открытый файл указывается через уникальный дескриптор, соответствующий метаданным, ассоциированным с самим файлом. Этот дескриптор обрабатывается целым числом (тип int в C) называемым дескриптором файла(file descriptor, fd). fd разделены с пространством пользователя (user space), и используются пользовательскими программами напрямую для доступа к файлу.
Длина файлов ограничена (и только) размерами типов C (C types). Однако файловые системы(FS) могут накладывать свои ограничения, например, укрощать максимальную длину.
Один файл может быть открыт не один раз, причем даже тем же процессом. Каждому открытому экземпляру файла присваивается уникальный дескриптор (файловый дескриптор). Процессы могут совместно использовать fd, позволяя единственному дескриптору использоваться более чем одним процессом.
inode (information node) включает в себя метаданные ассоциированные с файлом, включая местоположение данных файла.
C точки зрения безопасности доступ к файлу через inode обременителен, поэтому файлы обычно открывают из пространства пользователя (user space) по имени (не по номеру inode!). Имя (в человеко-читаемой форме) и inode файла образуют пару, называемую ссылкой (link).
Когда ядро обращается к файлу оно проходит каждое вхождение директории (directory entry, dentry), начиная с /, то есть (для /home/va1e/unix.prog.01.st) сначала получает inode директории home, входит сюда, получает inode va1e, входит сюда, и, наконец, получает inode unix.prog.01.st. Эта операция называется развязкой пути (directory resolution). Для хранения результатов развязки (dir resolution) ядро использует кэш вхождений (dentry cache). Это позволяет быстро обращаться к файлам в будущем. Хотя и директории обрабатываются как обычные файлы, они должны управляться специальным набором системных вызовов.
Специальные файлы - это объекты ядра. И они являются файлами в соответствии парадигмы "всё - файл". Специальными файлами могут быть: файлы UNIX устройств (блочных устройств, символьных устройств [каждое устройство имеет свой файл]), именованные каналы (FIFO, механизм межпроцессорного взаимодействия [IPC]), UNIX сокеты (в отличие от IPC, сокеты позволяют взаимодействовать двум различным процессам не только на одной машине). Как и обычные файлы, специальные создаются путем системных вызовов.

Процессы

Следующим за файлами по значимости в UNIX идут процессы.
Процесс - это запущенный объектный код. Пример: запущенная в своем адресном пространстве программа. Процесс начинает свою жизнь с запуска объектного кода в исполняемом формате, который содержит метаданные, куски кода, загружаемые в память(например, инициализированные переменные С) и данные. Процесс также связан с системными ресурсами(аппаратное обеспечение, сетевые соединения, таймеры, сигналы, открытые файлы, механизмы межпроцессорного взаимодействия), которые управляются ядром; процесс работает с ресурсами только через системные вызовы. Ресурсы, их данные, записываются в дескриптор процесса внутри ядра.
Каждый процесс состоит из одной или нескольких нитей (threads), или единицы активности в процессе, которая отвечает за состояние процесса. Нить состоит из стэка (структуры данных), состояния процессора, и текущего размещения в объектном коде.
Каждый процесс обозначется уникальным целым числом - идентификатором процессы (process ID, PID) [ps(1)]. Дерево процессов(process tree) начинается с первого процесса init(8) [man 8 init]. Новый процесс создается системным вызовом fork(), который создает копию вызываемого процесса. Оригинальный процесс называется родительским (parent), новый - наследованным (child).

Сигналы

Сигналы (Signals) - это механизм односторонней передачи асинхронных сообщений. Сигнал может быть послан от ядра к процессу, от одного процесса другому. Обычно сигнал сообщает процессу о событии, например, аварийное завершение, или нажатие пользователем клавиш C-c. Число сигналов ограничено архитектурой. Каждый из них представлен числовой константой и именем. Например, SIGHUP (signal hangup) имеет значение 1 на x86 архитектуре.

IPC

Одной из важнейших работ ОС является возможность обмена информацией между процессами и предупреждение их о различных событиях(IPC). Многие механазмы IPC описаны в UNIX стандартах, указанных выше.


Список литературы:
1. SUSv3 [http://www.unix.org/version3/]
2. Стивен Прата. Язык программирования С. Лекции и упражнения. 2006, Вильямс
3. D. Lewine. POSIX Programmer's Guide: Writing Portable UNIX Programs. 1992, O'Reilly & Associates
4. R. Love. Linux System Pogramming. 2007, O'Reilly.

27 марта, 2008

Особенности файловой системы UNIX (BSD, Linux, Solaris, Mach, Hurd, Plan9)

Все, что ни есть в системе UNIX, - это файл. Файл - это последовательность байтов (1 байт = 8 бит = 1 символ). Магнитные ленты, почтовые сообщения, символы, вводимые с клавиатуры, вывод принтера, поток данных в программном канале - каждый из этих файлов представляет собой последовательность байтов по отношению к системе и ее программам.

  • Что в файле?
  • Каталоги и имена файлов
  • Права доступа
  • Команды
  • Иерархия файловой системы


Что в файле?
Расширение имени файлов не имеет значения для типа файла.
Команда file делает предположение о типе файла.
~$ file /bin /bin/ed /usr/src/cmd/ed.c
/bin: directory
/bin/ed pure executable
/usr/src/cmd/ed.c c program text

file читает несколько сотен байт и ищет в них ключевые последовательности символов
например исполняемая программа начинается с "магического числа" в двоичном представлении. Команда od без параметров выводит дамп файла 16-битными порциями, позволяя увидеть это "магическое число"
~$ od /bin/ed
000000 000410 025000 000462 011444 000000 000000 000000 000001
000020 170011 016600 000002 005060 017776 010600 162706 000004
..

Восьмиричное значение 410 означает обычную исполняемыю программу. Заметим, что 410 не соответствует никакой ASCII-символ.

Каталоги и имена файлов
Все принадлежащие пользователю файлы имеют имена, начинающиеся с /usr/login, где login - имя вашей учетной записи, регистрационный каталог, чтобы просмотреть находящиеся здесь файлы введите cd(перенесет Вас в домашнюю директорию, если Вы еще не там); ls(1)
~$ сd; ls

команда pwd выведет имя текущего каталога
~$ pwd
/usr/login

В именнах файлов важен регистр букв, File и file - разные файлы

Права доступа
Команда ls запущенная с параметром -l, выводит, кроме основного содержания каталога, информацию о правах доступа.
~$ ls -l /etc/passwd
-rw-r--r-- 1 root 5115 Aug 30 10:40 /etc/passwd
~$ ls -lg /etc/passwd
-rw-r--r-- 1 adm 5115 Aug 30 10:40 /etc/passwd

В строке -rw-r--r-- представлены сведения о правах доступа к файлу, если бы это был каталог, то в первой позиции бы находился символ d.
~$ ls -l /
drwxr-xr-x 2 root root 4096 2008-03-25 11:42 bin

Следующие три символа показывают права владельца на чтение, запись и выполнение. rw-r--r-- означает, что пользователь root(владелец файла) из группы adm может читать и писать, но не может выполнять этот файл. У исполняемого файла должен стоять символ x вместо прочерка -. Следующие три симола rw-r--r-- показывают разрешения для группы adm, можно читать файл, но не более того. Последняя группа символов, также rw-r--r-- определяет права доступа для остальных - прочих пользователей системы. Таким образом только root может изменять регистрационную информацию, а всем остальным она доступна только для чтения.
Команда chmod изменяет права доступа к файлу
Восьмиричные значения образуются путем складывания 4 для чтения, 2 для записи, 1 для исполнения.
~$ chmod 666 file
дает право на чтение и запись файла file всем
~$ chmod 700 command
позволит читать, изменять, выполнять command только его владельцу

Отметим, что знак + (плюс) включает право доступа, а знак - (минус) - выключает.
~$ chmod +x command
позволит всем выполнять command
~$ chmod -w file
отменяет право на запись в файл file всех, включая владельца
~$ chmod -w .
запрещает право на запись в каталог, в котором мы находимся


Команды - это программы, которые вызывает пользователь. Основные команды расположены в директории /bin, но также могут быть расположены в
/usr/bin, чтобы не собирать мусор в /bin. Эти директории автоматически просматриваются командным интерпретатором (shell). UNIX имеет файловую систему компонованную в виде иерархии директорий.
При входе в систему вы попадаете в домашнюю директорию. Для того, чтобы обратиться к файлу в другой директорий, например /usr/share/bin/filex, указываем полный путь (начинается с '/', корневая директория всей файловой системы) с поддиректориями (usr, share, bin), то есть посылаем команду /usr/share/bin/filex
Важные команды, которые могут "играть" с файлами: cp(1), mv(1), rm(1), которые копируют, перемещают и удаляют файлы соответственно. Чтобы просмотреть содержание директорий используйте ls(1), создание директории - mkdir(1),
удаление директории - rmdir(1) или rm(1).

hier(7) - иерархия файловой системы

/     корневая директория
/dev/     devices(4)
     console     главная консоль, tty(4)
     tty*     терминалы, tty(4)
     cat     "наборщик снимков" cat(4)
     rp*     диски, rp, hp(4)
     rrp*     "сырые" диски, rp, hp(4)

/bin/     служебные программы, cf /usr/bin (1)
     as     ассемблер, cf /usr/lib/as2
     cc     исполнительный компилятор C, cf /usr/lib/c[012]

/lib/     объектные библиотеки и подобные вещи, cf /usr/lib/
     libc.a     системные вызовы, стандартные ввод/вывод I/O, и т.п.
     libm.a     математические программы
     libplot.a     программы рисования, plot(3)
     libF77.a     поддержка среды исполнения Фортрана
     libI77.a     ввод/вывод Фортрана
     as2     второй "проход" ассемблера as(1)
     c[012]     проходы cc(1)

/etc/     важные данные и полезные средства сопровождения
     passwd     файл с паролями пользователей, passwd(5)
     group     файл с группами пользователей, group(5)
     motd     сообщение дня, login(1)
     mtab     таблица монтируемых устройств, mtab(5)
     ddate     сброс истории, dump(1)
     ttys     параметры терминала, ttys(5)
     getty     часть login, getty(8)
     init     отец всех процессов, init(8)
     rc     shell-программа для загрузки системы
     cron     часовой демон, cron(8)
     mount     mount(1)
     wall     wall(1)

/tmp/     временные файлы, обычно находятся на быстром устройстве, cf /usr/tmp/
     e*     испольуемые ed(1)
     ctm*     .. cc(1)

/usr/     универсальная директория, обычно монтируемая ФС
     adm/     информация администратора
          wtmp     история входов в систему, utmp(5)
          messages     сообщения об ошибках устройств
          tracct     "наборщик снимков" счет , troff(1)
          vpacct     подсчет строк, lpr(1)
     bin/     служебные программы, чтобы не засорять /bin/
     tmp/     временные, чтобы не засорять /tmp/
          stm*     используется для sort(1)
          raster     .. plot(1)
     dict/     список слов, словообразований и т.п.
          words набор основных слов, используются look(1)
          spellhist     история для spell(1)

     games/     игры
          bj     блэкджек
          hangman     виселица
          quiz.k     что знает quiz(6)
               index     оглавление категории
               africa     страны и столицы
               ..
          ..
     include/стандартые #include файлы
          a.out.h     макет объектного файла, a.out(5)
          stdio.h     стандартные ввод/вывод, stdio(3)
          math.h
          ..
          sys/     системные макеты, cf /usr/sys/h
               acct.h     счет процессов, acct(5)
               buf.h     буфферы внутренней системы
               ..
     lib/     объектные библиотеки и т.п., чтобы не засорять /lib/
          lint[12]     подпроцессы lint(1)
          llib-lc          холостое объявление для /lib/libc.a, используемое lint(1)
          llib-lm          .. /lib/libc.m
          atrun     планировщик at(1)
          struct/     пути sruct(1)
          ..
          tmac/     макросы для troff(1)
               tmac.an      макрос для man(7)
               tmac.s          .. ms(7)
               ..
          font/     шрифты для troff(1)
               R     Times Roman
               B     Times Bold
               ..
          uucp/     программы и данные uucp(1)
               L.sys     имена и числа, поступающие удаленно
               uucico     реальная копия программы
               ..
          suftab     таблица суффиксов для автоматического переноса слов, используемый troff(1)
          units      таблицы обмена для units(1)
          eign     лист английских слов, игнорируемых ptx(1)

     man/     первый том руководства, man(1)
          man0/     основное
               intro     вступление к тому1, ms(7) форматирование
               xx     шаблон для страниц руководства(manual pages)
          man1/     раздел 1
               as.1
               mount,1m
               ..
          cat1/     предварительные страницы man1/
               as.1
               mount.1m
          ..
     spool/     замедленно исполняемые файлы
          at/     at(1)
          lpd/     lpr(1)
               lock     присутствует когда построчно-печатающее устройство активно
               cf*     копия распечатываемого файла, если нужно
               df*     файл управления демонами, lpd(8)
               tf*     файл контроля резидетной памяти, пока lpr работает
          uucp/     рабочие фалйы и область обработки для uucp(1)
               LOGFILE     суммарный журнал
               LOG.*     журнал одной транзакции
          mail/     почтовые ящики mail(1)
               $uid     почта пользователя $uid
               $uid.lock     блокировочный файл, пока $uid принимает почту
          $wd     рабочая директория пользователя, обычно по имени логина $wd
               .profile     окружение для sh(1), environ(5)
               calendar     календарь пользователя, calendar(1)
          doc/     статьи, обычно второй раздел руководства, в формате ms(7)
               as/     руководство ассемблера
               c     руководство C
               ..
          sys/     системный код
               dev/     драйверы устройств
                    bio.c      общий код
                    cat.c     cat(4)
               dh.c     DH11, tty(4)
               tty     tty(4)
               ..
          conf/     железо-зависимый код
               mch.s     часть ассемблерного кода
               conf     генератор конфигураций
               ..
          h/     заголовочные(include) файлы
               acct.h     acct(5)
               stat.h     stat(2)
               ..
          sys/
               main.c
               pipe.c
               sysent.c     точки входа системы
               ..

/usr/     src/     исходные коды утилит и прочего
          cmd/     коды команд
          as/     ассемблер
               makefile     способ сборки ассемблера
               as1?.s          код pass1
          ar.c     код ar(1)
          ..
          troff/     код nroff и troff(1)
               nmake     makefile для nroff
               tmake     makefile для troff
               font/     код таблиц шрифтов, /usr/lib/font/
                    ftR.c     Roman
                    ..
               term/     таблицы характеристик терминала, /usr/lib/term/
                    tab300.c     DASI 300
                    ..
               ..
          libc/     код функций в /lib/libc.a
               crt/     C runtime support
                    ldiv.s     division into a long
                    lmul.s     multiplication to produce long
                    ..
               csu/     запуск и "покрытие" программ нужных в каждой С программе
                    crt0.s     обычный запуск
                    mcrt0.s     модифицированный запуск для cc -p
               sys/     системные вызовы
                    access.s
                    alarm.s
                    ..
               stdio/     функции стандартного ввода/вывода I/O
                    fgets.c
                    fopen.c
                    ..
               gen/
                    abs.c
                    atof.c
                    ..
               compall     shell процедура для компиляции libc
               mklib     shell процедура для сборки /lib/libc.a
          libI77/     коды /lib/libI77
          libF77/
          ..
          games/     исходные коды /usr/games/

Также смотрите
ls(1), ncheck(1), find(1), grep(1)


В Linux также можно изучить иерархию каталогов в руководстве hier
~$ man hier


Если Вы начинаете осваивать сисему UNIX возможно Вам понадобится руководство intro(2)
~$ man 2 intro


Литература:
1. UNIX TIME-SHARING SYSTEM, UNIX Programmer's Manual, V7Vol1, January, 1979, Bell Labs Inc., B.W. Kernigan, M.D.
McIlroy
2. UNIX Programming Environment, The First Edition, 1984, B.W. Kernigan

Также смотрите: Unix Toolbox (pdf буклет)