システムコールを行う汎用関数を記述したいと思います。何かのようにLinux上のシステムコール引数のタイプは?
long my_syscall2(long number, long arg1, long arg2);
できるだけポータブルにしたいです。実装は明らかにすべてのアーキテクチャで異なります。関数のシグネチャも異なる必要がありますか? long
を使用することはできますか?何か他のものを使用する必要がありますか?
- カーネルは、いくつかのdark magicを使用しています:(__SYSCALL_DEFINExは、__SC_LONGは魔法が含まれているタイプを取得するために__SC_LONGを呼び出して)ここ は、私が見つけた可能な解決策です。私はどこかで、ユーザ空間の型がカーネル空間の型と同じではないと聞いたので、私はそれを使うことができるかどうかわかりません。
- musl-libc uses long for all architectures that it supports except x32:([arch] /syscall_arch.hで定義されています)。
- 私は、サポートするすべてのプロセッサアーキテクチャとコンパイラのドキュメント、レジスタサイズと整数型サイズを検索し、レジスタと同じサイズの整数型を選択できます。だから、
私は質問があると思います「『システムコールの引数の型は常にx32のようないくつかの例外を除いてlong
ある』または私はすべてのアーキテクチャとコンパイラのドキュメントを検索しないといけないと言ういくつかのルールがありますか?」
編集:私はいくつかのシステムコールをパラメータとしてポインタと他のタイプを取ることを知っています。私はジェネリックパラメータ型を使って任意のシステムコールを呼び出すことができるジェネリック関数を記述したいと思います。これらの汎用パラメータ型は、実際のパラメータ型を保持するのに十分な大きさでなければなりません。 syscall()機能があるので可能です。
Edit2:これは、この問題の別の部分的な解決方法です。現在、次のようになり、これらの機能の
実装:
static __inline long my_syscall2(long number, long arg1, long arg2)
{
unsigned long ret;
__asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(number), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
は興味深い部分は、これがレジスタa
に格納されたシステムコールの戻り値が変数ret
に保存する必要があることを意味し、"=a"(ret)
です。ローカル変数を作成する関数を書く代わりに、syscallを作成し、その戻り値を変数に保存し、変数を返します。これは、システムコールを作成し、その結果を呼び出し側が提供する変数に格納する変数です。それは次のようになります。
#define my_syscall2(RET, NUMBER, ARG1, ARG2) \
__asm__ __volatile__ ("syscall" : "=a"(RET) : "a"(NUMBER), "D"(ARG1), "S"(ARG2) \
: "rcx", "r11", "memory");
そして、それは次のように使用されるでしょう:私は値を保持するのに十分な大きさのサイズと整数型を登録知る必要はありません
long result;
void * arg1;
int arg2;
my_syscall2(result, <syscall number>, arg1, arg2);
この方法レジスタの
パラメータを使用しないシステムコールはどのように処理しますか? – edmz
@black私は6つの関数を定義しますmy_syscall {0-5} – alkedr
実際にはここでは簡単に答えられるよりも複雑ですが(アーキテクチャを指定しない限り)、私のパブリックドメイン実装のsyscall()マクロとsyscall0 )-syscall6()関数はhttps://github.com/technosaurus/BQC ...すべてがパラメータのために長くキャストされています – technosaurus