🚀
socket(2)でsocketが生成されるまで
概要
古いバージョンではkmem_cache_allocでsocketを、new_inode_pseudoで対応するinodeを確保していた。
現在のバージョン(6.3)ではnew_inode_pseudoでinodeを確保する際にsocket用の領域も一緒に確保している。
socketシステムコールの定義は以下の通り。
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
return __sys_socket(family, type, protocol);
}
socketを割り当てる部分は以下のコードです。
int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
...
sock = sock_alloc();
...
}
struct socket *sock_alloc(void)
{
struct inode *inode;
struct socket *socket;
inode = new_inode_pseudo(sock_mnt->mnt_sb);
...
sock = SOCKET_I(inode);
...
}
ソケットのsb(スーパーブロック)を渡してinodeを確保し、SOCKET_Iでinodeからsocketのアドレスを計算しています。つまり、
struct socket_alloc {
struct socket socket;
struct inode vfs_inode;
};
inode確保の際に上記の構造体としてsocket用の領域も含めて確保して、socketのアドレスを計算しています。
struct inode *new_inode_pseudo(struct superblock *sb)
{
struct inode *inode = alloc_inode(sb);
...
}
struct static inode *alloc_inode(struct super_block *sb)
{
const struct super_operations *ops = sb->s_op;
...
inode = ops->alloc_inode(sb);
...
}
inode確保に使うnew_inode_pseudo関数ですが、内部ではsb(スーパーブロック)に登録されているalloc_inodeを使っています。
sock_mnt->mnt_sbの設定を見ると、
static int sockfs_init_fs_context(struct fs_context *fc)
{
...
ctx->ops = &sockfs_ops;
...
}
static const struct super_operations sockfs_ops = {
.alloc_inode = sock_alloc_inode,
.free_inode = sock_free_inode,
.statfs = simple_statfs,
};
ということで、sock_alloc_inodeがsocket用のinode確保時に呼ばれていることが分かります。
static struct inode *sock_alloc_inode(struct super_block *sb)
{
struct socket_alloc *ei;
ei = alloc_inode_sb(sb, sock_inode_cachep, GFP_KERNEL);
...
return &ei->vfs_inode;
}
上記から、socketとinodeが同時に確保されていることが分かります。
Discussion