Linux ドライバ開発でよく使われる関数 copy_from_user open read write の詳細な説明

Linux ドライバ開発でよく使われる関数 copy_from_user open read write の詳細な説明

Linux ドライバーの共通機能 (copy_from_user open read write)

1.開く

関数定義:
int open( const char * pathname, int flags);
int open( const char * pathname,int flags, mode_t mode);
パラメータの説明:
パス名: ファイル名。絶対パスと相対パスを含めることができます。
フラグ: ファイルを開くモード
モード: ファイル所有者、ファイルのユーザー グループ、およびシステム内の他のユーザーのアクセス権を定義するために使用されます。ファイルの権限は次のとおりです: mode&(~umask)
機能説明:
パス名パラメータは、開くファイル パス文字列を指します。 flags パラメータで使用できるフラグは次のとおりです。

  • O_RDONLY はファイルを読み取り専用モードで開きます。
  • O_WRONLY はファイルを書き込み専用で開きます。
  • O_RDWR はファイルを読み取りおよび書き込み可能モードで開きます。

上記の 3 つのフラグは相互に排他的であり、同時に使用することはできませんが、OR (|) 演算子を使用して次のフラグと組み合わせることができます。

  • O_CREAT 開くファイルが存在しない場合は、ファイルが自動的に作成されます。
  • O_EXCL O_CREAT も設定されている場合、このコマンドはファイルが存在するかどうかを確認します。ファイルが存在しない場合は作成されます。存在しない場合は、ファイルを開く際にエラーが発生します。また、O_CREAT と O_EXCL が同時に設定されており、開くファイルがシンボリックリンクの場合、ファイルのオープンは失敗します。
  • O_NOCTTY 開くファイルが端末デバイスの場合、その端末はプロセス制御端末として使用されません。
  • O_TRUNC ファイルが存在し、書き込みモードで開かれている場合、このフラグはファイルの長さを 0 にクリアし、ファイルに元々保存されていたデータは消えます。
  • O_APPEND ファイルの読み取りまたは書き込み時に、データがファイルの末尾に追加されます。
  • O_NONBLOCK はブロックできない方法でファイルを開きます。つまり、読み取るデータや待機するデータがあるかどうかに関係なく、すぐにプロセスに戻ります。
  • O_NDELAY は O_NONBLOCK と同じです。
  • O_SYNC はファイルを同期的に開きます。
  • O_NOFOLLOW パラメータパス名が指すファイルがシンボリックリンクの場合、ファイルのオープンは失敗します。
  • O_DIRECTORY パラメータ パス名で指定されたファイルがディレクトリでない場合、ファイルのオープンは失敗します。

これは、いくつかのシステム セキュリティの問題を回避するための、Linux 2.2 以降に固有のフラグです。パラメータ mode には以下の組み合わせがあり、新規ファイル作成時にのみ有効となります。また、実際にファイルを作成する際の権限は umask 値の影響を受けるため、ファイル権限は (mode-umaks) とする必要があります。

  • S_IRWXU00700 権限。これは、ファイル所有者が読み取り、書き込み、および実行権限を持っていることを意味します。
  • S_IRUSR または S_IREAD、00400 権限。これは、ファイル所有者が読み取り権限を持っていることを意味します。
  • **S_IWUSR または S_IWRITE、00200 ** 権限、ファイル所有者に書き込み権限があることを示します。
  • S_IXUSR または S_IEXEC、00100 権限。これは、ファイル所有者が実行権限を持っていることを意味します。
  • S_IRWXG 00070 権限。これは、ファイル ユーザー グループに読み取り、書き込み、および実行権限があることを意味します。
  • S_IRGRP 00040 権限。ファイル ユーザー グループに読み取り権限があることを示します。
  • S_IWGRP 00020 権限。ファイル ユーザー グループに書き込み権限があることを示します。
  • S_IXGRP 00010 権限。ファイル ユーザー グループに実行権限があることを示します。
  • S_IRWXO 00007 権限。これは、他のユーザーに読み取り、書き込み、実行権限があることを意味します。
  • S_IROTH 00004 権限。他のユーザーには読み取り権限があることを示します。
  • S_IWOTH 00002 権限。他のユーザーに書き込み権限があることを示します。
  • S_IXOTH 00001 権限。他のユーザーには実行権限があることを示します。

戻り値:
チェックするすべての権限がチェックに合格すると、成功を示す 0 の値が返されます。いずれかの権限が拒否された場合は、-1 が返されます。

