質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

1回答

2353閲覧

ファイルディスクリプタにソケットが結び付けられるタイミングを教えてください

u_09

総合スコア18

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OS

OS(オペレーティングシステム)は、システムソフトウェアの一種であり、一般的に、ハードウェアを直接的に管理・操作する最も中心的な機能を有するソフトウェアがオペレーティングシステムとして呼ばれます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

1クリップ

投稿2018/01/31 08:58

編集2018/01/31 13:44

カーネルコード内での実装についての質問です. よろしければ こちら の質問も参照していただけると幸いです.

task_strcut 構造体がわかっている場合, 以下のようなコードで /proc/[pid]/fd と同一の情報が取得できると思います.

struct sock *sk; struct files_struct *files; struct fdtable fdtab; struct inet_sock *inet; files = task->files; fdtab = files->fdtab; unsigned int i = 0; for (i = 3; i < fdtab.max_fds; ++i) { if (!fdtab.fd[i]) break; if (!fcheck_files(files, i)) continue; if (!(sk = get_sock(fdtab.fd[i])) || !(inet = inet_sk(sk))) continue; // ここで inet から IP アドレスなどのソケット情報を得る }

質問としてはこの fd[i] のポインタが指す先のデータ (この場合はソケットの情報) がどこで登録されているのかということを教えていただきたいです (ポインタが指す先のメモリの確保のタイミングではなく, 情報が結び付けられるタイミング). ソケット生成の (bind() とか sock_create() とか) あたりを辿っても task_struct がありませんし, どのタイミングで紐付けられているのかがわかりません. カーネルのバージョンは 4.4.0-87-generic を使用しています.

回答よろしくお願いいたします.

頂いた回答に対しての追記

#include <net/inet_sock.h> // inet_sk() static struct sock *get_sock(struct file *fd) { struct path f_path = fd->f_path; struct dentry *dentry; struct inode *inode; struct socket *sock; if (!(dentry = f_path.dentry)) return NULL; if (!(inode = dentry->d_inode)) return NULL; if (!(sock = SOCKET_I(inode))) return NULL; return sock->sk; } void __fd_install(struct files_struct *files, unsigned int fd, struct file *file) { struct fdtable *fdt; might_sleep(); rcu_read_lock_sched(); while (unlikely(files->resize_in_progress)) { rcu_read_unlock_sched(); wait_event(files->resize_wait, !files->resize_in_progress); rcu_read_lock_sched(); } /* coupled with smp_wmb() in expand_fdtable() */ smp_rmb(); fdt = rcu_dereference_sched(files->fdt); BUG_ON(fdt->fd[fd] != NULL); rcu_assign_pointer(fdt->fd[fd], file); rcu_read_unlock_sched(); // 追加箇所 if (fdt->fd[fd]) { struct sock *sk; struct inet_sock *inet; if (sk = get_sock(fdt->fd[fd])) { if ((inet = inet_sk(sk))) { // ここがエラーになる __be32 addr = inet->inet_daddr; __u16 port = ntohs(inet->inet_dport); printk(KERN_EMERG "[%d] %08X:%04X\n", current->pid, addr, port); } } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_09

2018/01/31 09:34

alloc_fdtable() 見てみます. ありがとうございます! fd[i] は struct file のポインタだと認識しているのですが違うのでしょうか?
mattn

2018/01/31 09:40

あ、失礼しました。struct file のポインタですね。
u_09

2018/01/31 09:45 編集

教えていただいた alloc_fdtable() ですが, 見てみたところ fdtable 自体を生成している関数ではないでしょうか (メモリ確保など). また, fdtable->fd についても, これのメモリを確保しているように見えます. ``` struct fdtable { unsigned int max_fds; struct file __rcu **fd; /* current fd array */ unsigned long *close_on_exec; unsigned long *open_fds; unsigned long *full_fds_bits; struct rcu_head rcu; }; ``` 各要素にデータを入れている箇所には見えないのですがどうでしょうか.
u_09

2018/01/31 09:46

すみません。フォーマットが崩れて見づらくなってしまいました。
mattn

2018/01/31 09:47

質問文から読み取れなかったのでアロケートの箇所だけお伝えしました。
u_09

2018/01/31 09:57 編集

確かに聞き方が悪かったです. すみませんでした. 聞きたいこととしてはデータが結び付けられるタイミングです. つまり, ソケットが生成され, それがプロセスのもつ fd と結び付けられる場所を聞きたかったです (最終的に取得したいのは IP アドレスなどのソケットの情報です). 質問文も修正しておきます.
guest

回答1

0

ベストアンサー

fd と fdtable を結びつけるのはここではないでしょうか。

https://github.com/torvalds/linux/blob/72906f38934a49faf4d2d38ea9ae32adcf7d5d0c/fs/file.c#L617

投稿2018/01/31 09:58

編集2018/01/31 09:59
mattn

総合スコア5030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_09

2018/01/31 13:45

実際に試してみたところ, 教えていただいたとおり fd_install() で fd にデータを入れていそうでした. ここからは, 私の質問がそもそもおかしかったのですが, 色々試してみた結果です (質問にコードを追記しました). inet へのアクセスでエラーとなっているようで起動に失敗してしまうためソケットに関してはこの部分で取得するのは難しそうでした. 考えてみれば, ファイルディスクリプタの生成 => ソケットの生成 => ソケットへの情報のバインドの順なのに, ファイルディスクリプタの生成時点でソケットの情報は取れないですよね. 教えていただいて, 試してみて気づくことができました. ありがとうございました. ソケットに関してはまた別のアプローチで取得したいと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問