/proc/pid/syscall


/proc/pid/syscallはプロセスがシステムコール下で待機しているなら、そのシステムコールの情報(引数)を表示します。システムコール外での待機なら、runningとなります。

サンプル1
#include <sys/syscall.h>
#include <stdio.h>

void    main(int argc, char* argv[])
{
       char    buff[0x123];

       printf("%d:%lx\n", SYS_read, buff);
       syscall(SYS_read, 0, buff, sizeof(buff));
}

[root@localhost test]# ./a.out &
[1] 1662
[root@localhost test]# 3:bff98e5d

[1]+  停止                    ./a.out
[root@localhost test]# cat /proc/1662/syscall
3 0x0 0xbff98e5d 0x123 0x8 0x8 0x7 0xbff98e1c 0xb7737424
サンプル2
#include <sys/syscall.h>
#include <stdio.h>

void    main(int argc, char* argv[])
{
   while(1) {
       ;
   }
}

[root@localhost test]# ./a.out &
[1] 1643
[root@localhost test]# cat /proc/1643/syscall
running
システムコールはeaxにシステムコール番号を設定し、bx/cx・・・に引数が設定されint 80またはsysenterによりsystem_callカーネルスタックにpushし、sys_call_tableのeaxを引数とするアドレスをコールします。従ってシステムコールで待機しているなら、スタックはカーネルモードで、そうでないならユーザモードとなります。
ENTRY(system_call)
        pushl %eax                      # save orig_eax
        cld;
        pushl %es; 
        pushl %ds; 
        pushl %eax; 
        pushl %ebp; 
        pushl %edi;                     # 第 5 引数 
        pushl %esi;                     # 第 4 引数 
        pushl %edx;                     # 第 3 引数 
        pushl %ecx;                     # 第 2 引数 
        pushl %ebx;                     # 第 1 引数 
        movl $(__KERNEL_DS),%edx; 
        movl %dx,%ds; 
        movl %dx,%es; 
        movl %esp, %ebx; 
        andl $-8192, %ebx; 
        cmpl $(NR_syscalls),%eax 
        jae badsys 
        testb $0x20,flags(%ebx)         # PF_TRACESYS 
        jne tracesys 
        call *SYMBOL_NAME(sys_call_table)(,%eax,4) 
                                        # eax のシステムコールに対応する 
                                        # 関数を呼ぶ 
        movl %eax,EAX(%esp)             # スタック上のeaxに返り値設定 
        popl %ebx; 
        popl %ecx; 
        popl %edx; 
        popl %esi; 
        popl %edi; 
        popl %ebp; 
        popl %eax;                      # 返り値設定済み 
        popl %ds; 
        popl %es; 
        addl $4,%esp;                   # 最初の pushl %eax の分を捨てる 
        iret; 
 
static int proc_pid_syscall(struct task_struct *task, char *buffer)
{
       long nr;
       unsigned long args[6], sp, pc;
       int res = lock_trace(task);
       if (res)
               return res;

       if (task_current_syscall(task, &nr, args, 6, &sp, &pc))
               res = sprintf(buffer, "running\n");
       else if (nr < 0)
               res = sprintf(buffer, "%ld 0x%lx 0x%lx\n", nr, sp, pc);
       else
               res = sprintf(buffer,
                      "%ld 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
                      nr,
                      args[0], args[1], args[2], args[3], args[4], args[5],
                      sp, pc);
       unlock_trace(task);
       return res;
}

int task_current_syscall(struct task_struct *target, long *callno,
                        unsigned long args[6], unsigned int maxargs,
                        unsigned long *sp, unsigned long *pc)
{
       long state;
       unsigned long ncsw;

       if (unlikely(maxargs > 6))
               return -EINVAL;

       if (target == current)
               return collect_syscall(target, callno, args, maxargs, sp, pc);

       state = target->state;
       if (unlikely(!state))
               return -EAGAIN;

       ncsw = wait_task_inactive(target, state);
       if (unlikely(!ncsw) ||
           unlikely(collect_syscall(target, callno, args, maxargs, sp, pc)) ||
           unlikely(wait_task_inactive(target, state) != ncsw))
               return -EAGAIN;

       return 0;
}

static int collect_syscall(struct task_struct *target, long *callno,
                          unsigned long args[6], unsigned int maxargs,
                          unsigned long *sp, unsigned long *pc)
{
       struct pt_regs *regs = task_pt_regs(target);
       if (unlikely(!regs))
               return -EAGAIN;

       *sp = user_stack_pointer(regs);
       *pc = instruction_pointer(regs);

       *callno = syscall_get_nr(target, regs);
       if (*callno != -1L && maxargs > 0)
               syscall_get_arguments(target, regs, 0, maxargs, args);

       return 0;
}

