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 的东西,它有什么作用?

inodesocket_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;
}