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 データベースの基礎 - 結合操作の原理

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

推薦する

Vue の双方向イベントバインディング v-model の原理についての簡単な説明

目次説明する:要約する補充するDOM を直接変更して操作する js や jQuery とは異なり、V...

MySQL インデックスの正しい使い方とインデックスの原理の詳細な説明

1. はじめになぜインデックスが必要なのでしょうか?一般的なアプリケーション システムでは、読み取り...

Tomcat でのサーブレットの作成と実装に関する深い理解

1. サーブレットとは何か1.1. 正式な言葉で説明する:サーブレットは、動的な Web リソースを...

nginx + php の「入力ファイルが指定されていません」の解決策

本日、ローカル開発環境で突然「入力ファイルが指定されていません」というエラーが発生してしまいました。...

IDEA で mysql8.0.3 と mybatis-generator を使用する際に発生するバグ

1. プラグインを追加し、pomファイルの下に次の設定を追加します。 <!-- mybatis...

MySQL での find_in_set() 関数の使用に関する詳細な説明

まず、例を見てみましょう。記事テーブルにはタイプフィールドがあり、1 見出し、2 おすすめ、3 ホッ...

ローカル フォルダー内の画像を読み込んで表示するための HTML サンプル コード

一つの目的Html ページでローカル フォルダーを選択すると、フォルダーとそのサブフォルダー内のすべ...

CSS3はトランジション効果を実現するためにtransitionプロパティを使用する。

物件の詳細な説明transition 属性の目的は、一部の CSS プロパティ (背景など) をスム...

MySQL エラー コード 1862 の解決方法: パスワードの有効期限が切れています

ブロガーは 1 ~ 2 か月間 MySQL を使用していませんでしたが、今日この問題に遭遇しました。...

vue+antv でレーダーチャートを実装するためのサンプルコード

1. 依存関係をダウンロードするnpm インストール @antv/データセットnpm インストール ...

まだ*を選択しますか?

アプリケーションが牛のように遅い理由は数多くあります。ネットワーク、システム アーキテクチャ、または...

HTML テキストフォーマットの簡単な例 (詳細な説明)

1. テキストの書式設定: この例では、HTML ファイル内のテキストを書式設定する方法を示します...

MySQLクエリトランザクション処理へのノード接続の実装

目次トピックmysqlの追加、削除、変更、クエリを入力しますMySQL トランザクション処理私は M...

IE6 で CSS スタイルの div または li の背景のタイリングと境界の破損を解決する方法

IE6 で CSS スタイルの div または li の背景のタイリングや境界の破壊を解決するには、...