Доступ к жесткому диску через файл устройства
Предположим, что в системе присутствует один накопитель на жестком магнитном диске, который подключен как Primary Master. Согласно обозначениям блочных устройств, принятым в ОС Linux, ему соответствует файл устройства /dev/hda. Разработаем программный модуль, выполняющий чтение первого сектора (MBR) и получающий информацию об устройстве, такую как модель жесткого диска, его серийный номер, геометрию (число цилиндров/головок/секторов) и число логических блоков.
Нам понадобятся следующие заголовочные файлы:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <linux/hdreg.h>
В файле <linux/hdreg.h> определена структура struct hd_driveid, предназначенная для хранения информации идентификации устройства, и перечень команд управления устройством.
int main() {
struct hd_driveid ide; int hda, sect; char sector[512];
Для доступа к устройству достаточно стандартным способом открыть соответствующий файл устройства:
hda=open("/dev/hda",O_RDONLY); if(!hda) { perror("hda"); }
sect=open("mbr",O_CREAT|O_RDWR,0600); if(!sect) { perror("sect"); }
Для получения информации идентификации устройству посылаем команду HDIO_GET_IDENTITY. Команда идентификации позволяет считать из контроллера блок из 256 слов, характеризующих устройство. Результат будет сохранен в структуре struct hd_driveid ide, адрес которой задается в качестве третьего аргумента функции
ioctl:
if(ioctl(hda,HDIO_GET_IDENTITY,&ide)) perror ("HDIO_GET_IDENTITY");
Как уже было упомянуто, перечень команд управления устройством определен в файле <linux/hdreg.h>. Например, команды включения 32-битного режима обмена данными, режима DMA и мультисекторного чтения выглядят следующим образом:
static u_long dma=1, io32set=1, mult=16; if(ioctl(hda,HDIO_SET_32BIT,io32set)) perror("HDIO_SET_32BIT"); if(ioctl(hda,HDIO_SET_DMA,dma)) perror("HDIO_SET_DMA"); if(ioctl(hda,HDIO_SET_MULTCOUNT,mult)) perror("HDIO_SET_MULTCOUNT");
Отобразим информацию идентификации устройства:
printf("Серийный номер - %s\n",ide.serial_no); printf("Модель - %s\n",ide.model); printf("Число логических блоков - %d\n",ide.lba_capacity); printf("Число цилиндров - %d\n",ide.cyls); printf("Число головок - %d\n",ide.heads); printf("Число секторов - %d\n",ide.sectors);
Считываем первый сектор и сохраняем его в отдельном файле:
read(hda,sector,sizeof(sector)); write(sect,sector,sizeof(sector));
close(hda); close(sect);
return (0); }
Как вы видите, доступ к жесткому диску через файл устройства наиболее простой и удобный, т.к. позволяет абстрагироваться от деталей функционирования устройства. Давайте теперь посмотрим на жесткий диск с точки зрения драйвера, но в начале - немного теории.