【问题标题】:Perl - how to unpack psinfo binary file on Solaris 10Perl - 如何在 Solaris 10 上解压 psinfo 二进制文件
【发布时间】:2018-03-30 14:16:49
【问题描述】:

我正在尝试从 Solaris 10 上的 /proc/psinfo 文件中获取信息。它是一个二进制文件,因此想使用 Perl 解包对其进行解码。 不幸的是,我在为 Perl unpack 命令构建模板时遇到了麻烦。 psinfo结构如下

typedef struct psinfo {
int pr_flag;              /* process flags (DEPRECATED: see below) */
int pr_nlwp;              /* number of active lwps in the process */
int pr_nzomb;             /* number of zombie lwps in the process */
pid_t pr_pid;             /* process id */
pid_t pr_ppid;            /* process id of parent */
pid_t pr_pgid;            /* process id of process group leader */
pid_t pr_sid;             /* session id */
uid_t pr_uid;             /* real user id */
uid_t pr_euid;            /* effective user id */
gid_t pr_gid;             /* real group id */
gid_t pr_egid;            /* effective group id */
uintptr_t pr_addr;        /* address of process */
size_t pr_size;           /* size of process image in Kbytes */
size_t pr_rssize;         /* resident set size in Kbytes */
dev_t pr_ttydev;          /* controlling tty device (or PRNODEV) */
ushort_t pr_pctcpu;       /* % of recent cpu time used by all lwps */
ushort_t pr_pctmem;       /* % of system memory used by process */
timestruc_t pr_start;     /* process start time, from the epoch */
timestruc_t pr_time;      /* cpu time for this process */
timestruc_t pr_ctime;     /* cpu time for reaped children */
char pr_fname[PRFNSZ];    /* name of exec'ed file */
char pr_psargs[PRARGSZ];  /* initial characters of arg list */
int pr_wstat;             /* if zombie, the wait() status */
int pr_argc;              /* initial argument count */
uintptr_t pr_argv;        /* address of initial argument vector */
uintptr_t pr_envp;        /* address of initial environment vector */
char pr_dmodel;           /* data model of the process */
lwpsinfo_t pr_lwp;        /* information for representative lwp */
taskid_t pr_taskid;       /* task id */
projid_t pr_projid;       /* project id */
poolid_t pr_poolid;       /* pool id */
zoneid_t pr_zoneid;       /* zone id */
ctid_t pr_contract;       /* process contract id */
} psinfo_t;

但由于我对 C 一无所知,我确实在解锁模板中表示各种 psinfo 数据类型时遇到了麻烦。 我还尝试使用 hexdump/xxd 查看 psinfo 文件以查看我可以期待哪些数据,但这对我没有多大帮助。

到目前为止,我已经设法准备好了

#!/usr/bin/perl -w

use strict;
use warnings;
use Data::Dumper;

opendir(PROC,"/proc") or die "Unable to open /proc:$!\n";
while (defined($_= readdir(PROC))){
    next if ($_ eq "." or $_ eq "..");
    next unless /^\d+$/; # filter out any random non-pid files
    open(PSINFO, "/proc/$_/psinfo");
    local $/;
    read(PSINFO, my $psinfo,1000);
    close PSINFO;

    my @psinfoInfo = unpack("iiiiiiiiiiIiiiiSSi2i2i2Z16Z80iiIIaa3iiiiii", $psinfo);
    print "'@psinfoInfo'\n";

}
closedir(PROC);

输出如下

'33554432 1 7871 4646 7871 4646 3339 3339 1087 1087 0 0 0 0 6291464 1 0 1522419148 159507010 0 113016534 0 0 top top 0 1 0 0   986003 3 0 0 0 924925'
'33554432 1 8323 9639 8323 9639 3339 3339 1087 1087 0 4116 2812 0 6291463 0 0 1522419159 626531984 0 39242598 0 0 processChecker. /usr/bin/perl -w ./processChecker.pl 0 3 134511508 134511524   986024 3 0 0 0 924944'
'33554432 1 8147 8146 2165 2165 3339 3339 1087 1087 0 6668 4060 0 -1 0 0 1522408545 333100499 0 513142054 0 0 sshd /usr/lib/ssh/sshd 0 1 134512284 134512292   984753 3 0 0 0 923830'
'33554432 1 21997 8153 21997 8153 3339 3339 1087 1087 0 2400 1504 0 6291458 0 0 1522410593 434583624 0 204410711 0 0 vi vi processChecker.pl 0 2 134511556 134511568   984753 3 0 0 0 923830'