static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
       return regs->orig_ax;
}

struct pt_regs {
       unsigned long bx;
       unsigned long cx;
       unsigned long dx;
       unsigned long si;
       unsigned long di;
       unsigned long bp;
       unsigned long ax;
       unsigned long ds;
       unsigned long es;
       unsigned long fs;
       unsigned long gs;
       unsigned long orig_ax;
       unsigned long ip;
       unsigned long cs;
       unsigned long flags;
       unsigned long sp;
       unsigned long ss;
};

static inline void syscall_get_arguments(struct task_struct *task,
                                        struct pt_regs *regs,
                                        unsigned int i, unsigned int n,
                                        unsigned long *args)
{
       BUG_ON(i + n > 6);
       memcpy(args, &regs->bx + i, n * sizeof(args[0]));
}

補足

/proc/pid配下のdentryのコールバックです。/procをreaddirすると、namespace下のプロセスを取得し、のプロセスIDをdentry名とするdentryキャッシュ取得します。この時に.proc/pidのreaddirコールバックでtid_base_stuff[]とするキャッシュファイルが作成され、syscallはproc_pid_syscallがfile_operationsコールバックとなります。
struct pid_entry {
       char *name;
       int len;
       umode_t mode;
       const struct inode_operations *iop;
       const struct file_operations *fop;
       union proc_op op;
};

static const struct pid_entry tid_base_stuff[] = {
       DIR("fd",        S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
       DIR("fdinfo",    S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
       DIR("ns",        S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
       REG("environ",   S_IRUSR, proc_environ_operations),
       INF("auxv",      S_IRUSR, proc_pid_auxv),
       ONE("status",    S_IRUGO, proc_pid_status),
       ONE("personality", S_IRUGO, proc_pid_personality),
       INF("limits",    S_IRUGO, proc_pid_limits),
#ifdef CONFIG_SCHED_DEBUG
       REG("sched",     S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
       REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
       INF("syscall",   S_IRUGO, proc_pid_syscall),
#endif
       INF("cmdline",   S_IRUGO, proc_pid_cmdline),
       ONE("stat",      S_IRUGO, proc_tid_stat),
       ONE("statm",     S_IRUGO, proc_pid_statm),
       REG("maps",      S_IRUGO, proc_maps_operations),
#ifdef CONFIG_NUMA
       REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
#endif
       REG("mem",       S_IRUSR|S_IWUSR, proc_mem_operations),
       LNK("cwd",       proc_cwd_link),
       LNK("root",      proc_root_link),
       LNK("exe",       proc_exe_link),
       REG("mounts",    S_IRUGO, proc_mounts_operations),
       REG("mountinfo",  S_IRUGO, proc_mountinfo_operations),
#ifdef CONFIG_PROC_PAGE_MONITOR
       REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
       REG("smaps",     S_IRUGO, proc_smaps_operations),
       REG("pagemap",    S_IRUGO, proc_pagemap_operations),
#endif
#ifdef CONFIG_SECURITY
       DIR("attr",      S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
#ifdef CONFIG_KALLSYMS
       INF("wchan",     S_IRUGO, proc_pid_wchan),
#endif
#ifdef CONFIG_STACKTRACE
       ONE("stack",      S_IRUGO, proc_pid_stack),
#endif
#ifdef CONFIG_SCHEDSTATS
       INF("schedstat", S_IRUGO, proc_pid_schedstat),
#endif
#ifdef CONFIG_LATENCYTOP
       REG("latency",  S_IRUGO, proc_lstats_operations),
#endif
#ifdef CONFIG_PROC_PID_CPUSET
       REG("cpuset",    S_IRUGO, proc_cpuset_operations),
#endif
#ifdef CONFIG_CGROUPS
       REG("cgroup",  S_IRUGO, proc_cgroup_operations),
#endif
       INF("oom_score", S_IRUGO, proc_oom_score),
       REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adjust_operations),
       REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
#ifdef CONFIG_AUDITSYSCALL
       REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
       REG("sessionid",  S_IRUGO, proc_sessionid_operations),
#endif
#ifdef CONFIG_FAULT_INJECTION
       REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
#endif
#ifdef CONFIG_TASK_IO_ACCOUNTING
       INF("io",       S_IRUSR, proc_tid_io_accounting),
#endif
#ifdef CONFIG_HARDWALL
       INF("hardwall",   S_IRUGO, proc_pid_hardwall),
#endif
};

最終更新 2016/04/01 14:09:05 - north
(2016/04/01 14:09:05 作成)


検索

アクセス数
3570085
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。