Файловая структура ос. Система автоматического создания сигнатур исполняемых файлов

Typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Я лишь сухо опишу данные поля, т.к. названия интуитивно понятные и представляют из себя непосредственные значения, а не VA, RVA, RAW и прочие страшные интригующие штуки, о которых пока, мы только слышали от старых пиратов. Хотя с RAW мы уже сталкивались - это как раз смещения относительно начала файла (их ещё называют сырыми указателями или file offset). То есть если мы имеем RAW адрес, это значит что нужно шагнуть от начала файла на RAW позиций (ptrFile + RAW). После можно начинать читать значения. Ярким примером данного вида является e_lfnew - что мы рассмотрели выше в Dos заголовке.

*Machine : WORD - это число (2 байта) задаёт архитектуру процессора, на которой данное приложение может выполняться.
NumberOfSections : DWORD - количество секций в файле. Секции (в дальнейшем будем называть таблицей секций) следуют сразу после заголовка (PE-Header). В документации сказано что количество секций ограничено числом 96.
TimeDateStamp : WORD - число хранящее дату и время создания файла.
PointerToSymbolTable : DWORD - смещение (RAW) до таблицы символов, а SizeOfOptionalHeader - это размер данной таблицы. Данная таблица призвана служить для хранения отладочной информации, но отряд не заметил потери бойца с самого начала службы. Чаще всего это поле зачищается нулями.
SIzeOfOptionHeader : WORD - размер опционального заголовка (что следует сразу за текущим) В документации указано, что для объектного файла он устанавливается в 0…
*Characteristics : WORD - характеристики файла.

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

Оставим этот остров! Нам нужно двигаться дальше. Ориентир - страна под названием Optional-Header.

“- Где карта, Билли? Мне нужна карта.”
(Остров сокровищ)

Optional-Header (IMAGE_OPTIONAL_HEADER)

Название сего материка заголовка не очень удачное. Этот заголовок является обязательным и имеет 2 формата PE32 и PE32+ (IMAGE_OPTIONAL_HEADER32 и IMAGE_OPTIONAL_HEADER64 соответственно). Формат хранится в поле Magic : WORD. Заголовок содержит необходимую информацию для загрузки файла. Как всегда :

IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory; } IMAGE_OPTIONAL_HEADE R, *PIMAGE_OPTIONAL_HEADER;


* Как всегда, мы изучим только основные поля, которые имеют наибольшее влияние на представление о загрузке и того, как двигаться дальше по файлу. Давайте условимся - в полях данной структуры, содержаться значения с VA (Virtual address) и RVA (Relative virtual address) адресами. Это уже адреса не такие как RAW, и их нужно уметь читать (точнее считать). Мы непременно научимся это делать, но только для начала разберём структуры, которые идут друг за другом, чтобы не запутаться. Пока просто запомните - это адреса, которые после расчётов, указывают на определённое место в файле. Также встретится новое понятие - выравнивание. Его мы рассмотрим в купе с RVA адресами, т.к. эти они довольно тесно связаны.

AddressOfEntryPoint : DWORD - RVA адрес точки входа. Может указывать в любую точку адресного пространства. Для.exe файлов точка входа соответствует адресу, с которого программа начинает выполняться и не может равняться нулю!
BaseOfCode : DWORD - RVA начала кода программы (секции кода).
BaseOfData : DWORD - RVA начала кода программы (секции данных).
ImageBase : DWORD - предпочтительный базовый адрес загрузки программы. Должен быть кратен 64кб. В большистве случаев равен 0x00400000.
SectionAligment : DWORD - размер выравнивания (байты) секции при выгрузке в виртуальную память.
FileAligment : DWORD - размер выравнивания (байты) секции внутри файла.
SizeOfImage : DWORD - размер файла (в байтах) в памяти, включая все заголовки. Должен быть кратен SectionAligment.
SizeOfHeaders : DWORD - размер всех заголовков (DOS, DOS-Stub, PE, Section) выравненный на FileAligment.
NumberOfRvaAndSizes : DWORD - количество каталогов в таблице директорий (ниже сама таблица). На данный момент это поле всегда равно символической константе IMAGE_NUMBEROF_DIRECTORY_ENTRIES, которая равна 16-ти.
DataDirectory : IMAGE_DATA_DIRECTORY - каталог данных. Проще говоря это массив (размером 16), каждый элемент которого содержит структуру из 2-ух DWORD-ых значений.

Рассмотрим что из себя представляет структура IMAGE_DATA_DIRECTORY :

Typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
Что мы имеем? Мы имеем массив из 16 элементов, каждый элемент которого, содержит адрес и размер (чего? как? зачем? всё через минуту). Встаёт вопрос чего именно это характеристики. Для этого, у microsoft имеется специальные константы для соответствия. Их можно увидеть в самом конце описания структуры. А пока:

// Directory Entries #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory // IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) #define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP #define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers #define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table #define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors #define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
Ага! Мы видим, что каждый элемент массива, отвечает за прикреплённую к нему таблицу. Но увы и ах, пока эти берега недосягаемы для нас, т.к. мы не умеем работаться с VA и RVA адресами. А для того чтобы научиться, нам нужно изучить что такое секции. Именно они расскажут о своей структуре и работе, после чего станет понятно для чего нужны VA, RVA и выравнивания. В рамках данной статьи, мы затронем только экспорт и иморт. Предназначение остальных полей можно найти в оф. документации, либо в книжках. Так вот. Собственно поля:

