procfs
file system here. We'll have to solve this problem on our own.task_for_pid()
and task_threads()
.threadmon
, but this is not essential). As competent sources suggest, there was nothing required before Mac OS X 10.5, but then for security reasons, such restrictions were introduced. And this all means that we will need to sign our executable file with our certificate, and also before requesting our functions, request the user the right to execute them through the Security framework. Well, let's start from the beginning: write a function requesting user rights: #include <Security/Authorization.h> int acquireTaskportRight() { OSStatus stat; AuthorizationItem taskport_item[] = {{"system.privilege.taskport:"}}; AuthorizationRights rights = {1, taskport_item}, *out_rights = NULL; AuthorizationRef author; AuthorizationFlags auth_flags = kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed | ( 1 << 5); stat = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, auth_flags, &author); if (stat != errAuthorizationSuccess) { return 1; } stat = AuthorizationCopyRights(author, &rights, kAuthorizationEmptyEnvironment, auth_flags, &out_rights); if (stat != errAuthorizationSuccess) { return 1; } return 0; }
task_for_pid()
. Now we need at the beginning of the main()
function to call acquireTaskportRight()
and check the return value: 0 - everything is OK, otherwise - no privileges are received. Well, we write further. Let our input program receive the pid of the process for which we will receive information. We write in the main()
function: int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage:\n %s <PID>\n", argv[0]); return -1; } if (acquireTaskportRight()) { printf("No rights granted by user or some error occured! Terminating.\n"); return -2; } char* end; pid_t pid = strtol(argv[1], &end, 10); if (*end) { printf("Error: invalid PID given: \"%s\", terminating.\n", argv[1]); return -3; } printf("Starting threadmon for PID %d\n", pid); // TODO: the rest }
task_t port; kern_return_t kr = task_for_pid(mach_task_self(), pid, &port); if (kr != KERN_SUCCESS) { printf("task_for_pid() returned %d, terminating.\n", kr); return -4; } thread_array_t thread_list; mach_msg_type_number_t thread_count; thread_info_data_t thinfo; mach_msg_type_number_t thread_info_count; thread_basic_info_t basic_info_th; // get threads in the task kr = task_threads(port, &thread_list, &thread_count); if (kr != KERN_SUCCESS) { printf("task_threads() returned %d, terminating.\n", kr); return -5; }
long tot_cpu = 0; int j; for (j = 0; j < thread_count; j++) { thread_info_count = THREAD_INFO_MAX; kr = thread_info(thread_list[j], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count); if (kr != KERN_SUCCESS) { printf("Thread %d: Error %d\n", thread_list[j], kr); continue; } basic_info_th = (thread_basic_info_t)thinfo; if (!(basic_info_th->flags & TH_FLAGS_IDLE)) { tot_cpu = tot_cpu + basic_info_th->cpu_usage; printf("Thread %d: CPU %d%%\n", thread_list[j], basic_info_th->cpu_usage); } } printf("---\nTotal: CPU %ld%%\n", tot_cpu); return 0;
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> <key>CFBundleIdentifier</key> <string>com.silvansky.threadmon</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>threadmon</string> <key>CFBundleVersion</key> <string>1.0</string> <key>SecTaskAccess</key> <array> <string>allowed</string> </array> </dict> </plist>
SecTaskAccess
to the last key: SecTaskAccess
, we need it. Now we need to make changes to the Makefile: add our list during linking: LOPTS=-framework Security -framework CoreFoundation -sectcreate __TEXT __info_plist ./Info.plist
sudo
every time before running this utility. =) codesign -s "your-certificate-name" ./threadmon
$ ps -A | grep Xcode 775 ?? 617:02.82 /Applications/Xcode.app/Contents/MacOS/Xcode -psn_0_348245 73761 ttys005 0:00.00 grep Xcode $ ./threadmon 775 Starting threadmon for PID 775 Thread 6147: CPU 55% Thread 6403: CPU 0% Thread 6659: CPU 0% Thread 6915: CPU 0% Thread 7171: CPU 0% Thread 7427: CPU 0% Thread 7683: CPU 0% Thread 7939: CPU 0% Thread 8195: CPU 0% Thread 8451: CPU 0% Thread 8707: CPU 0% Thread 8963: CPU 0% Thread 9219: CPU 0% Thread 9475: CPU 0% Thread 9731: CPU 0% Thread 9987: CPU 0% Thread 10243: CPU 0% Thread 10499: CPU 0% Thread 10755: CPU 0% Thread 11011: CPU 0% Thread 11267: CPU 0% Thread 11523: CPU 22% Thread 11779: CPU 7% Thread 12035: CPU 32% Thread 12291: CPU 46% Thread 12547: CPU 14% Thread 12803: CPU 0% --- Total: CPU 176%
Source: https://habr.com/ru/post/152134/
All Articles