3

自分でシステムコールを書こうとしています。現在の時刻を返すだけです。私は何をすべきかという概念を知っており、次のようないくつかのリンクをたどりました。

しかし、私はまだ混乱していて、望ましい結果が得られていません。カーネルがコンパイルされておらず、問題が原因でクラッシュしています。3.XXのdebian最新の安定版リリースで試してみました

誰かが私にhello worldシステムコールを開発するためのクリーンな種類のプログラムを指摘してもらえますか?

編集

以下の答えに、ここに私の問題があります:

  1. File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.SLinuxフォルダに見つかりません。私は即興で次のファイルを修正しなければなりませんでした:linux-x.x.x/arch/x86/syscalls/syscall_64.tbl

  2. 上記の(1)上記の新しいファイルはパターンが異なり<number> <64/x32/common> <name> <entry point>、私のエントリは`313共通でした

  3. カーネルイメージは正常にコンパイルされましたが、関数を呼び出すことができませんでした。それはundefined reference" error私がgccでそれをコンパイルするときに与えます。なんで?

4

2 に答える 2

7

これは、単純なカーネル システム コールを記述する方法の単なる例です。次の C 関数 system_strcpy() を考えてみましょう。この関数は、単純にある文字列を別の文字列にコピーします: strcpy() が行うことと同様です。

#include<stdio.h>

long system_strcpy(char* dest, const char* src)
{
   int i=0;
   while(src[i]!=0)
      dest[i]=src[i++];

   dest[i]=0;
   return i;
}

書き込む前に、カーネル ソース tar を取得し、展開して linux-xxx ディレクトリを取得します。

ファイル 1: linux-xxx/test/system_strcpy.c linux-xxx 内にディレクトリを作成し、名前testを付けて、このコードをファイルとして保存system_strcpy.cします。

#include<linux/linkage.h>
#include<linux/kernel.h>
asmlinkage long system_strcpy(char*dest, const char* src)
{
   int i=0;
   while(src[i]!=0)
      dest[i]=src[i++];

   dest[i]=0;
   return i;
}

ファイル 2: linux-xxx/test/Makefile上で 作成したMakefileのと同じtestディレクトリ内に を作成し、次の行を入れます。

obj-y := system_strcpy.o

ファイル 3: linux-xxx/arch/x86/kernel/syscall_table_32.S ここで、システム コールをシステム コール テーブルに追加する必要があります。次の行をファイルに追加します。

.long system_strcpy

注: カーネル 3.3 以降のバージョンの場合。

*参照:linux-3.3.xx/arch/x86/syscalls/syscall_64.tbl*

そこに、次の一連の行の最後に追加します。

310 64 process_vm_readv sys_process_vm_readv

311 64 process_vm_writev sys_process_vm_writev

312 64 kcmp sys_kcmp

313 64 システム_strcpy システム_strcpy

3.3 バージョンの形式は次のとおりです。 number abi name entry point

ファイル 4: linux-xxx/arch/x86/include/asm/unistd_32.h

注: このセクションは、3.3 以降のカーネル バージョンでは冗長です。

このファイルでは、すべてのシステム コールの名前が一意の番号に関連付けられます。最後のシステム コール番号のペアの後に、行を追加します。

#define __NR_system_strcpy 338

(337 が、システム コール番号ペアの最後のシステム コールに関連付けられた番号である場合)。

次に、値を置き換えてNR_syscalls、システム コールの総数を (既存の数を 1 ずつ増やした数) に置き換えます。つまり、この場合はNR_syscalls338 である必要があり、新しい値は 339 です。

#define NR_syscalls 339

ファイル 5: linux-xxx/include/linux/syscalls.h

関数のプロトタイプをファイルに追加します。

asmlinkage long system_strcpy(char *dest,char *src);

#endifファイルの行の直前。

ファイル 6: ソース ディレクトリのルートにある Makefile。

が定義されている行を開いMakefileて見つけ、その行の最後にcore-yディレクトリを追加します。test

core-y += kernel/ mm/ fs/ test/

カーネルをコンパイルします。問題: make bzImage -j4

次のコマンドを root として (または root 権限で) 実行して、カーネルをインストールします。 make install

システムを再起動します。

最近作成されたシステム コールを使用するには、次のようにします。

syscall(338,dest,src);(またはsyscall(313,dest,src);カーネル 3.3+ の場合) 通常のstrcpyライブラリ関数の代わりに。

#include "unistd.h"
#include "sys/syscall.h"
int main()
{
 char *dest=NULL,*src="Hello";
 dest=(char*)malloc(strlen(src)+1);
 syscall(338,dest,src);//syscall(313,dest,src); for kernel 3.3+
 printf("%s \n %s\n",src,dest);
 return 0;
}

の 313 などの数字の代わりに、syscall直接使用することもできます__NR_system_strcpy

これは一般的な例です。特定のカーネル バージョンで何が機能するかを確認するには、少し実験を行う必要があります。

于 2012-09-18T10:05:40.387 に答える
4

上記の回答は、カーネル 3.5.0 および 3.7.6 では機能せず、未定義の参照コンパイル エラーが発生します。この問題を修正するには、linux/linkage.h の代わりに linux/syscalls.h を system_strcpy.c に含める必要があります。また、SYSCALL_DEFINE2(strcpy, dest, src) を使用してシステム コールを定義することをお勧めします。

于 2013-02-11T01:49:35.490 に答える