VirtualAddress : DWORD - RVA на таблицу, которой соответствует элемент массива.
Size : DWORD - размер таблицы в байтах.

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

А находимся мы не посредственно перед широкими просторами секций. Нам нужно непременно выпытать что они таят и разобраться уже наконец с другим видом адресации. Нам хочется настоящих приключений! Мы хотим поскорее отправится к таким республикам как таблицы импорта и экспорта. Старые пираты говаривают, что не каждый смог до них добраться, а тот кто добрался вернулся -с золотом и женщинами со священными знаниями об океане. Отчаливаем и держим путь на Section header.

“- Ты низложен, Сильвер! Слезай с бочки!”
(Остров сокровищ)

Section-header (IMAGE_SECTION_HEADER)


Сразу за массивом DataDirectory друг за другом идут секции. Таблица секций представляет из себя суверенное государство, которое делится на NumberOfSections городов. Каждый город имеет своё ремесло, свои права, а также размер в 0x28 байт. Количество секций указано в поле NumberOfSections , что хранится в File-header-е. Итак, рассмотрим структуру :

Typedef struct _IMAGE_SECTION_HEADER { BYTE Name; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
Name : BYTE - название секции. На данный момент имеет длину в 8 символов.
VirtualSize : DWORD - размер секции в виртуальной памяти.
SizeOfRawData : DWORD - размер секции в файле.
VirtualAddress : DWORD - RVA адрес секции.
SizeOfRawData : DWORD - размер секции в файле. Должен быть кратен FileAligment .
PointerToRawData : DWORD - RAW смещение до начала секции. Также должен быть кратен FileAligment
Characteristics : DWORD - атрибуты доступа к секции и правила для её загрузки в вирт. память. Например атрибут для определения содержимого секции (иниц. данные, не инициал. данные, код). Или атрибуты доступа - чтение, запись, исполнение. Это не весь их спектр. Характеристики задаются константами из того-же WINNT.h, которые начинаются с IMAGE_SCN_. Более подробно ознакомится с атрибутами секций можно . Также хорошо описаны атрибуты в книгах Криса Касперски - список литературы в конце статьи.

По поводу имени следует запомнить следующее - секция с ресурсам, всегда должна иметь имя.rsrc. В противном случае ресурсы не будут подгружены. Что касается остальных секций - то имя может быть любым. Обычно встречаются осмысленные имена, например.data, .src и т.д… Но бывает и такое:

Секции, это такая область, которая выгружается в виртуальную память и вся работа происходит непосредственно с этими данными. Адрес в виртуальной памяти, без всяких смещений называется Virtual address, сокращённо VA. Предпочитаемый адрес для загрузки приложения, задаётся в поле ImageBase . Это как точка, с которой начинается область приложения в виртуальной памяти. И относительно этой точки отсчитываются смещения RVA (Relative virtual address). То есть VA = ImageBase + RVA; ImageBase нам всегда известно и получив в своё распоряжение VA или RVA, мы можем выразить одно через другое.

Тут вроде освоились. Но это же виртуальная память! А мы то находимся в физической. Виртуальная память для нас сейчас это как путешествие в другие галактики, которые мы пока можем лишь только представлять. Так что в виртуальную память нам на данный момент не попасть, но мы можем узнать что там будет, ведь это взято из нашего файла.

Выравнивание


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

Как можно заметить, секция выгружается в память не по своему размеру. Здесь используются выравнивания. Это значение, которому должны быть кратен размер секции в памяти. Если посмотреть на схему, то мы увидим, что размер секции 0x28, а выгружается в размере 0x50. Это происходит из-за размера выравнивания. 0x28 “не дотягивает” до 0x50 и как следствие, будет выгружена секция, а остальное пространство в размере 0x50-0x28 занулится. А если размер секции был бы больше размера выравнивания, то что? Например sectionSize = 0x78, а sectionAligment = 0x50, т.е. остался без изменений. В таком случае, секция занимала бы в памяти 0xA0 (0xA0 = 0x28 * 0x04) байт. То есть значение которое кратно sectionAligment и полностью кроет sectionSize . Следует отметить, что секции в файле выравниваются аналогичным образом, только на размер FileAligment . Получив необходимую базу, мы можем разобраться с тем, как конвертировать из RVA в RAW.

“Здесь вам не равнина, здесь климат иной.”
(В.С. Высоцкий)

Небольшой урок арифметики


Перед тем как начать выполнение, какая то часть программы должна быть отправлена в адресное пространство процессора. Адресное пространство - это объём физически адресуемой процессором оперативной памяти. “Кусок” в адресном пространстве, куда выгружается программа называется виртуальным образом (virtual image). Образ характеризуется адресом базовой загрузки (Image base) и размером (Image size). Так вот VA (Virtual address) - это адрес относительно начала виртуальной памяти, а RVA (Relative Virtual Address) относительно места, куда была выгружена программа. Как узнать базовый адрес загрузки приложения? Для этого существует отдельное поле в опциональном заголовке под названием ImageBase . Это была небольшая прелюдия чтобы освежить в памяти. Теперь рассмотрим схематичное представление разных адресаций:

Дак как же всё таки прочитать информацию из файла, не выгружая его в виртуальную память? Для этого нужно конвертировать адреса в RAW формат. Тогда мы сможем внутри файла шагнуть на нужный нам участок и прочитать необходимые данные. Так как RVA - это адрес в виртуальной памяти, данные по которому были спроецированы из файла, то мы можем произвести обратный процесс. Для этого нам понадобится ключ девять на шестнадцать простая арифметика. Вот несколько формул:

VA = ImageBase + RVA; RAW = RVA - sectionRVA + rawSection; // rawSection - смещение до секции от начала файла // sectionRVA - RVA секции (это поле хранится внутри секции)
Как видно, чтобы высчитать RAW, нам нужно определить секцию, которой принадлежит RVA. Для этого нужно пройти по всем секциям и проверить следующие условие:

RVA >= sectionVitualAddress && RVA < ALIGN_UP(sectionVirtualSize, sectionAligment) // sectionAligment - выравнивание для секции. Значение можно узнать в Optional-header. // sectionVitualAddress - RVA секции - хранится непосредственно в секции // ALIGN_UP() - функция, определяющая сколько занимает секция в памяти, учитывая выравнивание
Сложив все пазлы, получим вот такой листинг:

Typedef uint32_t DWORD; typedef uint16_t WORD; typedef uint8_t BYTE; #define ALIGN_DOWN(x, align) (x & ~(align-1)) #define ALIGN_UP(x, align) ((x & (align-1))?ALIGN_DOWN(x,align)+align:x) // IMAGE_SECTION_HEADER sections; // init array sections int defSection(DWORD rva) { for (int i = 0; i < numberOfSection; ++i) { DWORD start = sections[i].VirtualAddress; DWORD end = start + ALIGN_UP(sections[i].VirtualSize, sectionAligment); if(rva >= start && rva < end) return i; } return -1; } DWORD rvaToOff(DWORD rva) { int indexSection = defSection(rva); if(indexSection != -1) return rva - sections.VirtualAddress + sections.PointerToRawData; else return 0; }
*Я не стал включать в код объявление типа, и инициализацию массива, а лишь предоставил функции, которые помогут при расчёте адресов. Как видите, код получился не очень сложным. Разве что малость запутанным. Это проходит… если уделить ещё немного времени колупанию в.exe через дизассемблер.

УРА! Разобрались. Теперь мы можем отправится в края ресурсов, библиотек импорта и экспорта и вообще куда душа желает. Мы ведь только что научились работать с новым видом адресации. В путь!

“-Неплохо, неплохо! Всё же они получили свой паёк на сегодня!”
(Остров сокровищ)

Export table


В самом первом элементе массива DataDirectory хранится RVA на таблицу экспорта, которая представлена структурой IMAGE_EXPORT_DIRECTORY. Эта таблица свойственна файлам динамических библиотек (.dll). Основной задачей таблицы является связь экспортируемых функций с их RVA. Описание представлено в оф. спецификикации :

Typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; WORD MajorVersion; WORD MinorVersion; DWORD Name; DWORD Base; DWORD NumberOfFunctions; DWORD NumberOfNames; DWORD AddressOfFunctions; DWORD AddressOfNames; DWORD AddressOfNameOrdinals; } IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
Эта структура содержит три указателя на три разные таблицы. Это таблица имён (функций) (AddressOfNames ), ординалов(AddressOfNamesOrdinals ), адресов(AddressOfFunctions ). В поле Name хранится RVA имени динамической библиотеки. Ординал - это как посредник, между таблицей имён и таблицей адресов, и представляет из себя массив индексов (размер индекса равен 2 байта). Для большей наглядности рассмотрим схему:

