简体   繁体   中英

linux kernel socket source macro container_of

i was trying to understand how created is socket but i have ran into the problem which i really dont understand. This problem is the code below:

static inline struct socket *SOCKET_I(struct inode *inode)
{
    return &container_of(inode, struct socket_alloc, vfs_inode)->socket; //why here is -> socket
}

I see it's the container_of macro and it returns a pointer. It takes inode pointer as a parameter and subtracts amount of vfs_inode bytes.

my question is : Why there is something like ->socket at the end of the macro and what does it do?

inode is the vfs_inode member of a socket_alloc structure. container_of expands to the structure that contains that member.

The structure also contains a socket member, and this function returns the value of that member.

In other words, there's a structure like

struct socket_alloc {
    // ... some members
    struct inode vfs_inode;
    // ... other members
    struct socket socket
    // ... more members
} some_variable;

If you do:

struct inode *i = &(some_variable.vfs_inode);

then you can later do

struct socket *this_sock = SOCKET_I(i);

to get a pointer to the corresponding socket .

Code which helps me to understand it more in kernel linux there is function like sock_alloc_inode which return &ei->vfs_inode nad i think linux kernel scenario with container of macro in socket.c may looks like that. Im not sure if its right but looks well.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM