2015-06-24 67 views
0

我有一個相當簡單的代碼,用於處理solaris中的/ proc/*文件以獲取進程信息和參數。對於它的工作原理在大多數情況下(這意味着它正確地確實存在爭論中的某些進程),但在某些工藝參數(特別是當他們長),它失敗,也許是爲什麼它產生的錯誤Value too large for defined data type解析/ proc psinfo和argv返回:值太大,無法定義的數據類型錯誤

有沒有人有任何想法失敗?

這是pread()線爲參數數組失敗在行108

它實際上是一些Java程序有許多爭論,是否可以幫助它失敗。

有趣太是:

  1. 檢查二進制/proc/<pid>/psinfo文件,它是非常小 - 大小顯然不足以包含我與一些流程看着那種長篇大論。執行psinfo文件內容的十六進制轉儲證實它們不在那裏。

  2. 當長參數爲零時,pr_argv的值。

  3. 在進一步挖掘,它看起來像參數在/proc/(pid)/object/tmpfs.394.2.71404854。我想知道爲什麼。

代碼:

#include <dirent.h> 
#include <ctype.h> 
#include <assert.h> 
#include <malloc.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/processor.h> 
#include <sys/sysinfo.h> 
#include <sys/param.h> 

#include <kstat.h> 
#include <procfs.h> 

#define PROC_ERRNO ((errno == ENOENT) ? ESRCH : errno) 

#define my_pread(fd, ptr, type, offset) \ 
    (pread(fd, ptr, sizeof(type), offset) == sizeof(type)) 

static int proc_psinfo_get(psinfo_t *psinfo, pid_t pid) 
{ 
    int fd, retval = 0; 
    char buffer[BUFSIZ]; 

    sprintf(buffer, "/proc/%d/psinfo", pid); 

    if ((fd = open(buffer, O_RDONLY)) < 0) { 
     return ESRCH; 
    } 

    if (!my_pread(fd, psinfo, psinfo_t, 0)) { 
     retval = errno; 
    } 

    close(fd); 

    return retval; 
} 

int main(int argc, char **argv) 
{ 
    DIR *dirp = opendir("/proc"); 
    struct dirent *ent; 
    char *models[] = { 
     "unknown", "32bit", "64bit" 
    }; 

    while ((ent = readdir(dirp))) { 
     pid_t pid; 
     psinfo_t psinfo; 
     int retval; 
     char buffer[BUFSIZ]; 
     char *argvb[56]; 
     char **argvp = argvb; 

     int n, fd; 
     size_t nread = 0; 
     unsigned int argv_size; 

     if (!isdigit(*ent->d_name)) { 
      continue; 
     } 
     psinfo.pr_dmodel = 0; 
     pid = strtoul(ent->d_name, NULL, 10); 
     retval = proc_psinfo_get(&psinfo, pid); 
     printf("---------------------------------\n"); 
     printf("pid=%d, status=%s, model=%s\n", 
       pid, retval ? strerror(retval) : "OK", 
       models[psinfo.pr_dmodel]); 

     printf("Parent Pid: %ld\n", psinfo.pr_ppid); 
    printf("UID: %ld\n", psinfo.pr_uid); 
    printf("size: %ld\n", psinfo.pr_size); 
    printf("rss: %ld\n", psinfo.pr_rssize); 

     printf("pcpu: %d\n", psinfo.pr_pctcpu); 
    printf("pctmem: %d\n", psinfo.pr_pctmem); 
    printf("zoneid: %d\n", psinfo.pr_zoneid); 

    printf("pr_sname: %c\n", psinfo.pr_lwp.pr_sname); 

    printf("Up Start: (%ld, %ld)\n", psinfo.pr_start.tv_sec, psinfo.pr_start.tv_nsec); 
     printf("Command: %s\n", psinfo.pr_fname); 

    // print argc 
     argv_size = sizeof(*argvp) * psinfo.pr_argc; 
     sprintf(buffer, "/proc/%d/as", pid); 
     printf("argc=%d, argv_size=%d\n", 
       psinfo.pr_argc, argv_size); 

     if ((fd = open(buffer, O_RDONLY)) < 0) { 
      printf("open(%s) == %s\n", 
        buffer, strerror(PROC_ERRNO)); 
      if (argvp != argvb) { 
       free(argvp); 
      } 
      continue; 
     } 

     if (argv_size > sizeof(argvb)) { 
      argvp = malloc(argv_size); 
     } 

     if ((long int)(nread = pread(fd, argvp, argv_size, (off_t)psinfo.pr_argv)) <= 0) { 
      close(fd); 
     printf("error in reading argvp\n"); 
      printf(" pread(%d, 0x%lx, %d, 0x%lx) == %d (%s)\n", 
        fd, (unsigned long)argvp, argv_size, 
        (unsigned long)psinfo.pr_argv, 
        nread, strerror(errno)); 
      continue; 
     } 

    // parse the args here 
     for (n = 0; n < psinfo.pr_argc; n++) { 
      int alen; 
      char *arg; 

      if ((long int)(nread = pread(fd, buffer, sizeof(buffer), (off_t)argvp[n])) <= 0) { 
       close(fd); 
     printf("buffer %d argvp as ld %ld argvp as lu %lu ", sizeof(buffer), argvp[n] , argvp[n]); 
       printf(" %-2d) pread(%d, 0x%lx, %d, 0x%lx) == %d (%s)\n", 
         n, fd, (unsigned long)&buffer[0], sizeof(buffer), 
         (unsigned long)argvp[n], 
         nread, strerror(errno)); 
       break; 
      } 

      printf(" %-2d) nread=%-4d, ", n, nread); 
      fflush(stdout); 
      alen = strlen(buffer)+1; 
      printf(" alen=%-4d ", alen); 
      fflush(stdout); 
      arg = malloc(alen); 
      memcpy(arg, buffer, alen); 
      printf(" {%s}\n", arg); 
      fflush(stdout); 
     } 

     if (argvp != argvb) { 
      free(argvp); 
     } 

     close(fd); 
    } 

    closedir(dirp); 

    return 0; 
} 
+0

我目前無法在solaris系統上嘗試此操作,但使用'-D_LARGEFILE64_SOURCE'進行編譯會使其工作嗎? –

+0

@mark試了一下。它沒有改變任何東西。正如我在OP中注意到的那樣,所需的信息似乎並不存在於psinfo文件中。 – paolov

回答

0

你試圖從過去的文件的末尾起始位置讀取。

pread man page

ssize_t供PREAD(INT法爾茲,無效* buf中,爲size_t nbyte,off_t偏移);

...

EOVERFLOW

該文件是一個普通文件,nbyte大於0,起始 位置是結束文件之前,與起始位置是 大於或等於在與fildes相關聯的公開 文件描述中建立的偏移最大值。

+0

這似乎是一個不同的錯誤。如果你有一個solaris盒子,這段代碼應該很容易編譯,你可以試試。 – paolov

+1

@ user55570 - 您忽略了流程的數據模型。您正在從進程地址空間讀取的指針是64位還是32位指針?這就是'pargs'的做法:http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/ptools/pargs/pargs.c#577 –

+0

該代碼已經在參數一些過程。只有在沒有參數的地方參數特別長的情況下,所以問題可能不在於指針類型。如果你有一個solaris框,代碼很容易編譯。 – paolov

相關問題