Рассмотрим пример. Допустим i-ый элемент массива имён указывает на название функции. Тогда адрес этой функции можно получить обратившись к i-му элементу в массиве адресов. Т.е. i - это ординал.

Внимание! Если вы взяли к примеру 2-ой элемент в таблице ординалов, это не значит 2 - это ординал для таблиц имён и адресов. Индексом является значение, хранящееся во втором элементе массива ординалов.

Количество значений в таблицах имён (NumberOfNames ) и ординалов равны и не всегда совпадают с количеством элементов в таблице адресов (NumberOfFunctions ).

“За мной пришли. Спасибо за внимание. Сейчас, должно быть, будут убивать!”
(Остров сокровищ)

Import table


Таблица импорта неотъемлемая часть любого приложения, которая использует динамические библиотеки. Данная таблица помогает соотнести вызовы функций динамических библиотек с соответствующими адресами. Импорт может происходить в трёх разных режимах: стандартный, связывающем (bound import) и отложенном (delay import). Т.к. тема иморта достаточно многогранна и тянет на отдельную статью, я опишу только стандартный механизм, а остальные опишу только «скелетом».

Стандартный импорт - в DataDirectory под индексом IMAGE_DIRECTORY_ENTRY_IMPORT(=1) хранится таблица импорта. Она представляет собой массив из элементов типа IMAGE_IMPORT_DESCRIPTOR. Таблица импорта хранит (массивом) имена функций/ординалов и в какое место загрузчик должен записать эффективный адрес этой функций. Этот механизм не очень эффективен, т.к. откровенно говоря всё сводится к перебору всей таблицы экспорта для каждой необходимой функции.

Bound import - при данной схеме работы в поля (в первом элементе стандартной таблицы импорта) TimeDateStamp и ForwardChain заносится -1 и информация о связывании хранится в ячейке DataDirectory с индексом IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT(=11). То есть это своего рода флаг загрузчику о том что нужно использовать bound import. Так же для «цепочки bound импорта» фигурируют свои структуры. Алгоритм работы заключается в следующем - в виртуальную память приложения выгружается необходимая библиотека и все необходимые адреса «биндятся» ещё на этапе компиляции. Из недостатоков можно отметить то, что при перекомпиляции dll, нужно будет перекомпилировать само приложение, т.к. адреса функций будут изменены.

