マルチCPU(補足)
Rev.2を表示中。最新版はこちら。
先のマルチCPUの記載で、プロセスの実行しているCPU ID取得のユーザ空間での実装がされてないとの認識でしたが、さらにCPU IDの検証をしましたら、スペースを区切りとするプロセス状態を表示する/proc/self/statの38項目に実装されています。(cutの-f39は取得項目の末尾がスペースとなる項目で、38項目の取得となります。)[root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 0 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 0 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 1 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 1 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 1 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 0 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 1 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 1 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39 0 [root@localhost ~]# cat /proc/self/stat | cut -d ' ' -f39/proc/tid/statのコールバックです。selfはcurrentで、tidにより起動済み任意プロセスのCPU IDも確認できます。検証では38項目をCPU IDとして取得していますが、do_task_stat()のtask_cpu(task)は37項目です。これはseq_printf()のフォーマットに20項目目を区切りとして0を追加している故です。
int proc_tid_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
{
return do_task_stat(m, ns, pid, task, 0);
}
static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task, int whole)
{
unsigned long vsize, eip, esp, wchan = ~0UL;
long priority, nice;
int tty_pgrp = -1, tty_nr = 0;
sigset_t sigign, sigcatch;
char state;
pid_t ppid = 0, pgid = -1, sid = -1;
int num_threads = 0;
int permitted;
struct mm_struct *mm;
unsigned long long start_time;
unsigned long cmin_flt = 0, cmaj_flt = 0;
unsigned long min_flt = 0, maj_flt = 0;
cputime_t cutime, cstime, utime, stime;
cputime_t cgtime, gtime;
unsigned long rsslim = 0;
char tcomm[sizeof(task->comm)];
unsigned long flags;
state = *get_task_state(task);
vsize = eip = esp = 0;
permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
mm = get_task_mm(task);
if (mm) {
vsize = task_vsize(mm);
if (permitted) {
eip = KSTK_EIP(task);
esp = KSTK_ESP(task);
}
}
get_task_comm(tcomm, task);
sigemptyset(&sigign);
sigemptyset(&sigcatch);
cutime = cstime = utime = stime = 0;
cgtime = gtime = 0;
if (lock_task_sighand(task, &flags)) {
struct signal_struct *sig = task->signal;
if (sig->tty) {
struct pid *pgrp = tty_get_pgrp(sig->tty);
tty_pgrp = pid_nr_ns(pgrp, ns);
put_pid(pgrp);
tty_nr = new_encode_dev(tty_devnum(sig->tty));
}
num_threads = get_nr_threads(task);
collect_sigign_sigcatch(task, &sigign, &sigcatch);
cmin_flt = sig->cmin_flt;
cmaj_flt = sig->cmaj_flt;
cutime = sig->cutime;
cstime = sig->cstime;
cgtime = sig->cgtime;
rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
if (whole) {
struct task_struct *t = task;
do {
min_flt += t->min_flt;
maj_flt += t->maj_flt;
gtime += t->gtime;
t = next_thread(t);
} while (t != task);
min_flt += sig->min_flt;
maj_flt += sig->maj_flt;
thread_group_times(task, &utime, &stime);
gtime += sig->gtime;
}
sid = task_session_nr_ns(task, ns);
ppid = task_tgid_nr_ns(task->real_parent, ns);
pgid = task_pgrp_nr_ns(task, ns);
unlock_task_sighand(task, &flags);
}
if (permitted && (!whole || num_threads < 2))
wchan = get_wchan(task);
if (!whole) {
min_flt = task->min_flt;
maj_flt = task->maj_flt;
task_times(task, &utime, &stime);
gtime = task->gtime;
}
priority = task_prio(task);
nice = task_nice(task);
start_time =
(unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC
+ task->real_start_time.tv_nsec;
start_time = nsec_to_clock_t(start_time);
seq_printf(m, "%d (%s) %c %d %d %d %d %d %u %lu \
%lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \
%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld %lu %lu %lu\n",
pid_nr_ns(pid, ns),
tcomm,
state,
ppid,
pgid,
sid,
tty_nr,
tty_pgrp,
task->flags,
10 min_flt,
cmin_flt,
maj_flt,
cmaj_flt,
cputime_to_clock_t(utime),
cputime_to_clock_t(stime),
cputime_to_clock_t(cutime),
cputime_to_clock_t(cstime),
priority,
nice,
20 num_threads,
start_time,
vsize,
mm ? get_mm_rss(mm) : 0,
rsslim,
mm ? (permitted ? mm->start_code : 1) : 0,
mm ? (permitted ? mm->end_code : 1) : 0,
(permitted && mm) ? mm->start_stack : 0,
esp,
task->pending.signal.sig[0] & 0x7fffffffUL,
30 task->blocked.sig[0] & 0x7fffffffUL,
sigign .sig[0] & 0x7fffffffUL,
sigcatch .sig[0] & 0x7fffffffUL,
wchan,
0UL,
0UL,
task->exit_signal,
37 task_cpu(task), <---------------------------- CPU ID
task->rt_priority,
task->policy,
(unsigned long long)delayacct_blkio_ticks(task),
cputime_to_clock_t(gtime),
cputime_to_clock_t(cgtime),
(mm && permitted) ? mm->start_data : 0,
(mm && permitted) ? mm->end_data : 0,
(mm && permitted) ? mm->start_brk : 0);
if (mm)
mmput(mm);
return 0;
}
static inline unsigned int task_cpu(const struct task_struct *p)
{
return task_thread_info(p)->cpu;
}






