目次- Linux ドライバーの共通機能 (copy_from_user open read write)
- 1.開く
- 2.読む
- 3.書く
- 4.ユーザーにコピー
- 5.ユーザーからコピー
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 の基礎
|