Delay import - при данном методе подразумевается что.dll файл прикреплён к исполняемому, но в память выгружается не сразу (как в предыдущих двух методах), а только при первом обращении приложения к символу (так называют выгружаемые элементы из динамических библиотек). То есть программа выполняется в памяти и как только процесс дошёл до вызова функции из динамической библиотеки, то вызывается специальный обработчик, который подгружает dll и разносит эффективные адреса её функций. За отложенным импортом загрузчик обращается к DataDirectory (элемент с номером 15).

Малость осветив методы импорта, перейдём непосредственно к таблице импорта.

“-Это моряк! Одежда у него была морская. - Да ну? А ты думал найти здесь епископа?”
(Остров сокровищ - Джон Сильвер)

Import-descriptor (IMAGE_IMPORT_DESCRIPTOR)


Для того чтобы узнать координаты таблицы импорта, нам нужно обратиться к массиву DataDirectory . А именно к элементу IMAGE_DIRECTORY_ENTRY_IMPORT (=1). И прочитать RVA адрес таблицы. Вот общая схема пути, который требуется проделать:

Затем из RVA получаем RAW, в соответствии с формулами приведёнными выше, и затем “шагаем” по файлу. Теперь мы впритык перед массивом структур под названием IMAGE_IMPORT_DESCRIPTOR. Признаком конца массива служит “нулевая” структура.

Typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; DWORD OriginalFirstThunk; } DUMMYUNIONNAME; DWORD TimeDateStamp; DWORD ForwarderChain; DWORD Name; DWORD FirstThunk; } IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR;
Я не смог выудить на msdn ссылку на описание структуры, но вы можете наблюдать её в файле WINNT.h. Начнём разбираться.

OriginalFirstThunk : DWORD - RVA таблицы имён импорта (INT).
TimeDateStamp : DWORD - дата и время.
ForwarderChain : DWORD - индекс первого переправленного символа.
Name : DWORD - RVA строки с именем библиотеки.
FirstThunk : DWORD - RVA таблицы адресов импорта (IAT).

Тут всё несколько похоже на экспорт. Также таблица имён (INT) и и тоже рубище на нём адресов (IAT). Также RVA имени библиотеки. Только вот INT и IAT ссылаются на массив структур IMAGE_THUNK_DATA. Она представлена в двух формах - для 64- и для 32-ый систем и различаются только размером полей. Рассмотрим на примере x86:

Typedef struct _IMAGE_THUNK_DATA32 { union { DWORD ForwarderString; DWORD Function; DWORD Ordinal; DWORD AddressOfData; } u1; } IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32;
Важно ответить, что дальнейшие действия зависят от старшего бита структуры. Если он установлен, то оставшиеся биты представляют из себя номер импортируемого символа (импорт по номеру). В противном случае (старший бит сброшен) оставшиеся биты задают RVA импортируемого символа (импорт по имени). Если мы имеем импорт по имени, то указатель хранит адрес на следующую структуру:

Typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
Здесь Hint - это номер функции, а Name - имя.

Для чего это всё? Все эти массивы, структуры… Рассмотрим для наглядности замечательную схему с

Лекция 3. Файловая структура

Литература

o Современные операционные системы, Э. Таненбаум, 2002, СПб, Питер, 1040 стр., (в djvu 10.1Мбайт) подробнее>>

o Сетевые операционные системы Н. А. Олифер, В. Г. Олифер (в zip архиве 1.1Мбайт)

o Сетевые операционные системы Н. А. Олифер, В. Г. Олифер, 2001, СПб, Питер, 544 стр., (в djvu 6.3Мбайт)подробнее>>

Файлы

Требования к хранению информации:

o возможность хранения больших объемов данных

o информация должна сохраняться после прекращения работы процесса

o несколько процессов должны иметь одновременный доступ к информации

2.1.1Именование файлов

Длина имени файла зависит от ОС, может быть от 8 (MS-DOS) до 255 (Windows, LINUX) символов.

ОС могут различать прописные и строчные символы. Например, WINDOWS и windows для MS-DOS одно и тоже, но для UNIX это разные файлы.

Во многих ОС имя файла состоит из двух частей, разделенных точкой, например windows.exe. Часть после точки называют расширением файла . По нему система различает тип файла.

У MS-DOS расширение составляет 3 символа. По нему система различает тип файла, а также можно его исполнять или нет.

У UNIX расширение ограничено размером имени файла в 255 символов, также у UNIX может быть несколько расширений, но расширениями пользуются больше прикладные программы, а не ОС. По расширению UNIX не может определить исполняемый это файл или нет.

2.1.2Структура файла

Три основные структуры файлов:

1. Последовательность байтов - ОС не интересуется содержимым файла, она видит только байты. Основное преимущество такой системы, это гибкость использования. Используются в Windows и UNIX.

2. Последовательность записей - записей фиксированной длины (например, перфокарта), считываются последовательно. Сейчас не используются.

3. Дерево записей - каждая запись имеет ключ, записи считываются по ключу. Основное преимущество такой системы, это скорость поиска. Пока еще используется на мэйнфреймах.

Три типа структур файла.

2.1.3Типы файлов

Основные типы файлов:

o Регулярные - содержат информацию пользователя. Используются в Windows и UNIX.

o Каталоги - системные файлы, обеспечивающие поддержку структуры файловой системы. Используются в Windows и UNIX.

o Символьные - для моделирования ввода-вывода. Используются только в UNIX.

o Блочные - для моделирования дисков. Используются только в UNIX.

Основные типы регулярных файлов:

