Скрытые типы данных
Скрытые (opaque) типы данных — это те типы, для которых не раскрывается их внутренняя структура, или формат. Они похожи на typedef
, называют его скрытым и надеются на то, что никто не будет преобразовывать этот тип в стандартный тип данных языка С. Любые использования данных этих типов возможны только через специальные интерфейсы, которые также создаются разработчиком. Примером может быть тип данных pid_t
, в котором хранится информация об идентификаторе процесса. Размер этого типа данных не раскрывается, хотя каждый может смошенничать, использовать размер по максимуму и работать с этим типом, как с типом int. Если нигде явно не используется размер скрытого типа данных, то размер этого типа может быть изменен, и это не вызовет никаких проблем. На самом деле так уже однажды случилось: в старых Unix-подобных операционных системах тип pid_t
был определен как short
.
Еще один пример скрытого типа данных — это тип atomic_t
. Как уже обсуждалось в главе 9, "Средства синхронизации в ядре", этот тип содержит данные целочисленного типа, с которыми можно выполнять атомарные операции. Хотя этот тип и соответствует типу int, использование скрытого типа данных позволяет гарантировать, что данные этого типа будут использоваться только в специальных функциях, которые выполняют атомарные операции. Скрытые типы позволяют скрыть размер типа данных, который не всегда равен полным 32 разрядам, как в случае платформы SPARC.
Другие примеры скрытых типов данных в ядре — это dev_t
, gid_t
и uid_t
. При работе со скрытыми типами данных необходимо помнить о следующем.
• Нельзя предполагать, что данные скрытого типа имеют некоторый определенный размер в памяти.
• Нельзя преобразовывать скрытый тип обратно в стандартный тип данных.
Разрабатывать код необходимо с учетом того, что размер и внутреннее представление скрытого типа данных могут изменяться.
Специальные типы данных
Некоторые данные в ядре, кроме того, что представляются с помощью скрытых типов, требуют еще и специальных типов данных. Два примера — счетчик импульсов системного таймера jiffies
и параметр flags
, используемый для обработки прерываний. Для хранения этих данных всегда должен использоваться тип unsigned long
.
При хранении и использовании специфических данных всегда необходимо обращать особенное внимание на тот тип данных, который представляет эти данные, и использовать именно его. Часто встречающейся ошибкой является использование другого типа, например типа unsigned int
. Хотя для 32-разрядных аппаратных платформ это не приведет к проблемам, на 64-разрядных системах возникнут проблемы.
Типы с явным указанием размера
Часто при программировании необходимы типы данных заданного размера. Обычно это необходимо для удовлетворения некоторых внешних требований, связанных с аппаратным обеспечением, сетью или бинарной совместимостью. Например, звуковой адаптер может иметь 32-разрядный регистр, пакет сетевого протокола — 16-разрядное поле данных, а исполняемый файл — 8 битовый идентификатор cookie. В этих случаях тип, который представляет данные, должен иметь
В ядре типы данных явно заданного размера определены в файле
, который включается из файла
. В табл. 19.2 приведен полный список таких типов данных.
Таблица 19.2. Типы данных явно заданного размера
Тип | Описание |
---|---|
s8 | байт со знаком |
u8 | байт без знака |
s16 | 16-разрядное целое число со знаком |
u16 | 16-разрядное целое число без знака |
s32 | 32-разрядное целое число со знаком |
u32 | 32-разрядное целое число без знака |
s64 | 64-разрядное целое число со знаком |
u64 | 64-разрядное целое число без знака |
Варианты со знаком используются редко.
Эти типы данных, с явно заданным размером, просто определены с помощью оператора typedef
через стандартные типы данных языка С. Для 64-разрядной машины они могут быть определены следующим образом.
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long s64;
typedef unsigned long u64;
Для 32-разрядной машины их можно определить, как показано ниже.
typedef signed char s8;
typedef unsigned char u8;