エラーコード:
EEXIST パラメータ パス名で参照されるファイルは既に存在しますが、O_CREAT および O_EXCL フラグが使用されています。
EACCESS パラメータ パス名が指すファイルは、テストに必要な権限を満たしていません。
EROFS 書き込み権限をテストするファイルは読み取り専用ファイル システムに存在します。
EFAULT パラメータ パス名ポインタがアクセス可能なメモリ領域を超えています。
EINVAL パラメータ モードが正しくありません。
ENAMETOOLONG パラメータのパス名が長すぎます。
ENOTDIR パラメータ パス名はディレクトリではありません。
ENOMEM カーネルメモリが不足しています。
ELOOP パラメータ パス名にシンボリック リンクが多すぎます。
EIO I/O アクセス エラー。

#含む
#含む
#含む
#含む
主要()
{
    int fd、サイズ;
    char s[]=”Linuxプログラマー!\n”,buffer[80];
    fd = open("/tmp/temp", O_WRONLY | O_CREAT);
    書き込み(fd,s,sizeof(s));
    閉じる(fd);
    fd = open ("/tmp/temp", O_RDONLY);
    サイズ=読み取り(fd、バッファ、バッファのサイズ)。
    閉じる(fd);
    printf("%s",バッファ);
}

2.読む

関数定義:
ssize_t read(int fd, void * buf, size_t count);

機能の説明:
read() は、パラメータ fd が指すファイルから buf ポインタが指すメモリに count バイトを転送します。

戻り値:
戻り値は実際に読み取られたバイト数です。0 が返された場合は、ファイルの末尾に到達したか、読み取るデータがもうないことを意味します。 count パラメータが 0 の場合、read() は効果がなく、0 を返します。

知らせ:
読み取り時に fd 内のデータが読み取るデータより小さい場合、ブロックが発生します。
read の使い方は write よりも簡単なので、ここでは詳細には説明しません。著者のレベルが限られているため、記事に誤りがある場合は、皆様に誤解を与えないようご指摘いただければ幸いです。

3.書く

関数定義:
ssize_t write (int fd, const void * buf, size_t count);

機能の説明:
write() は、パラメータ buf が指すメモリから count バイトをパラメータが指すファイルに書き込みます。

