socket


Rev.1を表示中。最新版はこちら

sock_create()で、ソケットファイルシステムのスーパブロックからinodeおよびをsocketを取得し、sock_map_fd()でFILEを取得し、FILE IDにセットします。file->private_dataにはsockが設定されています。
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
       int retval;
       struct socket *sock;
       int flags;

       flags = type & ~SOCK_TYPE_MASK;
       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
               return -EINVAL;
       type &= SOCK_TYPE_MASK;

       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

       retval = sock_create(family, type, protocol, &sock);
       if (retval < 0)
               goto out;

       retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
       if (retval < 0)
               goto out_release;

out:
       return retval;

out_release:
       sock_release(sock);
       return retval;
}
sock_create()は引数チェックして、sock_alloc()がコールし、ソケットファイルシステムのスーパブロックからinode/sockを取得します。

percpu_add()は、CPU変数(CPU毎に割り当てている変数で、ロックすることなく参照できます。)のsockets_in_useをインクリメントします。これは/proc/net/sockstatのsockets: usedで参照されます。
static struct socket *sock_alloc(void)
{
       struct inode *inode;
       struct socket *sock;

       inode = new_inode_pseudo(sock_mnt->mnt_sb);
       if (!inode)
               return NULL;

       sock = SOCKET_I(inode);

       kmemcheck_annotate_bitfield(sock, type);
       inode->i_ino = get_next_ino();
       inode->i_mode = S_IFSOCK | S_IRWXUGO;
       inode->i_uid = current_fsuid();
       inode->i_gid = current_fsgid();

       percpu_add(sockets_in_use, 1);
       return sock;
}

int sock_map_fd(struct socket *sock, int flags)
{
       struct file *newfile;
       int fd = sock_alloc_file(sock, &newfile, flags);

       if (likely(fd >= 0))
               fd_install(fd, newfile);

       return fd;
}
current->filesから空きのfdを取得し、alloc_file()でFILEを取得します。file->f_op = socket_file_opsとなりますが、以降file->f_pos = 0としてますので、ソケットに関してはfileでのread/writeはできないようです。
static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
{
       struct qstr name = { .name = "" };
       struct path path;
       struct file *file;
       int fd;

       fd = get_unused_fd_flags(flags);
       if (unlikely(fd < 0))
               return fd;

       path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
       if (unlikely(!path.dentry)) {
               put_unused_fd(fd);
               return -ENOMEM;
       }
       path.mnt = mntget(sock_mnt);

       d_instantiate(path.dentry, SOCK_INODE(sock));
       SOCK_INODE(sock)->i_fop = &socket_file_ops;

       file = alloc_file(&path, FMODE_READ | FMODE_WRITE,
                 &socket_file_ops);
       if (unlikely(!file)) {
               /* drop dentry, keep inode */
               ihold(path.dentry->d_inode);
               path_put(&path);
               put_unused_fd(fd);
               return -ENFILE;
       }

       sock->file = file;
       file->f_flags = O_RDWR | (flags & O_NONBLOCK);
       file->f_pos = 0;
       file->private_data = sock;

       *f = file;
       return fd;
}

struct file *alloc_file(struct path *path, fmode_t mode,
               const struct file_operations *fop)
{
       struct file *file;

       file = get_empty_filp();
       if (!file)
               return NULL;

       file->f_path = *path;
       file->f_mapping = path->dentry->d_inode->i_mapping;
       file->f_mode = mode;
       file->f_op = fop;

       if ((mode & FMODE_WRITE) && !special_file(path->dentry->d_inode->i_mode)) {
               file_take_write(file);
               WARN_ON(mnt_clone_write(path->mnt));
       }
       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
               i_readcount_inc(path->dentry->d_inode);
       return file;
}

補足

ファイルオペレーションコールバックは、参照位置をブロック位置に変換し、アドレスマップのコールバックをコールして実デバイス(キャッシュも含めた)とのやり取りを行う介添え的な役割となります。

socketはfile->f_pos = 0と言うことで、FILEをread/writeする様に読み書きできないようですが、実装としてはvfsに構造に基づいた物だと言う事です。


最終更新 2014/11/15 16:47:11 - north
(2014/11/15 16:47:11 作成)


検索

アクセス数
3588359
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。