dd: Команда, которая не похожа на другие


Обычные варианты применения команды dd
Начнем знакомство с операндами команды dd:

if=filename (input file) Этот операнд задает входной файл; если он не указан, то по умолчанию используется стандартный ввод. Этим файлом может быть также файл (нода) устройства, например /dev/hda1, или специфические файлы типа /dev/zero.

of=filename (output file) Задает выходной файл; если он не указан, то по умолчанию используется стандартный вывод (экран монитора).

Знакомство с этими двумя операндами уже дает нам возможность использовать программу dd для копирования файлов.

Пример 1. Простое копирование.

# dd if=/home/ya/Desktop/shema.txt of=/home/ya/Desktop/shema.html
3+1 записей считано
3+1 записей написано
скопировано 1549 байт (1,5 kB), 0,427457 секунд, 3,6 kB/s

Как мы видим, программа dd сняла копию файла shema.txt и записала данные в файл shema.html. При этом она выдала нам сообщение.

Разберемся, о чем говорится в этом сообщении. Команда dd считывает и записывает блоками по N байт в каждом. Поскольку мы не задали в командной строке размер блока, то программа использовала размер блока по умолчанию, равный 512 байт. Всего скопировано 1549 байт, как записано в последней строке сообщения. "3+1 записей считано" означает число полных блоков - 3 плюс один неполный блок, содержащий оставшиеся байты 1549-(3*512)=13. То же относится и к строке "3+1 записей написано".

Теперь самое время разобраться с размером блока.

Сразу скажу, что блок команды dd не имеет никакого отношения к блокам данных файловой системы. Программа dd работает с необработанными "сырыми" (raw data) данными на низком уровне, т.е. на уровне секторов жесткого диска. А любая файловая система является надстройкой над этим уровнем. Правильнее было бы назвать блок буфером. Мы имеем два буфера - входной буфер и выходной буфер. Величина буфера задается операндом bs (block size) и исчисляется в байтах. Например, запись bs=512 означает, что нами установлен размер блока (буфера) в 512 байт. Кстати это значение и используется по умолчанию. Если величина блока не указана, dd использует блоки по 512 байт, что подходит для абсолютного большинства задач. Итак, величина буфера задана, dd создает 512-байтный буфер считывания, посылает единственный запрос на чтение со входного файла, затем создает 512-байтный буфер записи и посылает единственный запрос на запись в выходной файл. Давайте сравним работу программы dd и программы cp при копировании дискеты.

# dd if=/dev/fd0 of=floppy.img bs=1474560
1+0 записей считано
1+0 записей написано
скопировано 1474560 байт (1,5 MB), 0,0438156 секунд, 33,7 MB/s

Может возникнуть вопрос: "А почему именно 1474560 байт, а не 1440 000, как принято считать размер дискеты?" Это значение складывается из: 2 головки, 80 цилиндров, 18 секторов/дорожку при длине сектора 512 байт. Итого: 2*80*18*512=1474560 байт.

Команде же

# cp /dev/fd0 floppy.img

требуется послать 360 запросов по 4096 байт (размер блока данных), что даст те же 360*4096=147560 байт. Для файла размером 1.44Mб это может показаться незначительным, но когда производятся операции с большими объемами данных, уменьшение числа системных вызовов приводит к существенному повышению быстродействия системы.

Итак, размер блока задается операндом

bs=n(байт)

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

bs=2х80х18х512

или используя суффиксы:

bs=2x80x18b

где суффикс b означает 512, а вся запись аналогична предыдущей. Применяются следующие суффиксы:

w означает 2 (в некоторых реализациях 4)
b означает 512
k означает 1024

Короче говоря, как часто бывает в Юниксе, все максимально запутано и требует недюжинной памяти. Но и это еще не все. Кроме bs, существуют еще три операнда размера блока:

ibs=n(байт) Этот операнд определяет размер входного блока. Правила его задания такие же, как для bs.

obs=n(байт) Этот операнд определяет размер выходного блока. Правила его задания такие же, как для bs.

bs является как бы старшим операндом, и если он задан, то ibs и obs игнорируются. ibs и obs нужны в тех случаях, когда необходимо задать различные значения входного и выходного блоков.

