linux内核套接字源码宏container_of
linux kernel socket source macro container_of
我试图了解套接字是如何创建的,但我 运行 遇到了我真的不明白的问题。这个问题是下面的代码:
static inline struct socket *SOCKET_I(struct inode *inode)
{
return &container_of(inode, struct socket_alloc, vfs_inode)->socket; //why here is -> socket
}
我看到它是 container_of
宏,它 returns 是一个指针。它以 inode
指针作为参数,
减去 vfs_inode
字节的数量。
我的问题是:
为什么在宏的末尾有类似 ->socket
的东西,它有什么作用?
inode
是 socket_alloc
结构的 vfs_inode
成员。 container_of
扩展为包含该成员的结构。
该结构还包含一个 socket
成员,并且此函数 returns 该成员的值。
换句话说,有一个像
这样的结构
struct socket_alloc {
// ... some members
struct inode vfs_inode;
// ... other members
struct socket socket
// ... more members
} some_variable;
如果你这样做:
struct inode *i = &(some_variable.vfs_inode);
那你以后可以做
struct socket *this_sock = SOCKET_I(i);
获取对应socket
的指针。
帮助我在内核中更多地理解它的代码 linux 有像 sock_alloc_inode 这样的功能 return &ei->vfs_inode nad 我认为 linux socket.c 中带有宏容器的内核场景可能看起来像这样。我不确定它是否正确,但看起来不错。
#include <stdio.h>
#include <stdlib.h>
#define offsetof(type, member) ((size_t) &((type *)0)->member)
#define container_of(ptr, type, member) ({ \
const typeof ( ((type *)0)->member ) *__mptr = (ptr); \
(type *) ( (char *)__mptr - offsetof(type, member) ); })
struct inode{
int a;
int b;
};
struct socket{
int some_other_data;
int this_data;
};
struct socket_alloc{
struct socket socket ;
struct inode vfs_inode;
};
static inline struct socket *SOCKET_I(struct inode *inode)
{
return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
}
static inline struct inode *SOCK_INODE(struct socket *socket)
{
return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
}
int main()
{
struct inode *inode;
struct socket* socket;
struct socket_alloc *ei;
ei = (struct socket_alloc*)malloc(sizeof(*ei));
inode = (struct inode*)malloc(sizeof(*inode));
socket = (struct socket*)malloc(sizeof(*socket));
printf("INODE POINTER NO MACRO AND WITHOUT REFER TO THE SOCKET_ALLOC STRUCT %d\n", *inode);
inode= &ei->vfs_inode;
printf("INODE POINTER NO MACRO %d\n", *inode);
printf("SOCKET POINTER NO MACRO%d\n", *socket);
socket = SOCKET_I(inode);
inode = SOCK_INODE(socket);
printf("INODE POINTER USING MACRO %d\n", *inode);
printf("SOCKET POINTER USING MACRO %d\n", *socket);
free(ei);
return 0;
}
我试图了解套接字是如何创建的,但我 运行 遇到了我真的不明白的问题。这个问题是下面的代码:
static inline struct socket *SOCKET_I(struct inode *inode)
{
return &container_of(inode, struct socket_alloc, vfs_inode)->socket; //why here is -> socket
}
我看到它是 container_of
宏,它 returns 是一个指针。它以 inode
指针作为参数,
减去 vfs_inode
字节的数量。
我的问题是:
为什么在宏的末尾有类似 ->socket
的东西,它有什么作用?
inode
是 socket_alloc
结构的 vfs_inode
成员。 container_of
扩展为包含该成员的结构。
该结构还包含一个 socket
成员,并且此函数 returns 该成员的值。
换句话说,有一个像
这样的结构struct socket_alloc {
// ... some members
struct inode vfs_inode;
// ... other members
struct socket socket
// ... more members
} some_variable;
如果你这样做:
struct inode *i = &(some_variable.vfs_inode);
那你以后可以做
struct socket *this_sock = SOCKET_I(i);
获取对应socket
的指针。
帮助我在内核中更多地理解它的代码 linux 有像 sock_alloc_inode 这样的功能 return &ei->vfs_inode nad 我认为 linux socket.c 中带有宏容器的内核场景可能看起来像这样。我不确定它是否正确,但看起来不错。
#include <stdio.h>
#include <stdlib.h>
#define offsetof(type, member) ((size_t) &((type *)0)->member)
#define container_of(ptr, type, member) ({ \
const typeof ( ((type *)0)->member ) *__mptr = (ptr); \
(type *) ( (char *)__mptr - offsetof(type, member) ); })
struct inode{
int a;
int b;
};
struct socket{
int some_other_data;
int this_data;
};
struct socket_alloc{
struct socket socket ;
struct inode vfs_inode;
};
static inline struct socket *SOCKET_I(struct inode *inode)
{
return &container_of(inode, struct socket_alloc, vfs_inode)->socket;
}
static inline struct inode *SOCK_INODE(struct socket *socket)
{
return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
}
int main()
{
struct inode *inode;
struct socket* socket;
struct socket_alloc *ei;
ei = (struct socket_alloc*)malloc(sizeof(*ei));
inode = (struct inode*)malloc(sizeof(*inode));
socket = (struct socket*)malloc(sizeof(*socket));
printf("INODE POINTER NO MACRO AND WITHOUT REFER TO THE SOCKET_ALLOC STRUCT %d\n", *inode);
inode= &ei->vfs_inode;
printf("INODE POINTER NO MACRO %d\n", *inode);
printf("SOCKET POINTER NO MACRO%d\n", *socket);
socket = SOCKET_I(inode);
inode = SOCK_INODE(socket);
printf("INODE POINTER USING MACRO %d\n", *inode);
printf("SOCKET POINTER USING MACRO %d\n", *socket);
free(ei);
return 0;
}