o ASCII файлы - состоят из текстовых строк. Каждая строка завершается возвратом каретки (Windows), символом перевода строки (UNIX) и используются оба варианта (MS-DOS). Поэтому если открыть текстовый файл, написанный в UNIX, в Windows, то все строки сольются в одну большую строку, но под MS-DOS они не сольются (это достаточно частая ситуация ). Основные преимущества ASCII файлов:
- могут отображаться на экране, и выводится на принтер без преобразований
- могут редактироваться почти любым редактором

o Двоичные файлы - остальные файлы (не ASCII). Как правило, имеют внутреннею структуру.

Основные типы двоичных файлов:

o Исполняемые - программы, их может обрабатывать сама операционная система, хотя они записаны в виде последовательности байт.

o Неисполняемые - все остальные.

Примеры исполняемого и не исполняемого файла

«Магическое число» - идентифицирующее файл как исполняющий.

2.1.4Доступ к файлам

Основные виды доступа к файлам:

o Последовательный - байты читаются по порядку. Использовались, когда были магнитные ленты.

2.1.5Атрибуты файла

Основные атрибуты файла:

o Защита - кто, и каким образом может получить доступ к файлу (пользователи, группы, чтение/запись). Используются в Windows и UNIX.

o Пароль - пароль к файлу

o Создатель - кто создал файл

o Владелец - текущий владелец файла

o Флаг "только чтение" - 0 - для чтения/записи, 1 - только для чтения. Используются в Windows.

o Флаг "скрытый" - 0 - виден, 1 - невиден в перечне файлов каталога (по умолчанию). Используются в Windows.

o Флаг "системный" - 0 - нормальный, 1 - системный. Используются в Windows.

o Флаг "архивный" - готов или нет для архивации (не путать сжатием). Используются в Windows.

o Флаг "сжатый" - файл сжимается (подобие zip архивов). Используются в Windows.

o Флаг "шифрованный" - используется алгоритм шифрования. Если кто-то попытается прочесть файл, не имеющий на это прав, он не сможет его прочесть. Используются в Windows.

o Флаг ASCII/двоичный - 0 - ASCII, 1 - двоичный

o Флаг произвольного доступа - 0 - только последовательный, 1 - произвольный доступ

o Флаг "временный" - 0 - нормальный, 1 - для удаления файла по окончании работы процесса

o Флаг блокировки - блокировка доступа к файлу. Если он занят для редактирования.

o Время создания - дата и время создания. Используются UNIX.

o Время последнего доступа - дата и время последнего доступа

o Время последнего изменения - дата и время последнего изменения. Используются в Windows и UNIX.

o Текущий размер - размер файла. Используются в Windows и UNIX.

2.1.6Операции с файлами

Основные системные вызовы для работы с файлами:

o Create - создание файла без данных.

o Delete - удаление файла.

o Open - открытие файла.

o Close - закрытие файла.

o Read - чтение из файла, с текущей позиции файла.

o Write - запись в файл, в текущею позицию файла.

o Append - добавление в конец файла.

o Seek - устанавливает файловый указатель в определенную позицию в файле.

o Get attributes - получение атрибутов файла.

o Set attributes - установить атрибутов файла.

o Rename - переименование файла.

память загрузчиком операционной системы и затем исполнен. В операционной системе Windows исполняемые файлы, как правило, имеют расширения ".exe" и ".dll". Расширение ".exe" имеют программы, которые могут быть непосредственно запущены пользователем. Расширение ".dll" имеют так называемые динамически связываемые библиотеки ( dynamic link libraries). Эти библиотеки экспортируют функции, используемые другими программами.

Для того чтобы загрузчик операционной системы мог правильно загрузить исполняемый файл в память , содержимое этого файла должно соответствовать принятому в данной операционной системе формату исполняемых файлов. В разных операционных системах в разное время существовало и до сих пор существует множество различных форматов. В этой главе мы рассмотрим формат Portable Executable (PE). Формат PE - это основной формат для хранения исполняемых файлов в операционной системе Windows . Сборки. NET тоже хранятся в этом формате.

Кроме того, формат PE может использоваться для представления объектных файлов . Объектные файлы служат для организации раздельной компиляции программы. Смысл раздельной компиляции заключается в том, что части программы (модули) компилируются независимо в объектные файлы , которые затем связываются компоновщиком в один исполняемый файл .

А теперь - немного истории. Формат PE был создан разработчиками Windows NT. До этого в операционной системе Windows использовались форматы New Executable (NE) и Linear Executable (LE) для представления исполняемых файлов, а для хранения объектных файлов использовался Object Module Format (OMF). Формат NE предназначался для 16-разрядных приложений Windows , а формат LE, изначально разработанный для OS/2 , был уже 32-разрядным. Возникает вопрос: почему разработчики Windows NT решили отказаться от существующих форматов? Ответ становится очевидным, если обратить внимание на то, что большая часть команды, работавшей над созданием Windows NT, ранее работала в Digital Equipment Corporation. Они занимались в DEC разработкой инструментария для операционной системы VAX / VMS , и у них уже были навыки и готовый код для работы с исполняемыми файлами, представленными в формате Common Object File Format ( COFF ). Соответственно, формат COFF в слегка модифицированном виде был перенесен в Windows NT и получил название PE.