И четвертый операнд, связанный с размером блока:

cbs=n(байт) Определяет размер буфера (блока) преобразования. О нем мы будем говорить в главе, посвященной преобразованиям форматов данных.

Теперь, когда мы умеем задавать размеры блока, мы можем выполнить очень важную задачу - снять резервную копию Главной загрузочной записи - MBR. Все, у кого на компьютере имеется несколько операционных систем, должны иметь такую копию, и обновлять ее при каждом изменении системы. MBR находится в 0 секторе первого раздела жесткого диска и занимает вместе с таблицей разделов ровно 512 байт.

Для того чтобы скопировать MBR, следует познакомиться с еще одним операндом:

count=n(блоков) Этот операнд определяет количество блоков, подлежащих копированию. Например запись

bs=512 count=100

означает приказ скопировать 100 блоков по 512 байт каждый. Здесь также возможно применение суффиксов, например

bs=512 count=1k

означает, что будет скопировано 1024 блока по 512 байт каждый.

Внимание! Операнд count имеет дело с блоками, а не с байтами!

Команда, которая скопирует нам MBR в файл backup.mbr выглядит так:

# dd if=/dev/hda of=backup.mbr bs=512 count=1
1+0 записей считано
1+0 записей написано
скопировано 512 байт (512 B), 0,000358146 секунд, 1,4 MB/s

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

# dd if=backup.mbr of=/dev/hda bs=512 count=1

И машина снова станет загружаться. Просмотреть полученную копию можно в любом двоичном (шестнадцатеричном) редакторе, например Khexedit или редакторе из Midnight Commander.

А если нам нужно не весь MBR, а только загрузочный код, который занимает первые 446 байт 0 сектора? Тогда придется изменить размер блока:

# dd if=/dev/hda of=boot-code.mbr bs=446 count=1
1+0 записей считано
1+0 записей написано
скопировано 446 байт (446 B), 0,0345156 секунд, 1,4 MB/s

Если же мы хотим сохранить только таблицу разделов, а загрузочный код (скажем от Windows) нам больше не нужен? Для выполнения этой задачи нам нужно познакомиться еще с одним операндом:

skip=n(блоков) Этот операнд пропускает n блоков от начала входного (if) файла, а затем копирует указанное количество блоков.

Внимание! Операнд skip (как и count) имеет дело с блоками, а не с байтами! Поэтому размер блока следует выбирать вдумчиво. Что мы и сделаем:

# dd if=/dev/hda of=part-table.mbr bs=1 count=66 skip=446
66+0 записей считано
66+0 записей написано
скопировано 66 байт (66 B), 0,034515 секунд, 11,9 kB/s

Мы выбрали размер блока в 1 байт, и бесхитростно указываем нужные параметры в байтах.

Может возникнуть вопрос: "Почему копировали 66 байт, хотя известно, что таблица разделов занимает 16*4=64 байта?" Дело в том, что последние два байта в таблице разделов занимает так называемая сигнатура (подпись) [55 аа], без которой ни один компьютер не опознает таблицу разделов. И поскольку мы делаем резервную копию, то, во избежание забывчивости и недоразумений при будущем восстановлении таблицы разделов, присоединили сигнатуру к таблице разделов.

Как вам нравится рисунок 5? Какой-то он непривычный (смещение на два байта) и неинформативный. Лучше бы иметь стандартную распечатку MBR, в котором первые 446 байт заменены, скажем, нулями. Если придется править вручную, будет намного удобнее. Команда dd позволяет и это. Только нужно применить еще один операнд:

seek=n(блоков) Этот операнд пропускает в выходном файле (of) n блоков, прежде чем начать туда запись.

Внимание! Операнд seek (как и skip и count) имеет дело с блоками, а не с байтами!

Место пропущенных блоков он заполняет нулями. Значит нам нужно применить такую команду:

# dd if=/dev/hda of=part-table.mbr bs=1 count=66 skip=446 seek=446
66+0 записей считано
66+0 записей написано
скопировано 66 байт (66 B), 0,034515 секунд, 12,9 kB/s

http://rus-linux.net/lib.php?name=MyLDP/consol/dd/dd-1.html

Обновлено: 13.03.2015