微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式系统中进程间通信的监视方法

嵌入式系统中进程间通信的监视方法

时间:10-08 来源:互联网 点击:

用来获得截获的系统调用的参数; traced_process 则是被监视进程的 PID 值。

             traced_process = atoi(argv[1]); /* 从命令行得到监视进程的PID */
             ptrace(PTRACE_ATTACH, traced_process, NULL, NULL);                           
             wait(status);    /* 等待被监视进程状态变化 */
             ptrace(PTRACE_SYSCALL, traced_process, NULL, NULL);

参数为 PTRACE_ATTACH 的 ptrace 对被监视进程在内核中的进程结构进行修改。使被监视进程成为当前程序的子进程。一旦被监视进程的状态发生变化, wait() 将返回。程序再次调用 ptrace 。这次的参数为 PTRACE_SYSCALL 。被监视进程的进程结构再次被修改,其 trace 标志被激活。内核将在被监视进程的每一次系统调用时,触发当前程序的运行。

             While (1) {
                 /* 等待被监视程序调用系统调用或是发生其它状态变化 */
                 wait(status); 
                 
                 /* 如果被监视进程退出,函数返回真。程序退出 */
                 if ( WIFEXITED(status) ) 
                     break;
                 
                 ptrace(PTRACE_GETREGS, traced_process, 0, u_in);
                 if (u_in.orig_eax == 102  u_in.ebx == SYS_SENDTO) { 
                     if (syscall_entry == 0) {  /* syscall entry */
                         insyscall = 1;
                         printf(call sendto()\n);
                     }                           
                     else {  /* Syscall exit */
                         Syscall_entry = 0;
                     }
                 }
                 ptrace(PTRACE_SYSCALL, traced_process, NULL, NULL);
              } /* while */
 
                           return 0;
                      }  /* main */

被监视进程的 trace 标志被激活后,它的每一次系统调用都会被内核检查。我们程序也随之被内核用信号通知。使用参数 PTRACE_GETREGS 的 ptrace() 将获得截获的系统调用的参数。最重要的参数是系统调用号。它保存在了 u_in.orig_eax 中。通过系统调用号,我们可以确定发生的是那一个系统调用。系统调用号可以在 Linux 的源代码中查找。它的定义在 linux-source-2.6.xx/arch/x86/kernel/syscall_table_32.S 中。它的部分代码如下所示:

            .long sys_fstatfs       /* 100 */
            .long sys_ioperm
            .long sys_socketcall
            .long sys_syslog

在这里,我们最关心的是 sendto 系统调用。在 Linux 的内核中, sendto 的真实入口是 socketcall 系统调用。它是 bind , sendto 等socket相关系统调用的入口。在这个系统调用中,通过一个 call number来区分出 bind , sendto 等不同的子系统调用。在我们的程序中,这个 call number 保存在 u_in.ebx 中。 从上面的 syscall_table_32.S 示例代码就可以看出, socketcall 的系统调用号是102(从100向下数两行)。而 call number 则在 net.h 有定义,我们关心的 sendto 的 call number 被定义为 SYS_SENDTO ,其绝对值为11。有了这两个重要的数据,我们的程序据此判断当前发生的系统调用是否为 sendto 。这一点表现为代码:

             if (u_in.orig_eax == 102  u_in.ebx == SYS_SENDTO)                            

被监视进程进入系统调用和退出系统调用时,都会触发 wait() 返回,使我们的程序有机会运行。因此,我们需要使用 syscall_entry 来记录当前时刻是被监视进程进入系统调用,还是退出系统调用。这是一个开关量,非常容易理解。 最后,每次处理完,都需要再次调用参数为 PTRACE_SYSCALL 的 ptrace ,准备监视下一次的系统调用。

上面的程序虽然很简单,但已经可以完整的表现出利用 ptrace 截获被监视进程的 sendto 系统调用的过程。值得补充一点的是,利用 ptrace 也可以获得 sendto 向外发送的数据。

sendto 系统调用的定义是:

        #include sys/types.h>
        #include sys/socket.h>
        size_t sendto(int s, const void *msg, size_t len, int flags, \
                      const struct sockaddr *to, socket len_t tolen);

sendto 包含了六个参数,特别是 msg 参数指出了发送的数据内容。参数 to 指出了发送的目标。利用 PTR

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top