カーネルコード内での実装についての質問です. よろしければ こちら の質問も参照していただけると幸いです.
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); } } } }
回答1件
あなたの回答
tips
プレビュー