из ядра 2.6.6
макрос объявлен в linux/kernel.h
используется для получения структуры из содержащей ее структуры
в частности многие структуры в ядре связаны списками типа struct list_head,которые ничего не содержат,кроме указателей на следующий и предыдущий элемент.
этот макрос должен извлекать структуру по указателю,типу структуры и имени члена в структуре
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
как понимать выражение ((type *)0)->member?
и что такое __mptr?
еще нашел,что такое offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
если можете,поясните максимально днтально работу макроса container_of
спасибо.
помогите разобраться в макросе (надо понять как работает макрос container_of(, объявленный в ядре)
Модератор: Модераторы разделов
-
_petya_
- Сообщения: 53
Re: помогите разобраться в макросе
Макрос возвращает указатель на начало структуры типа type .При этом предплагается, что ptr указывает на поле member этой структуры.
К примеру, при создании индекса (inode) для сокета создаётся структура
struct socket_alloc {
struct socket socket;
struct inode vfs_inode;
}
При этом функции, создавшей индекс, возвращается указатель на vfs_inode.
В дальнейшем, функциям, работающим с этим сокетом через индекс, может понадобиться доступ к структуре socket_alloc в целом или к структуре socket.
Тогда будет сделано так
/*inode -указатель на индекс сокета (на поле vfs_inode структуры socket_alloc)*/
struct socket *s = container_of(inode,socket_alloc,vfs_inode)->socket;
По строчкам:
const typeof( ((type *)0)->member ) *__mptr = (ptr);
Выражение typeof( ((type *)0)->member ) возвращает тип поля, на который указывает ptr. Выглядит действительно жутко, но работает - компилятор всё понимает и ошибок времени выполнения нет.
__mptr - просто имя переменной.
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Макрос возвращает адрес поля MEMBER. Так как указатель на структуру, содержащую поле, равен 0, то адрес поля MEMBER - это его (поля) смещение от-но начала структуры .
(type *)( (char *)__mptr - offsetof(type,member) );
Эта строчка вычитает из адреса поля member его (поля) смещение, и получается адрес содержащей его стр-ры.
P.S. Сам недавно начал бродить по ядру - там много прикольных вещей вроде ((type *)0)->member
К примеру, при создании индекса (inode) для сокета создаётся структура
struct socket_alloc {
struct socket socket;
struct inode vfs_inode;
}
При этом функции, создавшей индекс, возвращается указатель на vfs_inode.
В дальнейшем, функциям, работающим с этим сокетом через индекс, может понадобиться доступ к структуре socket_alloc в целом или к структуре socket.
Тогда будет сделано так
/*inode -указатель на индекс сокета (на поле vfs_inode структуры socket_alloc)*/
struct socket *s = container_of(inode,socket_alloc,vfs_inode)->socket;
По строчкам:
const typeof( ((type *)0)->member ) *__mptr = (ptr);
Выражение typeof( ((type *)0)->member ) возвращает тип поля, на который указывает ptr. Выглядит действительно жутко, но работает - компилятор всё понимает и ошибок времени выполнения нет.
__mptr - просто имя переменной.
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
Макрос возвращает адрес поля MEMBER. Так как указатель на структуру, содержащую поле, равен 0, то адрес поля MEMBER - это его (поля) смещение от-но начала структуры .
(type *)( (char *)__mptr - offsetof(type,member) );
Эта строчка вычитает из адреса поля member его (поля) смещение, и получается адрес содержащей его стр-ры.
P.S. Сам недавно начал бродить по ядру - там много прикольных вещей вроде ((type *)0)->member