📄 nptl_trace.c
字号:
/* Copyright (C) 2004,2005,2006 Bull S.A. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#if HAVE_CONFIG_H#include <config.h>#endif#define _XOPEN_SOURCE 500#include <string.h>#include <stdio.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <endian.h>#include <signal.h>#include <sys/mman.h>#include "types.h"#include "level.h"#include "timestamp.h"#include "daemon.h"#include "debug.h"#include "version.h"#define PTT_FILE_LEN 255#define PTT_BIN_FILE_LEN 255#define PTT_BUF_SIZE_DEFAULT (1<<21)#define PTT_MAX_BUF_SIZE ((1<<30)-1)#define PTT_SZ_WORD (sizeof(PTT_WORD))#define PTT_ARCH_LEN 30struct ptt_buffer * ptt_buf;extern unsigned int max_file, max_size;static void usage(void) { printf ("ptt_trace [options] cmd [cmd_arg ...]\n" "Help :\n" "\t-s size:\tchange the buffer size\n" "\t-l level:\tchange the trace level\n" "\t-m max:\t\tmax file size in Mb\n" "\t-f max:\t\tmax number of file\n" "\t-n name:\tname of the trace file\n" "\t-h:\t\tthis help\n" "\t--:\t\tforce an end of option-scanning\n"); exit (1);}static pid_t cmd; /* pid of the process which inits the trace mechanism */char region [PTT_FILE_LEN]; /* shared memory name */static void sighandler (int signum) { printf ("Killed by signal %d\n", signum); kill (cmd, signum);}static void aborthandler (int signum) { printf ("Killed by signal %d\n", signum); if (shm_unlink (region) == -1) perror("shm_unlink failed"); kill (cmd, SIGKILL);}int main (int argc, char**argv) { pid_t pgid; /* name of the binary file created by the trace mechanism */ static char binary [PTT_BIN_FILE_LEN]; int fd; long long size_buff; int size_log2 = 0; int trace_level = PTT_LEVEL_ALL; signed char c; int status; ptt_header_t header = { .byte_order = __BYTE_ORDER, .version = { .major = PTT_VERS_MAJOR, .minor = PTT_VERS_MINOR }, .freq_khz = get_clockfreq_khz (), .timestamp = get_timestamp (), .start_time = time (NULL), }; const char * optstring = "+s:hl:m:f:n:"; /* don't use _SC_AVPHYS_PAGES since memory could be cached and still * usable */ size_buff = (long long) sysconf (_SC_PHYS_PAGES) / (1<<7) * sysconf (_SC_PAGESIZE) * sysconf (_SC_NPROCESSORS_ONLN); if (size_buff <= 0) size_buff = PTT_BUF_SIZE_DEFAULT; /* default file name */ snprintf (binary, sizeof (binary), "trace_%d_%d", (int) time (NULL), getpid()); while ((c = getopt (argc-1, argv+1, optstring)) != EOF) { switch (c) { case 'h': usage(); break; case 's': size_buff = strtol (optarg, NULL, 10); break; case 'l': trace_level = PTT_LEVEL_NONE; while (optarg) { char *level = optarg; strsep (&optarg, ","); trace_level |= levelstr2int (level); } break; case 'm': max_size = strtol (optarg, NULL, 10) * (1<<20); break; case 'f': max_file = strtol (optarg, NULL, 10); break; case 'n': strncpy (binary, optarg, sizeof (binary)); binary [sizeof (binary)] = 0; break; case '?': printf ("error : %c\n", optopt); usage(); } } if ((argc - 1 - optind) < 1) { printf("missing program to excecute\n"); usage(); exit (1); } if (size_buff > (PTT_MAX_BUF_SIZE)) size_buff = (long long) (PTT_MAX_BUF_SIZE); if (size_buff < 4) size_buff = 4; while (size_buff != 0) { ++size_log2; size_buff>>=1; } size_buff = (long long) (1<<size_log2); pgid = getpid (); if (pgid != getpgid (0)) if (setpgid (pgid, pgid)) { perror("setpgid failed"); abort(); } snprintf (region, sizeof (region), "/ptt_%d", pgid); printf("*** Currently using the NPTL Trace Tool.\n"); if (max_size) printf("*** Output file is %s-[0-9]*.bin\n", binary); else printf("*** Output file is %s.bin\n", binary); printf("*** pgid=%d\n", pgid); /* Create and open a new POSIX shared memory object*/ if ((fd = shm_open(region, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR)) == -1) { perror("shm_open failed"); abort(); } /* we should clean our file if we are aborted */ signal (SIGABRT, aborthandler); /* set the size of the shared memory object to size of buffer */ if (lseek (fd, sizeof (struct ptt_buffer) + size_buff, SEEK_SET) == -1) { perror("lseek failed"); abort(); } if (write (fd, &fd, 1) != 1) { perror("write for extended"); abort(); } /* map the shared memory */ ptt_buf = mmap (0, sizeof (struct ptt_buffer) + size_buff, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptt_buf == MAP_FAILED) { perror("mmap failed"); abort(); } /* initialize fields of the buffer */ ptt_buf->reserved = 0; ptt_buf->written = 0; ptt_buf->beg_read = 0; ptt_buf->PAUSE = 0; ptt_buf->size_buff = size_buff / PTT_SZ_WORD; ptt_buf->current_level = trace_level;#ifdef PTT_TRACE_INFO ptt_buf->stat_enable = 1;#else ptt_buf->stat_enable = 0;#endif /* initialize the fields of the header */ strncpy (header.architecture, PTT_ARCH, PTT_ARCH_LEN); /* create the second process */ if ((cmd = fork()) == -1) { perror("fork failed"); abort(); } if (cmd == 0) { /* add argv[optind] to LD_PRELOAD in process environnement */ char *old_preld = getenv ("LD_PRELOAD"); if (old_preld == NULL) setenv ("LD_PRELOAD", argv[1], 1); else { char *new_preld = (char *) malloc (sizeof (char) * (strlen (old_preld) + 2 + strlen (argv[1]))); strncpy (new_preld, argv[optind], strlen(argv[1])); strncat (new_preld, ":", 1); strncat (new_preld, old_preld, strlen(old_preld)); setenv ("LD_PRELOAD", new_preld, 1); } execvp (argv[optind+1], argv+optind+1); perror("execve failed"); abort(); } /* term signal */ signal (SIGHUP, sighandler); signal (SIGINT, sighandler); signal (SIGQUIT, sighandler); signal (SIGKILL, sighandler); signal (SIGPIPE, sighandler); signal (SIGALRM, sighandler); signal (SIGTERM, sighandler); signal (SIGPROF, sighandler); signal (SIGVTALRM, sighandler); /* user signal */ signal(SIGUSR1, sighandler); signal(SIGUSR2, sighandler); /* stop signal */ signal(SIGSTOP, sighandler); signal(SIGTSTP, sighandler); signal(SIGTTIN, sighandler); signal(SIGTTOU, sighandler); signal(SIGCONT, sighandler); status = daemon (&header, binary); /* reader process has finished */ if (shm_unlink (region) == -1) perror("shm_unlink failed"); PTT_TRACE_INTERNALS (PTT_DBG_MAIN, "At the end of this program, written=%u\n", ptt_buf->written); printf("*** The NPTL Trace Tool's work is finished.\n"); if (WIFSIGNALED (status)) { printf("*** %s was killed by a signal(%d)\n", argv[optind+1], WTERMSIG (status)); kill (getpid(), WTERMSIG (status)); } if (WIFEXITED (status)) { printf("*** %s terminated normally(%d)\n", argv[optind+1], WEXITSTATUS (status)); exit (WEXITSTATUS (status)); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -