1

MacOS Xで「top」コマンドを使用して、リソースを使用しているアプリを特定しようとしています。私がする時:

top -stats "pid、command"

プロセス名が長すぎる場合、コマンド列は切り捨てられます。

アクティビティモニターを見ると、プロセス名が正しく(フルネームで)+アイコンで表示されています。私の質問は次のとおりです。

  1. 完全なプロセス名を取得する方法は?
  2. プロセス名の横にアプリのアイコンが表示されることがありますが、Objective-cを使用して同様のことを行う方法はありますか?アプリのコンテンツフォルダに移動して、icnsイメージを取得する必要がありますか?
4

1 に答える 1

5

まず、プログラムでデータを取得しようとしている場合、運転topはほぼ間違いなくやりたいことではありません。

ただし、直接の質問に答えるには:

完全なプロセス名を取得するには?

コマンドの切り捨てを制御する方法はありません。このパラメーターを使用して-ncols、非対話型出力の出力幅を設定できますが、必要topに応じて切り捨てを停止しません。

プロセス名の横にアプリのアイコンが表示されることがありますが、objective-c を使用して同様のことを行う方法はありますか? アプリのコンテンツ フォルダーに移動して、icns イメージを取得するだけでよいですか?

いいえ。ドキュメント アイコンなど、複数の .icns ファイルを持つアプリをどのように処理しますか? (たとえば、iTunes で試してみてください。最初の .icns を選択すると、AIFF ドキュメント アイコンが表示されます。最後の .icns を選択すると、内部使用の最近のテレビ番組アイコンが表示されます。)

これを行う正しい方法はNSBundle、アプリケーションの を取得してから、次のようにすることです。

NSString *iconFile = [bundle objectForInfoDictionaryKey:@"CFBundleIconFile"];
if (iconFile) {
    NSString *iconPath = [bundle pathForResource:iconFile ofType:@"icns"];
    // load and display the icon
}

では、運転しない場合、実際にどのようにこれを行いたいtopですか?

さて、あなたが求めているのは、実際には明確に定義されたものではありません。OS X には、1 対 1 で対応しないタスク/プロセス/プログラム/アプリケーションの 4 つの異なる概念があり、異なる概念を使用する 2 つのプログラムのマッシュアップを作成したい場合は、作業が困難になりますtop。プロセス、Activity Monitor は OS X アプリケーションを扱います。

実際に同じリストを使用したい場合top、それはオープン ソースなので、それを読んで同じことを行うことができます。

しかし、BSD プロセスのリストを取得する最も簡単な方法は、おそらく 、libproc.h特にproc_listallpidsとのインターフェースproc_pidinfoです。例えば:

int dump_proc_names() {
  int buf[16384];
  int count = proc_listallpids(&buf, 16384*sizeof(int));
  for (int i = 0; i != count; ++i) {
    int pid = buf[i];
    char path[MAXPATHLEN+1] = {0};
    int ret = proc_pidinfo(pid, PROC_PIDPATHINFO, 0,
                           &path, sizeof(path));
    if (ret < 0) {
      printf("%d: error %s (%d)\n", pid, strerror(errno), errno);
    } else {
      printf("%d: %s\n", pid, path);
    }
  }
}

明らかに実際のコードでは、バッファーを動的に割り当てたり、値をダンプする代わりに値を返したり、パス以外のものを取得したりする必要があります。しかし、基本的な考え方を理解するにはこれで十分です。(追加情報を取得するときは、構造体を要求すると、その構造体のすべてのメンバーを表示する権限がない限り、EPERM エラーが発生することに注意してください。したがって、必要なPROC_PIDTASKALLINFO場合のみ要求しないでください。 PROC_PIDT_SHORTBSDINFO.


いずれにせよ、この API はアプリケーションではなく BSD プロセス (および Mach タスク) を扱うためNSBundle、Activity Monitor スタイルの機能を提供したいという目的を達成するのに直接役立つことはありません。

これを完全に正しく行う方法はありませんが、おそらく次のような方法で問題を解決できます。

NSString *path = processPath;
while (path && ![path isEqualTo:@"/"]) {
    NSBundle *bundle = [NSBundle bundleWithPath:path];
    if (bundle) {
        if ([bundle executablePath != processPath]) return nil;
        return bundle;
    }
    path = [path stringByDeletingLastPathComponent];
}

おそらく、これを行う別の方法があり、それぞれに異なるトレードオフがあります。たとえば、 を使用して-[NSWorkspace runningApplications]、バンドルの実行可能パスをバンドルにマッピングする辞書に結果を格納し、それを使用して各プロセスを検索するのは簡単ですが、現在のユーザーが所有するアプリケーションにのみ役立つようです (おそらく現在のセッション)。一方、システム上のすべてのバンドルを列挙したり、Spotlight に問い合わせたりするのは、その場で行うにはおそらく遅すぎますが、最初の実行時にそれらをキャッシュすると古くなります。


の代わりにlibproc、 を使用することもできますlibtop

残念ながら、Apple はそれを提供していません。ツールに使用する実装がありますが実際にはソースに埋め込まれており、外部からは利用できません。ソース (上記のリンク) を見つけて、それ自体と同じ方法でプログラムに埋め込むことができます。libtoptoptoptop

あるいは、GNU と BSD の両方のプロセス ユーティリティに Mac ポートがあるため (ただし、Homebrew/MacPorts/Google 検索で使用する名前を知るのは必ずしも簡単ではありませんが…)、それらのいずれかをビルドして使用することもできます。

ただし、クロスプラットフォームのソフトウェアを作成しようとしている場合 (または、Linux や FreeBSD などでこのコードを作成する方法を既に知っている場合) を除き、複雑さが増すだけだと思います。

于 2013-01-16T21:56:00.020 に答える