voidInit() { readPort = &Pipe[0], writePort = &Pipe[1]; // if the pipeline creation fails the function will directly end the function if (pipe(Pipe) == -1) {
perror("pipe error!"); exit(EXIT_FAILURE); } // reduce the output that is not needed to /dev/null devNull = open("/dev/null", O_WRONLY); // get environment variables and save it into PATH char *pathVar = getenv("PATH"); strcpy(PATH, pathVar); // fill in pad to '\0' memset(pad, '\0', sizeof(pad)); }
voidsubProcessing(int argc, char *argv[], char *envp[]) { // reset the output of the sub thread dup2(devNull, fileno(stdout)), dup2(devNull, fileno(stderr)); // sub process redirection to close the reading at the same time close(*readPort); // construct the parameters required for strace char *exec_argv[32] = {"strace", "-T", "-o"}; char writeFile[32]; sprintf(writeFile, "/proc/self/fd/%d", *writePort); exec_argv[3] = writeFile; for (int i = 1; i <= argc - 1; i++) { exec_argv[i + 3] = argv[i]; } exec_argv[argc + 3] = NULL; // according to ":" divide path and look for strace for each path char *token = strtok(PATH, delim); while (token != NULL) { char straceFile[128]; sprintf(straceFile, "%s/strace", token); execve(straceFile, exec_argv, envp); straceFile[0] = '\0'; token = strtok(NULL, delim); } Assert((token == NULL), "incompletely divided"); perror(argv[0]); exit(EXIT_FAILURE); }
voidparentProcessing() { // parent process closes the write port close(*writePort); // copy the output results of the sub processes // and adjust the analysis function as a solid parameter char buf[2], arr[1024]; int index = 0; structtimevalstart, end; gettimeofday(&start, NULL); while (1) { if (isEnd) { /* if the process ends print immediately and return */ print(); break; } // read a line of system calls and parse them while (read(*readPort, &buf, 1) > 0) { arr[index++] = buf[0]; if (buf[0] == '\n') { arr[index] = '\0'; analysis(arr, index); index = 0; break; } } gettimeofday(&end, NULL); // output every second if (end.tv_sec - start.tv_sec >= 1) { Assert((end.tv_sec - start.tv_sec >= 1), "pass less than one second"); print(); start = end; } } Assert((isEnd), "child process not terminated"); close(*readPort); }
voidanalysis(char buffer[], ssize_t count) { // name is the name that is called by the system // and time is the time to use this call char name[128]; float time = 0.0f; if (buffer[0] == '+') { // "+++ exited with 0 +++" represents the end of the process isEnd = 1; return; }
// get name and time obtained through format string sscanf(buffer, regular, name, &time); for (int i = 0; i <= countOfItem; i++) { if (i == countOfItem) { // unprecedented system calls strcpy(table[countOfItem].name, name); table[countOfItem].time = time; countOfItem++; break; } elseif (strcmp(name, table[i].name) == 0) { // system calls that have appeared table[i].time += time; break; } } }