void cl_net_stats(void) { static vector_t NS; /* Network stats */ static time_t t_last; time_t t_now; t_now = time(NULL); /* Only update net stats once a second */ if( t_now != t_last ) { t_last = t_now; NS = net_stats(server, client.netstats); } draw_netstats(NS); }
int main (int argc, char* argv[]) { mach_msg_type_number_t actListCnt; thread_act_array_t actList; double cpuTime; kern_return_t kr; int i; char *procName; float scaledUsage; task_t task = 0; pid_t pid = -1; thread_basic_info_t tbi; thread_basic_info_data_t tbiData; double waitSeconds = 0.0; struct timespec tv; // Setup a Ctrl-C handler. //act.sa_handler = intHandler; //sigaction(SIGINT, &act, NULL); // // PARSE PARAMETERS // while ((i = getopt(argc, argv, "dn:p:vw:")) != -1) { switch (i) { case 'd': gFmpFormat = true; break; case 'h': print_usage(); break; case 'n': procName = optarg; //printf ("Name: %s\n", procName); pid = get_pid_for_process(procName); break; case 'p': pid = atoi (optarg); break; case 'v': gVerbose = true; break; case 'w': //printf ("Wait: %s\n", argv[i+1]); waitSeconds = atof (optarg); if (waitSeconds <= 0.0) waitSeconds = 0.0; if (waitSeconds > 0.0 && waitSeconds < 0.1) waitSeconds = 0.1; break; default: printf ("Invalid arguments, please try again.\n"); print_usage(); exit(1); break; } } if (gVerbose) { print_verbose_info(); } //printf ("PID: %i\n", pid); if (pid < 1) { printf ("No process found, please try again.\n"); print_usage(); return 1; } if (waitSeconds > 0.0) { /* Construct the timespec from the number of whole seconds... */ tv.tv_sec = (time_t) waitSeconds; /* ... and the remainder in nanoseconds. */ tv.tv_nsec = (long) ((waitSeconds - tv.tv_sec) * 1e+9); } else { // Default time if none specified. tv.tv_sec = (time_t) 1; tv.tv_nsec = 0; } // // GET PROCESS INFO // task_basic_info_data_t basic_info; mach_msg_type_number_t count; // Get port for accessing system CPU stats. gHostPort = mach_host_self(); do { // Need to load the task number? if (task == 0 && pid > 0) { if ((kr = task_for_pid(mach_task_self(), pid, &task)) != KERN_SUCCESS) { mach_error("processdetail", kr); perror ("Could not get Mach task for pid. Did you run with sudo?\n"); exit (1); } } count = TASK_BASIC_INFO_COUNT; if ((kr = task_info(task, TASK_BASIC_INFO, (task_info_t)&basic_info, &count)) != KERN_SUCCESS) { if (gHasRunOnce && procName != NULL) { // We found the process originally, so we'll wait the regular interval and // see if the process restarts. gKeepRunning = nanosleep(&tv, NULL) == 0; if (!gKeepRunning) printf ("\n"); // Return after Ctrl-C pid = get_pid_for_process(procName); // Force the task number to be reloaded. task = 0; continue; } else { // Shouldn't happen unless process died in between getting pid and here. perror ("Process being monitored died!?\n"); mach_error("processdetail", kr); exit(1); } } if (count != TASK_BASIC_INFO_COUNT) { fprintf(stderr, "size mismatch"); exit(1); } // CPU STATS cpuTime = cpu_statistics(); // NET STATS if (net_stats() != 0) { perror ("Error getting network stats"); exit (1); } // There is a wait interval and this is the very first run? if (gHasRunOnce == false) { // Skip printing until we have a full interval. // We can then give difference between before & after. gHasRunOnce = true; // Update values but don't print. net_print_stats(false); gKeepRunning = nanosleep(&tv, NULL) == 0; if (!gKeepRunning) printf ("\n"); continue; } // // PRINT SYSTEM STATS // print_timestamp(); cpu_print_statistics(cpuTime); net_print_stats(true); // // PRINT PROCESS SPECIFIC STATS // if (gFmpFormat) { printf ("$pd.pid=%i;\n$pd.vmsize=%li;\n$pd.residentmemory=%li;\n", pid, basic_info.virtual_size,basic_info.resident_size); } else { printf ("%i, %li, %li, ", pid, basic_info.virtual_size,basic_info.resident_size); //printf("Suspend count: %d\n", basic_info.suspend_count); } task_events_info_data_t events_info; if ((kr = task_info(task, TASK_EVENTS_INFO, (task_info_t)&events_info, &count)) != KERN_SUCCESS) { mach_error("processdetail", kr); exit(1); } if (count != TASK_EVENTS_INFO_COUNT) { fprintf(stderr, "size mismatch"); exit(1); } if (gFmpFormat) { printf ("$pd.pagefaults=%d;\n$pd.pageins=%d;\n$pd.copyonwritefaults=%d;\n", events_info.faults, events_info.pageins, events_info.cow_faults); } else { //printf("Page faults: %d\n", events_info.faults); printf("%d, ", events_info.faults); //printf("Pageins: %d\n", events_info.pageins); printf("%d, ", events_info.pageins); //printf("Copy-on-write faults: %d\n", events_info.cow_faults); printf("%d, ", events_info.cow_faults); //printf("Messages sent: %d\n", events_info.messages_sent); //printf("Messages received: %d\n", events_info.messages_received); //printf("Mach system calls: %d\n", events_info.syscalls_mach); //printf("Unix system calls: %d\n", events_info.syscalls_unix); //printf("Context switches: %d\n", events_info.csw); } if (gFmpFormat) { switch (basic_info.policy) { case THREAD_STANDARD_POLICY: printf("$pd.threadpolicy=Standard;\n"); break; case THREAD_TIME_CONSTRAINT_POLICY: printf("$pd.threadpolicy=\"Time Constraint\";\n"); break; case THREAD_PRECEDENCE_POLICY: printf("$pd.threadpolicy=Precendence;\n"); break; default: printf("$pd.threadpolicy=Unknown;\n"); break; } } else { switch (basic_info.policy) { case THREAD_STANDARD_POLICY: printf("Standard, "); break; case THREAD_TIME_CONSTRAINT_POLICY: printf("\"Time Constraint\", "); break; case THREAD_PRECEDENCE_POLICY: printf("Precendence, "); break; default: printf("Unknown, "); break; } } kr = task_threads (task, &actList, &actListCnt); if (kr != KERN_SUCCESS) { fprintf(stderr, "task_threads failed"); exit (1); } if (gFmpFormat) { printf ("$td.threadcount=%i;\n", actListCnt); } else { printf ("%i, ", actListCnt); } mach_msg_type_number_t threadInfoCnt; float cpuUsage; /* Never a pthread (!?) so this doesn't work. for (int i = 0; i < actListCnt; ++i) { pthread_t pt = pthread_from_mach_thread_np(actList[i]); if (pt) { name[0] = '\0'; int rc = pthread_getname_np(pt, name, sizeof name); printf("mach thread %u: getname returned %d: %s\n", actList[i], rc, name); } else { printf("mach thread %u: no pthread found\n", actList[i]); } } */ tbi = &tbiData; cpuUsage = 0.0; for (i = 0; i < actListCnt; i++) { threadInfoCnt = THREAD_BASIC_INFO_COUNT; kr = thread_info( actList[i], //thread_act_t target_act THREAD_BASIC_INFO, //thread_flavor_t flavor (thread_info_t) tbi, //thread_info_t thread_info_out &threadInfoCnt); //mach_msg_type_number_t *thread_info_outCnt cpuUsage += tbi->cpu_usage; //printf ("CPU Usage: %i\n", tbi->cpu_usage); scaledUsage = tbi->cpu_usage / (float)TH_USAGE_SCALE * 100.0; if (gFmpFormat) { printf ("$pd.threadcpu[%i]=%.2f;\n", i+1, scaledUsage); } else { printf ("%.2f, ", scaledUsage); } } if (gFmpFormat) { printf ("$pd.totalcpu=%.2f\n\n", cpuUsage / (float)TH_USAGE_SCALE * 100.0); } else { printf ("%.2f\n", cpuUsage / (float)TH_USAGE_SCALE * 100.0); } // If user is tailing the piped result we want them to see results quickly. fflush (stdout); // We've done the whole process at least once. gHasRunOnce = true; if (waitSeconds != 0.0) { gKeepRunning = nanosleep(&tv, NULL) == 0; } else { gKeepRunning = false; } } while (gKeepRunning); return 0; }