我有一個相當簡單的代碼,用於處理solaris中的/ proc/*文件以獲取進程信息和參數。對於它的工作原理在大多數情況下(這意味着它正確地確實存在爭論中的某些進程),但在某些工藝參數(特別是當他們長),它失敗,也許是爲什麼它產生的錯誤Value too large for defined data type
解析/ proc psinfo和argv返回:值太大,無法定義的數據類型錯誤
有沒有人有任何想法失敗?
這是pread()
線爲參數數組失敗在行108
它實際上是一些Java程序有許多爭論,是否可以幫助它失敗。
有趣太是:
檢查二進制
/proc/<pid>/psinfo
文件,它是非常小 - 大小顯然不足以包含我與一些流程看着那種長篇大論。執行psinfo
文件內容的十六進制轉儲證實它們不在那裏。當長參數爲零時,
pr_argv
的值。在進一步挖掘,它看起來像參數在
/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;
}
我目前無法在solaris系統上嘗試此操作,但使用'-D_LARGEFILE64_SOURCE'進行編譯會使其工作嗎? –
@mark試了一下。它沒有改變任何東西。正如我在OP中注意到的那樣,所需的信息似乎並不存在於psinfo文件中。 – paolov