但它与 psinfo 定义并不真正对应。例如进程名称被截断,时间值为 NOK 等。

我知道,有 Proc::processTable 可用,我不想重新发明轮子,但由于各种原因,我不能使用该模块,这很重要。

我检查了http://perldoc.perl.org/perlpacktut.htmlhttp://perldoc.perl.org/functions/pack.html,但仍然...

编辑:基于@borodins 建议使用简短的 C 代码,我还设法在我的机器上获得了数据类型的长度

Size of int: 4 bytes
Size of long: 4 bytes
Size of float: 4 bytes
Size of double: 8 bytes
Size of char: 1 byte
Size of pid_t: 4 bytes
Size of uid_t: 4 bytes
Size of gid_t: 4 bytes
Size of uintptr_t: 4 bytes
Size of size_t: 4 bytes
Size of dev_t: 4 bytes
Size of ushort_t: 2 bytes
Size of timestruc_t: 8 bytes
Size of lwpsinfo_t: 104 bytes
Size of taskid_t: 4 bytes
Size of projid_t: 4 bytes   
Size of poolid_t: 4 bytes
Size of zoneid_t: 4 bytes
Size of ctid_t: 4 bytes
Size of time_t: 4 bytes

有人吗?

【问题讨论】:

  • 某些类型的大小会根据您使用的计算机体系结构而变化。我建议您编写一个 C 程序,使用 sizeof(uintptr_t) 等在目标机器上打印每种不同类型的大小。您可以增强相同的程序以输出 Perl unpack 格式。
  • @Borodin 正如我所写,我不知道 C。无论如何我可以在 Perl 中实现你的建议吗?
  • 而您对发现没有兴趣或兴趣?我认为你做错了工作。即使对 C 有一点了解,也能在未来软件开发的许多方面为您提供帮助。
  • 试试p3rl.org/Convert::Binary::C - 我无法测试,没有 Solaris。
  • timestruct_t 是一个 C 结构,由多个字段组成,例如 psinfo_t。您必须单独解压缩每个字段。

标签: perl process solaris pack


【解决方案1】:

