4

コマンドライン内のデータを使用して、アプリが呼び出されたパラメーターを抽出しようとしています。

このようなアプリケーションインスタンスを起動すると、次のようになります。

myapp 1 2

次に、myappのコマンドラインをcatします。myapp12のようなものが表示されます。

これらの値を抽出する必要があり、このコードを使用して抽出しました


pid_t proc_id = getpid();

sprintf(buf,"/proc/%i/cmdline",proc_id);

FILE * pFile;
pFile = fopen (buf,"r");
if (pFile!=NULL)
{
    fread(buf,100,100,pFile);
    cout << "PID " << proc_id << endl;
    string str = buf;
    cout << buf << endl;
    size_t found=str.find_last_of("/\\");
    cout << " file: " << str.substr(found+1) << endl;

    fclose (pFile);
}

しかし、私が得ているのはアプリ名だけで、パラメーターはありません...


回答からコピーされた更新:

さて、私の質問は、最初のNULL文字で停止せずにcmdlineファイルを読み取る方法のようです...

fopen(cmdline, "rb")

他には何もしませんので...

4

3 に答える 3

8

/usr/bin/strings /proc/1337/cmdline通常、私のために仕事をします。

于 2011-03-16T13:44:42.913 に答える
7

すべてのコマンドラインパラメータ(argv[]配列として取得されるもの)は、実際には。のnullで区切られた文字列です/proc/XXX/cmdline

abatkin@penguin:~> hexdump -C /proc/28460/cmdline
00000000  70 65 72 6c 00 2d 65 00  31 20 77 68 69 6c 65 20  |perl.-e.1 while |
00000010  74 72 75 65 00                                    |true.|

これは、あなたcatが編集したときcmdlineにそれらがすべて「スタック」した(cat無効なNULL文字を無視した)理由coutと、プロセス名がnullで終了する文字列であると考えたために最初のコマンドライン引数(プロセス名)の後で停止した理由を説明しています。その時点でそれ以上の文字を探すのをやめました。

コマンドライン引数の処理

コマンドライン引数を処理するには、いくつかのオプションがあります。コマンドライン全体を1つの巨大な文字列にしたい場合は、0から(numRead - 2)numRead読み取られる文字数)までループし、NULLバイト(curByte == 0)をスペースに置き換えます。次に、最後の文字も必ずNULLバイトに設定してください(固定サイズのバッファーが原因で切り捨てられた場合に備えて)。

代わりに、すべての引数を含む配列が必要な場合は、より創造的である必要があります。1つのオプションは、0からループすること(numRead - 1)であり、見つかったすべてのNULLバイトである可能性があります。char*次に、その長さの配列を割り当てます。次に、コマンドラインをループバックして、すべての文字列の先頭(つまり、配列の最初のバイトとNULLバイトに続く各バイト)をchar*'sの配列の連続する要素に設定します。

固定サイズのバッファーを読み取るため、そのバッファーを超えるものはすべて切り捨てられることを知っておいてください。したがって、何をするにしても、最後の文字列の終わりがNULLで終了することを手動で確認する必要があることを覚えておいてください。そうしないと、ほとんどの文字列処理関数は文字列の終わりを認識せず、永久に継続します。

于 2009-09-10T17:35:42.833 に答える
0

|path|で提供される多くのファイル サイズが正しくありません(procファイルなど)。したがって、ファイルは1回限りの読み取りではなく、順次読み取られます。

std::string cmdline;
char buf[1024];
size_t len;
FILE *fp = fopen("/proc/self/cmdline", "rb");
if (fp) {                       
    while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) {
        cmdline.append(buf, len); // note: `len` here is very important
    }
}

次に、コマンドライン全体とパラメータも取得します。ただし、アプリ名またはファイルパスのみを取得でき、印刷しようとしたときにパラメーターが取得できない理由は、取得したコマンドラインが。などで区切られて'\0'いるためです"./exefile_name\0-param1=p1\0-param2=p2"'\0'したがって、マシンは弦がその場所で終了していると想定しているため、最初の部分より前の部分しか取得できません。また、最初にトークン化して'\0'から、印刷または使用する必要があります。

std::stringstream tokens(cmdline);
std::string tmp;
while (getline(tokens, tmp, '\0')){
    std::cout << tmp << std::endl;
}
fclose(fp);
于 2021-08-24T09:54:21.173 に答える