В ". NET Framework Glossary " сказано, что PE - это реализация Microsoft формата COFF . В то же время в утверждается, что PE - это формат исполняемых файлов, а COFF - это формат объектных файлов . Вообще, мы можем наблюдать путаницу в документации Microsoft относительно названия формата. В некоторых местах они называют его COFF , а в некоторых - PE. Правда, можно заметить, что в новых текстах название COFF используется все меньше и меньше. Более того, формат PE постоянно эволюционирует. Например, несколько лет назад в Microsoft отказались от хранения отладочной информации внутри исполняемого файла, и поэтому теперь многие поля в структурах формата COFF просто не используются. Кроме того, формат COFF - 32-разрядный, а последняя редакция формата PE (она называется PE32+) может использоваться на 64-разрядных аппаратных платформах. Поэтому, видимо, дело идет к тому, что название COFF вообще перестанут использовать.

Интересно отметить, что исполняемые файлы в устаревших форматах NE и LE до сих пор поддерживаются Windows . Исполняемые файлы в формате NE можно запускать под управлением NTVDM (NT Virtual DOS Machine), а формат LE используется для виртуальных драйверов устройств (

Понимание файловой системы Linux, структуры каталогов, размещения конфигурационных, исполняемых и временных файлов поможет вам лучше разбираться в своей системе и стать успешным системным администратором. Файловая система Linux будет непривычна именно для новичка, только что перешедшего с Windows, ведь здесь все совсем по-другому. В отличие от Windows, программа не находится в одной папке, а, как правило, распределена по корневой файловой системе. Это распределение поддается определенным правилам. Вы когда-нибудь задавались вопросом, почему некоторые программы находятся в папке /bin, или /sbin, /usr/sbin, /usr/local/bin, в чем разница между этими каталогами?

Например, программа less, находится в каталоге /usr/bin, но почему не в /sbin или /usr/sbin. А такие программы, как ifconfig или fdisk находятся в каталоге /sbin и нигде иначе.

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

/ - корень

Это главный каталог в системе Linux. По сути, это и есть файловая система Linux. Здесь нет дисков или чего-то подобного, как в Windows. Вместо этого, адреса всех файлов начинаются с корня, а дополнительные разделы, флешки или оптические диски подключаются в папки корневого каталога.

Обратите внимание, что у пользователя root домашний каталог /root, но не сам /.

/bin - (binaries) бинарные файлы пользователя

Этот каталог содержит исполняемые файлы. Здесь расположены программы, которые можно использовать в однопользовательском режиме или режиме восстановления. Одним словом, те утилиты, которые могут использоваться пока еще не подключен каталог /usr/. Это такие общие команды, как cat, ls, tail, ps и т д.

/sbin - (system binaries) системные исполняемые файлы

Так же как и /bin, содержит двоичные исполняемые файлы, которые доступны на ранних этапах загрузки, когда не примонтирован каталог /usr. Но здесь находятся программы, которые можно выполнять только с правами суперпользователя. Это разные утилиты для обслуживания системы. Например, iptables, reboot, fdisk, ifconfig,swapon и т д.

/etc - (etcetera) конфигурационные файлы

В этой папке содержатся конфигурационные файлы всех программ, установленных в системе.

Кроме конфигурационных файлов, в системе инициализации Init Scripts, здесь находятся скрипты запуска и завершения системных демонов, монтирования файловых систем и автозагрузки программ. Структура каталогов linux в этой папке может быть немного запутанной, но предназначение всех их - настройка и конфигурация.

/dev - (devices) файлы устройств

В Linux все, в том числе внешние устройства являются файлами. Таким образом, все подключенные флешки, клавиатуры, микрофоны, камеры - это просто файлы в каталоге /dev/. Этот каталог содержит не совсем обычную файловую систему. Структура файловой системы Linux и содержащиеся в папке /dev файлы инициализируются при загрузке системы, сервисом udev. Выполняется сканирование всех подключенных устройств и создание для них специальных файлов. Это такие устройства, как: /dev/sda, /dev/sr0, /dev/tty1, /dev/usbmon0 и т д.

/proc - (proccess) информация о процессах

Это тоже необычная файловая система, а подсистема, динамически создаваемая ядром. Здесь содержится вся информация о запущенных процессах в реальном времени. По сути, это псевдофайловая система, содержащая подробную информацию о каждом процессе, его Pid, имя исполняемого файла, параметры запуска, доступ к оперативной памяти и так далее. Также здесь можно найти информацию об использовании системных ресурсов, например, /proc/cpuinfo, /proc/meminfo или /proc/uptime. Кроме файлов в этом каталоге есть большая структура папок linux, из которых можно узнать достаточно много информации о системе.

/var (variable) - Переменные файлы

Название каталога /var говорит само за себя, он должен содержать файлы, которые часто изменяются. Размер этих файлов постоянно увеличивается. Здесь содержатся файлы системных журналов, различные кеши, базы данных и так далее. Дальше рассмотрим назначение каталогов Linux в папке /var/.

/var/log - Файлы логов

/var/lib - базы данных

Еще один тип изменяемых файлов - это файлы баз данных, пакеты, сохраненные пакетным менеджером и т д.

/var/mail - почта

В эту папку почтовый сервер складывает все полученные или отправленные электронные письма, здесь же могут находиться его логи и файлы конфигурации.

/var/spool - принтер

Изначально, эта папка отвечала за очереди печати на принтере и работу набора программ cpus.

/var/lock - файлы блокировок

Здесь находятся файлы блокировок. Эти файлы означают, что определенный ресурс, файл или устройство занят и не может быть использован другим процессом. Apt-get, например, блокирует свою базу данных, чтобы другие программы не могли ее использовать, пока программа с ней работает.

/var/run - PID процессов

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

/tmp (temp) - Временные файлы

В этом каталоге содержатся временные файлы, созданные системой, любыми программами или пользователями. Все пользователи имеют право записи в эту директорию.

Файлы удаляются при каждой перезагрузке. Аналогом Windows является папка Windows\Temp, здесь тоже хранятся все временные файлы.

/usr - (user applications) Программы пользователя

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

/usr/bin/ - Исполняемые файлы

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

/usr/sbin/

Содержит двоичные файлы программ для системного администрирования, которые нужно выполнять с правами суперпользователя. Например, таких как Gparted, sshd, useradd, userdel и т д.

/usr/lib/ - Библиотеки

Содержит библиотеки для программ из /usr/bin или /usr/sbin.

/usr/local - Файлы пользователя

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

/home - Домашняя папка

В этой папке хранятся домашние каталоги всех пользователей. В них они могут хранить свои личные файлы, настройки программ и т д. Например, /home/sergiy и т д. Если сравнивать с Windows, то это ваша папка пользователя на диске C, но в отличии от WIndows, home как правило размещается на отдельном разделе, поэтому при переустановке системы все ваши данные и настройки программ сохранятся.

/boot - Файлы загрузчика

Содержит все файлы, связанные с загрузчиком системы. Это ядро vmlinuz, образ initrd, а также файлы загрузчика, находящие в каталоге /boot/grub.

/lib (library) - Системные библиотеки

Содержит файлы системных библиотек, которые используются исполняемыми файлами в каталогах /bin и /sbin.

Библиотеки имеют имена файлов с расширением *.so и начинаются с префикса lib*. Например, libncurses.so.5.7. Папка /lib64 в 64 битных системах содержит 64 битные версии библиотек из /lib. Эту папку можно сравнить с WIndows\system32, там тоже сгружены все библиотеки системы, только там они лежат смешанные с исполняемыми файлами, а здесь все отдельно.

/opt (Optional applications) - Дополнительные программы

В эту папку устанавливаются проприетарные программы, игры или драйвера. Это программы созданные в виде отдельных исполняемых файлов самими производителями. Такие программы устанавливаются в под-каталоги /opt/, они очень похожи на программы Windows, все исполняемые файлы, библиотеки и файлы конфигурации находятся в одной папке.

/mnt (mount) - Монтирование

В этот каталог системные администраторы могут монтировать внешние или дополнительные файловые системы.

/media - Съемные носители

В этот каталог система монтирует все подключаемые внешние накопители - USB флешки, оптические диски и другие носители информации.

/srv (server) - Сервер

В этом каталоге содержатся файлы серверов и сервисов. Например, могут содержаться файлы веб-сервера apache.

/run - процессы

Еще один каталог, содержащий PID файлы процессов, похожий на /var/run, но в отличие от него, он размещен в TMPFS, а поэтому после перезагрузки все файлы теряются.

/sys (system) - Информация о системе

Назначение каталогов Linux из этой папки - получение информации о системе непосредственно от ядра. Это еще одна файловая система организуемая ядром и позволяющая просматривать и изменить многие параметры работы системы, например, работу swap, контролировать вентиляторы и многое другое.

2.1 Файлы

Требования к хранению информации:

    возможность хранения больших объемов данных

    информация должна сохраняться после прекращения работы процесса

    несколько процессов должны иметь одновременный доступ к информации

2.1.1 Именование файлов

Длина имени файла зависит от ОС, может быть от 8 (MS-DOS) до 255 (Windows, LINUX) символов.

ОС могут различать прописные и строчные символы. Например, WINDOWS и windows для MS-DOS одно и тоже, но для UNIX это разные файлы.

Во многих ОС имя файла состоит из двух частей, разделенных точкой, например windows.exe. Часть после точки называют расширением файла . По нему система различает тип файла.

У MS-DOS расширение составляет 3 символа. По нему система различает тип файла, а также можно его исполнять или нет.

У UNIX расширение ограничено размером имени файла в 255 символов, также у UNIX может быть несколько расширений, но расширениями пользуются больше прикладные программы, а не ОС. По расширению UNIX не может определить исполняемый это файл или нет.

2.1.2 Структура файла

Три основные структуры файлов:

    Последовательность байтов - ОС не интересуется содержимым файла, она видит только байты. Основное преимущество такой системы, это гибкость использования. Используются в Windows и UNIX.

    Последовательность записей - записей фиксированной длины (например, перфокарта), считываются последовательно. Сейчас не используются.

    Дерево записей - каждая запись имеет ключ, записи считываются по ключу. Основное преимущество такой системы, это скорость поиска. Пока еще используется на мэйнфреймах.

Три типа структур файла.

2.1.3 Типы файлов

Основные типы файлов:

    Регулярные - содержат информацию пользователя. Используются в Windows и UNIX.

    Каталоги - системные файлы, обеспечивающие поддержку структуры файловой системы. Используются в Windows и UNIX.

    Символьные - для моделирования ввода-вывода. Используются только в UNIX.

    Блочные - для моделирования дисков. Используются только в UNIX.

Основные типы регулярных файлов:

    ASCII файлы - состоят из текстовых строк. Каждая строка завершается возвратом каретки (Windows), символом перевода строки (UNIX) и используются оба варианта (MS-DOS). Поэтому если открыть текстовый файл, написанный в UNIX, в Windows, то все строки сольются в одну большую строку, но под MS-DOS они не сольются (это достаточно частая ситуация ). Основные преимущества ASCII файлов:
    - могут отображаться на экране, и выводится на принтер без преобразований
    - могут редактироваться почти любым редактором

    Двоичные файлы - остальные файлы (не ASCII). Как правило, имеют внутреннею структуру.

Основные типы двоичных файлов:

    Исполняемые - программы, их может обрабатывать сама операционная система, хотя они записаны в виде последовательности байт.

    Неисполняемые - все остальные.

Примеры исполняемого и не исполняемого файла

«Магическое число» - идентифицирующее файл как исполняющий.

2.1.4 Доступ к файлам

Основные виды доступа к файлам:

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

2.1.5 Атрибуты файла

Основные атрибуты файла:

    Защита - кто, и каким образом может получить доступ к файлу (пользователи, группы, чтение/запись). Используются в Windows и UNIX.

    Пароль - пароль к файлу

    Создатель - кто создал файл

    Владелец - текущий владелец файла

    Флаг "только чтение" - 0 - для чтения/записи, 1 - только для чтения. Используются в Windows.

    Флаг "скрытый" - 0 - виден, 1 - невиден в перечне файлов каталога (по умолчанию). Используются в Windows.

    Флаг "системный" - 0 - нормальный, 1 - системный. Используются в Windows.

    Флаг "архивный" - готов или нет для архивации (не путать сжатием). Используются в Windows.

    Флаг "сжатый" - файл сжимается (подобие zip архивов). Используются в Windows.

    Флаг "шифрованный" - используется алгоритм шифрования. Если кто-то попытается прочесть файл, не имеющий на это прав, он не сможет его прочесть. Используются в Windows.

    Флаг ASCII/двоичный - 0 - ASCII, 1 - двоичный

    Флаг произвольного доступа - 0 - только последовательный, 1 - произвольный доступ

    Флаг "временный" - 0 - нормальный, 1 - для удаления файла по окончании работы процесса

    Флаг блокировки - блокировка доступа к файлу. Если он занят для редактирования.

    Время создания - дата и время создания. Используются UNIX.

    Время последнего доступа - дата и время последнего доступа

    Время последнего изменения - дата и время последнего изменения. Используются в Windows и UNIX.

    Текущий размер - размер файла. Используются в Windows и UNIX.

2.1.6 Операции с файлами

Основные системные вызовы для работы с файлами:

    Create - создание файла без данных.

    Delete - удаление файла.

    Open - открытие файла.

    Close - закрытие файла.

    Read - чтение из файла, с текущей позиции файла.

    Write - запись в файл, в текущею позицию файла.

    Append - добавление в конец файла.

    Seek - устанавливает файловый указатель в определенную позицию в файле.

    Get attributes - получение атрибутов файла.

    Set attributes - установить атрибутов файла.

    Rename - переименование файла.

2.1.7 Файлы, отображаемые на адресное пространство памяти

Иногда удобно файл отобразить в памяти (не надо использовать системные вызовы ввода-вывода для работы с файлом), и работать с памятью, а потом записать измененный файл на диск.

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

При использовании сегментной организации памяти, файл загружают в отдельный сегмент.

Пример копирования файла через отображение в памяти.

Алгоритм:

    Создается сегмент для файла 1

    Файл отображается в памяти

    Создается сегмент для файла 2

    Сегмент 1 копируется в сегмент 2

    Сегмент 2 сохраняется на диске

Недостатки этого метода:

    Тяжело определить длину выходного файла

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

    Файл может оказаться большим, больше сегмента или виртуального пространства.

2.2 Каталоги

2.2.1 Одноуровневые каталоговые системы

В этой системе все файлы содержатся в одном каталоге.

Однокаталоговая система, содержащая четыре файла, файлов А два, но разных владельцев

Преимущества системы:

    Простота

    Возможность быстро найти файл, не надо лазить по каталогам

Недостатки системы:

    Различные пользователи могут создать файлы с одинаковыми именами.

2.2.2 Двухуровневые каталоговые системы

Для каждого пользователя создается свой собственный каталог.

Двухуровневая каталоговая система

Пользователь, при входе в систему, попадает в свой каталог и работает только с ним. Это делает проблематичным использование системных файлов.

Эту проблему можно решить созданием системного каталога, с общим доступом.

Если у одного пользователя много файлов, то у него тоже может возникнуть необходимость в файлах с одинаковыми именами.

2.2.3 Иерархические каталоговые системы

Каждый пользователь может создавать столько каталогов, сколько ему нужно.

Иерархическая каталоговая система

Почти все современные универсальные ОС, организованы таким образом. Специализированным ОС это может быть не нужным.

2.2.4 Имя пути

Для организации дерева каталогов нужен некоторый способ указания файла.

Два основных метода указания файла:

    абсолютное имя пути - указывает путь от корневого каталога, например:
    - для Windows \usr\ast\mailbox
    - для UNIX /usr/ast/mailbox
    - для MULTICS >usr>ast>mailbox

    относительное имя пути - путь указывается от текущего каталога (рабочего каталога), например:
    - если текущий каталог /usr/, то абсолютный путь /usr/ast/mailbox перепишется в ast/mailbox
    - если текущий каталог /usr/ast/, то абсолютный путь /usr/ast/mailbox перепишется в mailbox
    - если текущий каталог /var/log/, то абсолютный путь /usr/ast/mailbox перепишется в../../usr/ast/mailbox

./ - означает текущий каталог

../ - означает родительский каталог

2.2.5 Операции с каталогами

Основные системные вызовы для работы с каталогами:

    Create - создать каталог

    Delete - удалить каталог

    OpenDir - закрыть каталог

    CloseDir - закрыть каталог

    Rename - переименование каталога