C linux内核套接字源宏容器

C linux内核套接字源宏容器,c,sockets,kernel,C,Sockets,Kernel,我试图了解如何创建是套接字,但我遇到了我真的不明白的问题。此问题的代码如下所示: static inline struct socket *SOCKET_I(struct inode *inode) { return &container_of(inode, struct socket_alloc, vfs_inode)->socket; //why here is -> socket } 我看到它是宏的容器,它返回一个指针。它将inode指针作为参数 减去vfs\

我试图了解如何创建是套接字,但我遇到了我真的不明白的问题。此问题的代码如下所示:

static inline struct socket *SOCKET_I(struct inode *inode)
{
    return &container_of(inode, struct socket_alloc, vfs_inode)->socket; //why here is -> socket
}
我看到它是宏的
容器,它返回一个指针。它将
inode
指针作为参数 减去
vfs\u inode
字节数

我的问题是:
为什么在宏的末尾有类似于
->socket
的东西,以及它的作用是什么?

inode
socket\u alloc
结构的
vfs\u inode
成员<代码>容器\u的
扩展到包含该成员的结构

该结构还包含一个
socket
成员,该函数返回该成员的值

换言之,有一种结构

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);

为了获得相应的
套接字
代码的指针,这有助于我更好地理解内核linux中的代码,有一个类似于sock\u alloc\u inode的函数,它返回&ei->vfs\u inode nad,我认为socket.c中包含宏的linux内核场景可能是这样的。我不确定它是否正确,但看起来很好

#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;
}
#包括
#包括
#定义偏移量(类型,成员)((大小)和((类型*)0)->成员)
#定义(ptr,type,member)({\
常量typeof(((type*)0)->成员)*\uu mptr=(ptr)\
(类型*)((字符*)u mptr-offsetof(类型,成员));})
结构节点{
INTA;
int b;
};
结构套接字{
输入一些其他数据;
把这个数据整型;
};
结构套接字\u alloc{
结构套接字;
结构索引节点vfs_索引节点;
};
静态内联结构套接字*socket\u I(结构索引节点*inode)
{
返回和容器(inode、struct socket、vfs inode)->socket;
}
静态内联结构inode*SOCK\u inode(结构套接字*socket)
{
返回和容器(socket、struct socket、alloc、socket)->vfs inode;
}
int main()
{
结构inode*inode;
结构套接字*socket;
结构套接字\u alloc*ei;
ei=(结构套接字_alloc*)malloc(sizeof(*ei));
inode=(结构inode*)malloc(sizeof(*inode));
套接字=(结构套接字*)malloc(sizeof(*socket));
printf(“INODE指针无宏且未引用套接字\u ALLOC结构%d\n”,*INODE);
inode=&ei->vfs\u inode;
printf(“INODE指针没有宏%d\n”,*INODE);
printf(“套接字指针没有宏%d\n”,*SOCKET);
插座=插座I(inode);
inode=SOCK_inode(socket);
printf(“使用宏%d\n的索引节点指针,*索引节点”);
printf(“使用宏%d\n的套接字指针,*SOCKET”);
免费(ei);
返回0;
}

“为什么宏末尾有类似于
->socket
的东西,以及它的作用?”-
->socket
不是宏调用的一部分。假设宏返回一个指针(类型为
inode*
),您将该返回值命名为
inode\u object
。因此,您可以将返回语句编写为
&inode\u object->socket
。也就是说,这只是一个指向
socket
字段的指针。因此,此宏将返回指向socket结构的inode指针。它将指针指向inode并减去vfs_inode字节数,然后该指针指向套接字?。我是对的?如果“
vfs\u inode
bytes”是指
vfs\u inode
结构中
socket\u alloc
字段的偏移量,那么是的,
container\u of
从输入指针中减去给定的量,并返回减法结果,并将其转换为
struct socket\u alloc*
。关于这个输入指针,我还有一个问题。正如我所知,指针有一些地址和SOCKET_,我用一些地址获取指针,然后从字节中减去这个地址。然后按你说的返回插座。它怎么知道这个地址字节数将是struct socket_alloc*。我的意思是,在不设置该指针的情况下,它指向vfs\u inode/这是
SOCKET\u I
函数的使用要求,只应使用
inode
参数调用它,该参数指向某些
SOCKET\u alloc
对象的字段
vfs\u inode
。您可能想知道,如果不使用指向对象的指针,如何获得指向对象字段的指针。但实际上,在用于面向对象编程(OOP)的Linux内核中,这是非常常见的场景,当使用指向基类型对象的指针调用虚拟方法时,在这个派生类型方法的实现中,您需要将这个指向基类型的指针转换为指向派生类型的指针offsetof
告诉您从结构开头到成员的字节数。因此,如果有一个指向成员的指针并减去偏移量,则会得到一个指向结构开头的指针。