funini.com 自由研究 モジュール
static unsigned long dt_thres = 100; // make some time if(currnet->bw_thres > 0){ for(;;) { current->sock_rcvd += ret; dt = jiffies - current->prev_jiffies; bw = (current->sock_rcvd - current->prev_sock_rcvd) / dt; if(bw >= current->bw_thres){ schedule_timeout(100); continue; } break; } if(dt < dt_thres){ current->rcvd_sock_rcvd = current->sock_rcvd; current->prev_jiffies = jiffies; } } 1. プロセス構造体の拡張 include/linux/sched.h の task_struct 構造体にメンバを追加する。 ---------------------------------------------------------------------- struct task_struct { volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; atomic_t usage; ... unsigned long sock_rcvd; unsigned long prev_sock_rcvd; unsigned long bw_thres; unsigned long prev_jiffies; }; ---------------------------------------------------------------------- TODO: sock_rcvd の初期化 2. recv() が呼ばれるたびに、受信量を更新 net/socket.c の sys_recv() を編集。 ---------------------------------------------------------------------- asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, unsigned flags) { // コメントアウト // return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); + long ret = sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); + current->sock_rcvd += ret; + return ret; } ---------------------------------------------------------------------- 3. /proc/PID/sock_rcvd を追加 fs/proc/base.c を編集し、/proc/PID/sock_rcvd を追加する。 ここを読むと、task_struct 構造体の sock_rcvd メンバが読めるようにする。 まず、tgif_base_stuff 配列にエントリを追加する。 ---------------------------------------------------------------------- static const struct pid_entry tgid_base_stuff[] = { DIR("task", S_IRUGO|S_IXUGO, task), DIR("fd", S_IRUSR|S_IXUSR, fd), DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), ... + INF("sock_rcvd", S_IRUGO, sock_rcvd), ... }; ---------------------------------------------------------------------- INF の最後の引数に sock_rcvd と書いたので、その先頭に proc_ を付けた proc_sock_rcvd という関数を宣言する。 ---------------------------------------------------------------------- + static int proc_sock_rcvd(struct task_struct *task, char *buffer) + { + return sprintf(buffer, "%lu\n", + task->sock_rcvd); + } ---------------------------------------------------------------------- これでカーネルをビルドし、起動すると、/proc/PID/sock_rcvd から 送信量を取得できるようになる。下に表示例を示す。 ---------------------------------------------------------------------- # cat /proc/1011/sock_rcvd 1102334 ---------------------------------------------------------------------- sysfs に関する情報 Documentation/filesystems/sysfs.txt fs/libfs.c include/linux/fs.h の somple attribute files をいじるといいらしい。