Linux カーネル デバイス ドライバー システム コールに関する注意事項

Linux カーネル デバイス ドライバー システム コールに関する注意事項
/****************************
 * システムコール********************************/

(1)システムコールとは何か?

システム コールは、カーネルとアプリケーション間のインターフェイスです。アプリケーションがハードウェア デバイスやその他のオペレーティング システム リソースにアクセスする場合は、システム コールを介してアクセスする必要があります。

Linux では、システム コールはユーザー空間がカーネルにアクセスするための唯一の手段です。例外と割り込みを除き、システム コールはカーネルへの唯一の正当なエントリ ポイントです。システムコールの数は少なく、i386 では約 300 個のみです。

(2)Cライブラリとシステムコールの関係

アプリケーション プログラマーは、システム コールを直接使用するのではなく、C ライブラリのアプリケーション プログラミング インターフェイス (API) を介してプログラミングを行います。 C ライブラリ内の関数は、システム コールを呼び出さないか、システム コールを単にカプセル化するか、複数のシステム コールを呼び出すことによって関数を実装する場合があります。

アプリケーション --> C ライブラリ --> カーネル システム コール

プログラマーの観点から見ると、システム コールは無関係であり、API のみを処理すればよいのです。

カーネルの観点から見ると、カーネルはシステム コールのみを処理します。ライブラリ関数とアプリケーションがシステム コールをどのように使用するかはカーネルの関心事ではありません。

Unix システム コールは、特定の目的を達成するために使用される関数を抽象化します。これらの関数をどのように使用するかはユーザーの責任であり、カーネルは気にしません。

(3)カーネルに実装されたシステムコール機能

ユーザー空間でのシステムコールの使用例

#include <unistd.h>
pid を取得します。

glibc ライブラリによってカプセル化された後、最終的にはカーネル内の kernel/timer.c の sys_getpid 関数が呼び出されます。この機能を参照してください。カーネル内のすべてのシステム コール関数は sys_ で始まります。

  • asmlinkageは、ローカルスタックを使用してパラメータを渡すようにコンパイラに指示します。
  • FASTCALL マクロは、レジスタを使用してパラメータを渡すようにコンパイラに指示します。

(4)システムコール番号

システム コールはユーザー空間からカーネル空間に入る必要があるため、単純な関数呼び出しでは完了できず、プロセッサによってサポートされているいくつかの特別なメカニズム (いわゆるソフト割り込み) を経由する必要があります。

x86 では、この特別なメカニズムはアセンブリ命令 int $0x80 であり、arm ではアセンブリ命令 SWI です。

この命令は、C ライブラリの関数にカプセル化されています。プログラムがこの命令を実行すると、CPU は特別な例外モード (またはソフト割り込みモード) に入り、プログラム ポインターを特定の位置 (ARM の割り込みベクター テーブルの 0x8 など) にジャンプします。

カーネルには多くのシステム コールが実装されています。これらのシステム コールのアドレスは、システム コール テーブルに順番に配置されます。このテーブルは sys_call_table と呼ばれる配列で、合計 NR_syscalls 個のエントリがあります。このテーブルを通じて、カーネルで定義されたすべてのsys_関数を呼び出すことができます。

アセンブリ命令 int $0x80 または SWI を呼び出すときは、同時にシステム コール番号を渡す必要があります。このシステム コール番号は、sys_call_table から対応するシステム コールを選択するためのインデックスとして使用されます。

int80 はシステムコール番号を eax レジスタに保存しますが、SWI はそれを命令に直接統合します (SWI 0x124 など)。

(5)システムコール実装機構

カーネル内のシステム コールを処理する関数は、arch/i386/kernel/entry.s の system_call で定義されていますが、arm システムは、arch/arm/kernel/entry-common.s の vector_swi で定義されています。 x86 システムのシステム コール テーブルは arch/i386/kernel/syscall_table.s (または直接 entry.s) で定義されていますが、arm システム コール テーブルは arch/arm/kernel/calls.s で定義されています。システム コール番号は include/asm/unistd.h で定義されています。

(6)システムコールを実装する際に注意すべき点

Linux にシステム コールを追加することは難しくありませんが、システム コールをどのように設計して実装するかが難しい点です。 Linux では、多目的システム コール (異なるパラメーターに基づいて異なる機能を提供する) の使用は推奨されていません。

システム コールは、受信パラメータ、特にユーザー指定のポインタの有効性を慎重にチェックし、次の点を確認する必要があります。

  • *ポインタが指すメモリ領域はユーザー空間に属しており、プロセスはカーネルを騙してカーネル空間のデータを読み込ませることはできない。
  • *ポインタが指すメモリ領域はプロセスのアドレス空間に属し、カーネルを騙して他のプロセスからデータを読み取らせることはできません。
  • *プロセスはメモリアクセス権限をバイパスできません。