为了不让更多编辑混淆观众,我将在此处发布答案。其实很简单

  1. 我从我的系统中获得了正确的 psinfo 信息。在我的系统(Solaris 10 1/13 s10x_u11wos_24a X86)上,它存储在 /usr/local/include/sys/procfs.h

    typedef struct psinfo {
        int     pr_flag;        /* process flags (DEPRECATED; do not use) */
        int     pr_nlwp;        /* number of active lwps in the process */
        pid_t   pr_pid;         /* unique process id */
        pid_t   pr_ppid;        /* process id of parent */
        pid_t   pr_pgid;        /* pid of process group leader */
        pid_t   pr_sid;         /* session id */
        uid_t   pr_uid;         /* real user id */
        uid_t   pr_euid;        /* effective user id */
        gid_t   pr_gid;         /* real group id */
        gid_t   pr_egid;        /* effective group id */
        uintptr_t pr_addr;      /* address of process */
        size_t  pr_size;        /* size of process image in Kbytes */
        size_t  pr_rssize;      /* resident set size in Kbytes */
        size_t  pr_pad1;
        dev_t   pr_ttydev;      /* controlling tty device (or PRNODEV) */
                    /* The following percent numbers are 16-bit binary */
                    /* fractions [0 .. 1] with the binary point to the */
                    /* right of the high-order bit (1.0 == 0x8000) */
        ushort_t pr_pctcpu;     /* % of recent cpu time used by all lwps */
        ushort_t pr_pctmem;     /* % of system memory used by process */
        timestruc_t pr_start;   /* process start time, from the epoch */
        timestruc_t pr_time;    /* usr+sys cpu time for this process */
        timestruc_t pr_ctime;   /* usr+sys cpu time for reaped children */
        char    pr_fname[PRFNSZ];       /* name of execed file */
        char    pr_psargs[PRARGSZ];     /* initial characters of arg list */
        int     pr_wstat;       /* if zombie, the wait() status */
        int     pr_argc;        /* initial argument count */
        uintptr_t pr_argv;      /* address of initial argument vector */
        uintptr_t pr_envp;      /* address of initial environment vector */
        char    pr_dmodel;      /* data model of the process */
        char    pr_pad2[3];
        taskid_t pr_taskid;     /* task id */
        projid_t pr_projid;     /* project id */
        int     pr_nzomb;       /* number of zombie lwps in the process */
        poolid_t pr_poolid;     /* pool id */
        zoneid_t pr_zoneid;     /* zone id */
        id_t    pr_contract;    /* process contract */
        int     pr_filler[1];   /* reserved for future use */
        lwpsinfo_t pr_lwp;      /* information for representative lwp */
    } psinfo_t;
    
  2. 解压 psinfo 二进制文件的那段代码没问题。只有我没有意识到 timestruc_t 有两个元素,秒和纳秒。均为 LONG 类型。 (感谢鲍罗丁)

  3. 下面是一段 C 代码,它显示了所使用的不同数据类型的大小

    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>             /* UNIX dirs       POSIX */
    #include <errno.h>              /* error stf       POSIX */
    #include <fcntl.h>              /* UNIX file ctrl  UNIX  */
    #include <procfs.h>             /* Solaris proc    SUN   */
    #include <string.h>             /* Strings         C89   */
    #include <sys/stat.h>           /* UNIX stat       POSIX */
    #include <sys/types.h>          /* UNIX types      POSIX */
    
     int main() 
            {
              int integerType;
              long long_type;
              float floatType;
              double doubleType;
              char charType;
              pid_t pid_t_type;
              uid_t uid_t_type;
              gid_t gid_t_type;
              uintptr_t uintptr_t_type;
              size_t size_t_type;
              dev_t dev_t_type;
              ushort_t ushort_t_type;
              timestruc_t timestruc_t_type;
              lwpsinfo_t lwpsinfo_t_type;
              taskid_t taskid_t_type;
              projid_t projid_t_type;
              poolid_t poolid_t_type;
              zoneid_t zoneid_t_type;
              ctid_t ctid_t_type;
              time_t time_t_type;
            // Sizeof operator is used to evaluate the size of a variable
              printf("Size of int: %ld bytes\n",sizeof(integerType));
              printf("Size of long: %ld bytes\n",sizeof(long_type));
              printf("Size of float: %ld bytes\n",sizeof(floatType));
              printf("Size of double: %ld bytes\n",sizeof(doubleType));
               printf("Size of char: %ld byte\n",sizeof(charType));
               printf("Size of pid_t: %ld bytes\n",sizeof(pid_t_type));
               printf("Size of uid_t: %ld bytes\n",sizeof(uid_t_type));
               printf("Size of gid_t: %ld bytes\n",sizeof(gid_t_type));
               printf("Size of uintptr_t: %ld bytes\n",sizeof(uintptr_t_type));
               printf("Size of size_t: %ld bytes\n",sizeof(size_t_type));
               printf("Size of dev_t: %ld bytes\n",sizeof(dev_t_type));
               printf("Size of ushort_t: %ld bytes\n",sizeof(ushort_t_type));
               printf("Size of timestruc_t: %ld bytes\n",sizeof(timestruc_t_type));
               printf("Size of lwpsinfo_t: %ld bytes\n",sizeof(lwpsinfo_t_type));
               printf("Size of taskid_t: %ld bytes\n",sizeof(taskid_t_type));
               printf("Size of projid_t: %ld bytes\n",sizeof(projid_t_type));
               printf("Size of poolid_t: %ld bytes\n",sizeof(poolid_t_type));
               printf("Size of zoneid_t: %ld bytes\n",sizeof(zoneid_t_type));
               printf("Size of ctid_t: %ld bytes\n",sizeof(ctid_t_type));
               printf("Size of time_t: %ld bytes\n",sizeof(time_t_type));
    
            return 0;
            }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多