状況は次のとおりです。glibcのgetpid作業手順は何ですか?
私は012bを実行して、githubでカーネルをハックしようとしています。カーネルのバージョンはlinux-3.18.6です。
環境をシミュレートするためにQEMUが使用されます。
私のアプリケーションでは、私は自分のアプリケーションに従うことによってシステムコールの手順を理解しようとしています。私の目的を達成する方法は、シェルプログラムのようなものです。相対的なシステムコールを実行するコマンドをいくつか作成します。たぶんそれは写真を通して簡単です。
1を使用APIのGETPIDを次のように some commands
コードは簡単です。
int Getpid(int argc, char **argv)
{
pid_t pid;
pid = getpid();
printf("current process's pid:%d\n",pid);
return 0;
}
2 int $ 0x80を直接使用してください。
int GetpidAsm(int argc, char **argv)
{
pid_t pid;
asm volatile(
"mov $20, %%eax\n\t"
"int $0x80\n\t"
"mov %%eax, %0\n\t"
:"=m"(pid)
);
printf("current process's pid(ASM):%d\n",pid);
return 0;
}
私のアプリケーションだけで、pidを1とプロセスで、私は、コマンドを入力しgetpidをそうするたびに実行されるので、それは本当だ。もちろん、1を返します。
gyscを使用してsyscallプロセスをデバッグすると、実行するgetpidとタイプすると、berakpoint sys_getpidで一度だけ停止します。何度も何度もやり直すと、止まることなく出力されます。
明らかに、int $ 0x80の使用は私が理解するように絶対に正しいです。
問題を解決するために、私はいくつかの研究を行いました。 glibcソース(glibc-2.25)コードをダウンロードして、api getpidがint $ 0x80をどのようにラップするかを確認します。残念ながら、それはそこになかったか、私はちょうど正しい位置を見つけられませんでした。
glibcのコード。
pid_t getpid(void)
{
pid_t (*f)(void);
f = (pid_t (*)(void)) dlsym (RTLD_NEXT, "getpid");
if (f == NULL)
error (EXIT_FAILURE, 0, "dlsym (RTLD_NEXT, \"getpid\"): %s", dlerror());
return (pid2 = f()) + 26;
}
私に間違ったコードがある場合は、教えてください。
コードに示すとおり、getpidの定義はglibcには含まれていません。いくつかのデータを読んだ後、誰かがthe VDSO...と言った。
単純なシステムコール のコストの重要な部分であるAFAIKは、ユーザー空間からカーネルに戻ってきていることに注意してください。したがって、いくつかのシステムコール (おそらくgettimeofday、getpid ...)では、VDSOは でさえ回避することができます(そして、技術的には実際のシステムコールを避けるかもしれません)。男GETPID pgaeで
:
C glibcのバージョン2.3.4以降のライブラリ/カーネルの違い 、GETPID用glibcのラッパー関数() キャッシュのPIDを、追加のシステムコールを避けるためにプロセス がgetpid()を繰り返し呼び出すとき。通常、このキャッシュは見えませんが、 の正しい操作は、 fork(2)、vfork(2)、およびclone(2)のラッパー関数のサポートに依存します。アプリケーションがglibc ラッパーをバイパスしてsyscall(2)を呼び出すと、子の getpid()を呼び出すと間違った値が返されます(正確には、 は親プロセスのPIDを返します)。 clone(2)も参照してください。 glibcラッパー関数を使用して を呼び出しても、getpid()が間違った値を返す場合があります。
私はAPI getpidの作業手順を分かりません。
対照的に、API時間はわかりやすいです。時間の 定義:その後、
time_t
time (time_t *t)
{
INTERNAL_SYSCALL_DECL (err);
time_t res = INTERNAL_SYSCALL (time, err, 1, NULL);
/* There cannot be any error. */
if (t != NULL)
*t = res;
return res;
}
、
#define INTERNAL_SYSCALL(name, err, nr, args...) \
internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \
"IK" (SYS_ify (name)), \
0, err, args)
最後に、それが埋め込まれていASM、カーネルソースを使用する通常の方法。
API getpidの仕組みを誰かが明確に説明できますか? getpidがシステムコールsys_getpidに1回だけトラップするのはなぜですか?可能であれば、いくつかの参考文献を賞賛する。
ありがとうございました。
あなたの質問は何ですか?あなたはマニュアルを読んでいます:glibcはgetpid-syscallによって返された値をキャッシュします。明らかに、このキャッシュは、子プロセスでfork(2)の後に再設定する必要があります。 –
あなたの答えをありがとう。 dlsymを使ったgetpidのメカニズムは何ですか? getpidの実現が他のものと異なるのはなぜですか?それは私が知りたいことです。ありがとう。 –