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 をいじるといいらしい。