戻り値:
すべてがうまくいけば、write() は実際に書き込まれたバイト数を返します。エラーが発生した場合は -1 が返され、エラー コードが errno に格納されます。
(1) write() 関数の戻り値は通常 0 ではありません。write(fp, p1+len, (strlen(p1)-len) の 3 番目のパラメータが 0 である場合にのみ 0 を返します。この場合、write() は何も行わず、0 のみを返します。man マニュアルに記載されている write() の戻り値の説明は次のとおりです。
(2) write()関数がbufからfdにデータを書き込むとき、bufのデータを一度にすべて読み取れない場合、bufのデータを2回目に読み取るときに、その読み取り位置ポインタ(つまり、2番目のパラメータbuf)は自動的に移動しません。プログラマは、bufの最初のアドレスを2番目のパラメータに単に入力するのではなく、プログラムで制御する必要があります。たとえば、読み取り位置は、write(fp, p1+len, (strlen(p1)-len) という形式で移動できます。このように、2 番目の書き込みループでは、p1+len から fp にデータが書き込まれ、(strlen(p1)-len) が 0 になるまで、残りの部分でも同じ処理が行われます。

次の例は、書き込み関数の使用方法を示しています。

#含む 
#含む 
#含む 
int メイン()
{
  char *p1 = "これはACテストコードです";
  揮発性int len ​​= 0;
 
  int fp = open("/home/test.txt", O_RDWR|O_CREAT);
  のために(;;)
  {
     整数n;
 
     if((n=write(fp, p1+len, (strlen(p1)-len)))== 0) //if((n=write(fp, p1+len, 3)) == 0) 
     { //strlen(p1) = 21
         printf("n = %d \n", n);
         壊す;
     }
     長さ+=n;
  }
  0を返します。
}

(3)一度に書き込むことができる最大データ範囲(BUFSIZ、8192と思われる)内では、エラーを回避するために、3番目のパラメータcountはbuf内のデータのサイズにするのが望ましい。 (再度テストしてみたところ、一度に書き込めるデータの最大数は 8192 ではないことがわかりました。81920000 を一度に書き込んでみましたが、結果も OK でした。一度に書き込めるデータの最大数は 8192 ではないようです。ただし、カーネル内には確かに BUFSIZ というパラメータがあり、その具体的な意味は未だ調査中です。)

4.ユーザーにコピー

関数定義:
unsigned long copy_to_user(void *to, const void *from, unsigned long n)
パラメータの説明:
to: ターゲットアドレス(ユーザー空間)
from: 送信元アドレス (カーネル空間)
n: コピーするデータのバイト数
機能の説明:
カーネル空間からユーザー空間にデータを読み取る
戻り値:
成功した場合は 0 を返し、失敗した場合は正常にコピーされなかったデータのバイト数を返します。

5.ユーザーからコピー

関数定義:
unsigned long copy_from_user(void *to, const void *from, unsigned long n);
パラメータの説明:
to: ターゲットアドレス(カーネル空間)
from: 送信元アドレス (ユーザー空間)
n: コピーするデータのバイト数
機能説明:
ユーザー空間からカーネル空間にデータを読み取る
戻り値:
成功した場合は 0 を返し、失敗した場合は正常にコピーされなかったデータのバイト数を返します。

上記は、Linux ドライバーのよく使われる機能 (copy_from_user open read write) の詳細です。Linux ドライバーのよく使われる機能の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。今後とも123WORDPRESS.COMをよろしくお願いいたします!

以下もご興味があるかもしれません:
  • Linuxサービスの監視と運用および保守
  • Linux スクリプトの基礎を詳しく紹介
  • Linux カーネルプログラミングにおけるコンテナの of() 関数の紹介
  • VS2019 で Linux C++ プログラムを開発するための実装手順
  • Linux 上級学習マニュアル (パート 2)
  • Linux 上級学習マニュアル (パート 1)
  • 学習マニュアル - Linux の基礎

<<:  MYSQL データベースの基礎 - 結合操作の原理

>>:  ボックスモデルのサイズの詳細な説明は、パディング、マージン、境界の値によって異なります。

推薦する

CSS を使用して fullpage.js のフルスクリーン スクロール効果を実装するサンプル コード

最近 CSS を勉強していたとき、 2 つの CSS プロパティだけを使用して全画面スクロール効果を...

Linux でのマルチスレッドにおけるフォークの紹介

目次質問:ケース(1)子スレッドを作成する前にフォークするケース(2)子スレッドを作成した後にフォー...

画像内のrarファイルを隠す方法

このロゴを .rar ファイルとしてローカルに保存し、解凍して効果を確認することができます。よりシン...

MySQLはテーブル内のフィールドを別のテーブル内のフィールドの値と等しくなるように更新します

以下のように表示されます。 table1 を z として更新し、table2 を zb として結合し...

テーブル切り替えのための JavaScript プラグインのカプセル化

この記事では、テーブル切り替えプラグインを実装するためのJavaScriptのカプセル化コードを参考...

CSS テキスト強調を使用してテキストを強調するための実装コード

1. はじめにこれまで、テキストの特定の部分を強調したい場合、通常は太字にしたり明るい色を使用したり...

LinuxベースのLVMシームレスディスク水平拡張の詳細な説明

環境名前財産CPU 5650 円メモリ4Gディスク20G+4TB この時点で、サーバーにはすでに次の...

JavaScript setinterval 1秒遅延ソリューション

setinterval を使用すると、ページを開いた直後に 1 秒の遅延後に実行されることがわかりま...

MySql インデックスの詳細な紹介と正しい使用方法

MySql インデックスの詳細な紹介と正しい使用方法1. はじめに:インデックスはクエリ速度に重大な...

Linux で yum と入力した後に -bash: /usr/bin/yum: No such file or directory という問題を解決する方法

Linuxでyumを入力すると、プロンプトが表示されます: -bash: /usr/bin/yum:...

WeChatアプレットがテキストスクロールを実装

この記事の例では、WeChatアプレットでテキストスクロールを実装するための具体的なコードを参考まで...

JavaScriptはシンプルな計算機能を実装します

この記事では、参考までに、簡単な計算機を実装するためのJavaScriptの具体的なコードを紹介しま...

サーバーストレステストの概念と方法 (TPS/同時実行性)

目次1 ストレステストの指標1.1 秒あたり1.2 クォータ1.3 平均処理時間(RT) 1.4 同...

Elementのメッセージポップアップウィンドウが繰り返しポップアップする問題の解決

目次1. 使用2. メッセージポップアップウィンドウが繰り返し表示される問題を解決する1. 使用Vu...

Nginx がフロントエンド リソースへのクロスドメイン アクセスの問題をどのように解決するかの詳細な説明

フロントエンドのクロスドメイン問題に2日間近く悩まされましたが、ようやくngnxを使って解決したので...