Um ioctl vai para um driver, então a coisa mais importante para descobrir o que um ioctl está fazendo é qual driver está lidando com ele.
O que você leu sobre type
, number
e data_type
é uma convenção que os gravadores de driver devem usar ao escolher números ioctl. Embora drivers diferentes possam usar o mesmo valor para significar coisas completamente diferentes, é melhor evitar isso, de modo que se um ioctl for acidentalmente enviado para o dispositivo errado, há uma boa chance de ele retornar um erro em vez de causar algum evento catastrófico .
Uma boa descrição da convenção está no livro Drivers de dispositivos do Linux (LDD ), capítulo 6 . O data_type
é de fato (desde algum tempo no início da série 2.6.x IIRC) feito de duas partes, direction
e size
.
-
type
(8 bits) é uma constante que deve ser consistente nos ioctls implementados em um driver e deve ser diferente de ioctls de dispositivos não relacionados, se possível. Há um repositório desatualizado de valorestype
emDocumentation/ioctl/ioctl-number.txt
. -
number
(8 bits) deve ser diferente para todos os ioctls em um driver. -
direction
(2 bits) indica a direção da transferência de dados (0 = nenhum, 1 = gravação, 2 = leitura, 3 = ambos). -
size
é o tamanho do buffer de dados, se o argumento ioctl for um ponteiro para um buffer de dados.
O número de ioctl deve ser
direction << 30 | size << 16 | type << 8 | number
(Se você estiver escrevendo um driver, use as macros _IOC_*
definidas em asm-generic/ioctl.h
.)
Para o seu número de ioctl 3222823425 = 0xc0186201, obtemos type = 0x62 (conhecido como “bit3 vme host bridge” em 1999), number = 1, direction = 2 e size = 0x18 = 24, então o ioctl leva um valor de 24- parâmetro de entrada de byte.
Esse valor ioctl deve ser definido como _IOR(0x62, 0x01, struct somestruct)
ou algo equivalente como _IOR('b', 1, struct somestruct)
, em que struct somestruct
é uma estrutura de 24 bytes. Se você não souber qual driver está processando o ioctl, poderá procurar uma chamada como essa na origem do kernel para reunir candidatos. No entanto, observe que uma pesquisa de texto simples geralmente não encontra o driver, pois é comum usar uma macro, por exemplo, #define FOOIO_TYPE 0x62
seguido por #define FOOIO_SOMETHING _IOR(FOOIO_TYPE, 1, struct foobar)
.
Uma chamada ioctl tem dois parâmetros além do descritor de arquivo com o qual o ioctl atua: o número do ioctl cmd
e um argumento arg
. O argumento pode ser um valor imediato ou um ponteiro para um buffer. Aqui, se o gravador de driver estiver seguindo a convenção, arg
deverá ser um ponteiro para um buffer de 24 bytes no espaço de memória do aplicativo.