Un tipico caso d'uso (in applicazioni con codice utente ospitato) per lanciare un puntatore su intptr_t
(da <stdint.h>
standard C99 o C11 header) è calcolare un codice hash su quel puntatore:
uint32_t hash_of_foo_ptr(struct foo_st*foo) {
return (uint32_t) (((intptr_t)foo)*613) ^ ((intptr)foo%51043));
}
Per ragioni storiche (ad esempio Linux è venuto prima del C99), il kernel Linux usa unsigned long
invece di uintptr_t
(il tipo integrale non firmato dello stesso sizeof
come puntatori) o intptr_t
Inoltre, lo spazio utente per le trasmissioni nello spazio del kernel (ad esempio gli argomenti delle sysc) è nel kernel di Linux in termini di long
o unsigned long
(anche in questo caso, è meglio pensare in termini di intptr_t
o% codice%). Anche quando trasmetti gli indirizzi dallo spazio utente allo spazio del kernel, devi pensare agli spazi degli indirizzi e alla memoria virtuale (e sta diventando complesso, dal momento che lo spazio utente e il codice del kernel vivono in spazi di indirizzi diversi).
Una citazione sull'argomento da LDD3 :
Although, conceptually, addresses are pointers, memory administration
is often better accomplished by using an unsigned integer type; the
kernel treats physical memory like a huge array, and a memory address
is just an indexinto the array. Furthermore, a pointer is easily
dereferenced; when dealing directly with memory addresses, you
almost never want to dereference them in this manner. Using an integer
type prevents this dereferencing, thus avoiding bugs. Therefore,
generic memory addresses in the kernel are usually unsigned long ,
exploiting the fact that pointers and long integers are always the
same size, at least on all the platforms currently supported by Linux.
Si noti che il kernel Linux non è codificato in C99 portatile standard accademicamente ospitato. È un programma indipendente, codificato con alcuni compilatori particolari C in mente ( GCC e forse anche in futuro Clang / LLVM ...).
Il kernel Linux sta usando alcune estensioni GCC a C (es. uintptr_t
-s , builtins, goto-s computati, ecc ...), magari avvolti con macro. Molte di queste estensioni sono supportate anche da Clang / LLVM .
Kernel newbies & lkml è probabilmente un buon posto per chiederlo.