システム コールを実行する場合、カーネルはプロセス コンテキストにあり、スリープ状態になったり、プリエンプトされたりする可能性があるため、システム コールは再入可能でなければなりません。

(7)システムコールの例(カーネルの変更とユーザー空間プログラムの実装を含む)

システムコールsys_fooを実装する

a. システムコール番号を追加する

include/asm/unistd.hを変更し、 #define __NR_foo 289を追加し、 #define NR_syscalls 290を変更します。

b. システムコールテーブルに追加

arch/i386/kernel/entry.s または syscall_table.s を変更し、以下を追加します。

.long sys_foo

c. システム コールは、コア カーネル イメージにコンパイルする必要があります。システム コールの定義は、kernel/sys.c など、その機能に最も関連のあるコードに配置し、次のコードを追加できます。

#include <asm/thread_info.h>
/* 
 * カーネルスタックのサイズを返す
 */
asmlinkage long sys_foo(void)
{
 THREAD_SIZE を返します。
}

d. ユーザー空間での呼び出し

通常、システムコールは C ライブラリによってサポートされており、glibc は独自のシステムコールをサポートできません。現時点では、システムコールに直接アクセスするには、Linux 自体が提供するマクロのセットを使用する必要があります。

man 2 syscall

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。これについてもっと知りたい場合は、次のリンクをご覧ください。

以下もご興味があるかもしれません:
  • Linux でプロセスのシステム コールとパラメータを取得する (トラブルシューティングのケース)
  • Linux C におけるライブラリ関数とシステムコールの違いの詳細な分析
  • Linux システムコールと標準ライブラリコールの違いの詳細な分析
  • Linux システムコールを実装する 3 つの方法
  • Linux システムコールに基づく方法 - getrlimit() および setrlimit() 関数
  • Linuxシステムコール原理の詳細な説明
  • Linuxで中断されたシステムを呼び出す方法

<<:  Reactドラッグフックを実装するための100行以上のコード

>>:  MySQL の基本ステートメントを最適化するための 10 の原則の概要

推薦する

node.jsのコアモジュールとは

目次グローバルオブジェクトグローバルオブジェクトとグローバル変数プロセスコンソール一般的なツールユー...

nginx ウェブサイト サービスのアンチホットリンクを設定する方法 (推奨)

1. ホットリンクの原則1.1 Webページの準備Web ソース ホスト (192.168.153...

CSSスプライト技術は複数の背景を1つのPNG画像に統合しますCSSポジショニング

アメリカのYAHOOがページ制作で使用している画像統合技術。これらのアイコン、列背景、画像ボタンを定...

Vueはダイアログのカプセル化を実装します

目次Vue2 ライティングVue3プラグインのバージョンの記述Vue3 動的コンポーネントの記述書き...

sqlite を mysql スクリプトに移行する方法

さっそく、コードを直接投稿します。具体的なコードは次のとおりです。 パーレル # # https:/...

vscodeを使用してuniappを開発する方法

私はフロントエンド プロジェクトの開発に常に vscode を使用してきたため、現在ではいくつかの小...

Vue で PC 解像度の適応を実装するためのサンプルコード

目次プラン依存関係をインストールする依存関係の導入pxをremに変換するFlexible.jsを変更...

mini-vueレンダリングのシンプルな実装

目次序文ターゲット最初のステップ:ステップ2:ステップ3:ステップ4:要約する序文現在主流のフレーム...

HTML、CSS、RSSフィードが正しいかどうかを確認する無料ツール

この種のエラーに対処するための 1 つの方法は、まずマークアップとスタイルシートを検証することです。...

Nginx Rewrite の使用シナリオとコード例の詳細な説明

Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....

Nginx+ModSecurity セキュリティモジュールの導入

目次1. ダウンロード2. 展開1.Nginxのデプロイメント2. ModSecurityの展開3....

ホワイトボードを踏まないようにするゲームを実装するための HTML+CSS+JS

目次背景1. 思考分析2. ページ構成2.1 HTML レイヤー2.2 CSS レイヤー2.3 JS...

Vueはシンプルなスライダー検証を実装する

この記事の例では、Vueスライダー検証の実装を共有しています。コードは次のとおりです。 <テン...

IDEAでVUEプロジェクトをデバッグするための詳細な手順

js コードをデバッグするには、コード内にデバッガーを記述するか、Chrome で毎回ブレークポイン...

知っておくべき 25 の Vue のヒント

目次1. プロパティを型リストに制限する2. デフォルトのコンテンツと拡張ポイント3. ネストされた...