老实说,我不明白你为什么要在 C 中这样做。
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <getopt.h>
#include <unistd.h>
enum { ERR = -1 };
static int s_running = 1;
static void sigintHandler(int s) {
(void)s;
s_running = 0;
}
int main(int argc, char *argv[]) {
int pid = -1, sleepMsec = 1000;
char optchr, buf[260];
FILE *fp;
signal(SIGINT, sigintHandler);
while (ERR != (optchr = getopt(argc, argv, "p:s:"))) {
switch (optchr) {
case 'p': pid = strtol(optarg, NULL, 0); break;
case 's': sleepMsec = strtol(optarg, NULL, 0); break;
default:
fprintf(stderr, "USAGE: smap -p pid [-s msec]\n");
return -10;
}
}
snprintf(buf, sizeof buf, "/proc/%d/smaps", pid);
buf[sizeof buf - 1] = '\0';
fp = fopen(buf, "r");
if (NULL == fp) {
char buf1[sizeof buf];
snprintf(buf1, sizeof buf1, "fopen for [%s]", buf);
buf1[sizeof buf1 - 1] = '\0';
perror(buf1);
return -20;
}
for (;;) {
if (ERR == fseek(fp, 0, SEEK_SET)) {
perror("fseek(3)");
return -30;
}
while (fgets(buf, sizeof buf, fp)) {
if (strstr(buf, "stack")) {
printf("%s", buf);
if ( ! fgets(buf, sizeof buf, fp)) {
fprintf(stderr, "fgets(3) found EOF\n");
return -40;
}
printf("%s", buf);
}
}
usleep(1000 * sleepMsec);
if ( ! s_running)
break;
}
printf("Bye!\n");
return 0;
}
我建议您使用 Python 等脚本语言来完成此类任务。
#! /usr/bin/env python
from __future__ import print_function
import time
import sys
import getopt
def main(args):
pid = -1
sleepMsec = 1000
opts, _ = getopt.getopt(args, "p:s:")
for (k,a) in opts:
if "-p" == k:
pid = int(a)
elif "-s" == k:
sleepMsec = int(a)
try:
with open("/proc/{}/smaps".format(pid)) as fp:
while True:
fp.seek(0)
while True:
line = fp.readline()
if not line:
break
if 0 <= line.find("stack0"):
print(line, fp.readline(), sep='', end='')
break
time.sleep(1e-3 * sleepMsec)
except KeyboardInterrupt:
print("Bye!")
if "__main__" == __name__:
main(sys.argv[1: ])
Bash 和标准 Linux 命令的组合也是一种选择。事实上,您已经在初始版本中使用了 grep。
请注意,您不能对管道使用 fseek(3)(严格意义上说是流),但 /proc/PID/smaps 伪文件系统支持它。