
Linuxには、ファイルを開くためのプログラム要求を処理するレイヤ/スクリプトがありますか?
Bashでファイル記述子を開くときと同じです。exec 3 <>/documents/foo.txt
または、テキストエディタが開いたときと同じです。/documents/foo.txt
編集者が独自の読み取り/書き込みアクセスのために「ファイルを開く」ことができるとは信じられません。
むしろこれが「レイヤー」に対する要請だと思います(init.dスクリプト?)、最初は特定の数のファイルのみを開くことができ、アクセスタイプ、ファイルを開いたプロセスなどに応じて開こうとしているファイルを注意深く観察できます。
答え1
このレイヤーはLinuxや他のシステムのカーネル内にあり(ほとんどの非Unixオペレーティングシステムと同様)、歴史的なUnixデザインとは大きく変わりません。
カーネルのこの部分をカーネルといいます。VFS(仮想ファイルシステム)層。 VFSの機能は、開いたファイルの情報(ファイル間対応)を管理することです。ファイル記述子、ファイル説明を開くおよびディレクトリエントリ)、ファイルパスを確認し(および解釈)、ディレクトリエントリの操作を/
正しいファイルシステムドライバに渡します。.
..
ほとんどのファイルシステムドライバもカーネルにありますが、ヒューズファイルシステムドライバを使用すると、この機能をカーネルの外部に委任できます。たとえば、ディスクファイルシステムがある場合など、低レベルのリポジトリで実行されている場合、ファイルシステムの操作にはユーザードメインコードが含まれる場合があります。循環装置。
答え2
Linuxでは、ファイルを開くことはカーネルによって直接処理されます。しかし、プロセスに影響を与え、研究するためにできることがあります。
システムコール
一番上から、アプリケーションがファイルと対話するために使用するインターフェースが次のようになります。システムコール。
開いている、読むそして書くその間期待どおりにしなさい統計資料ファイルを開かずにファイルに関する情報を返します。
straceを使用して、プログラムのファイル関連システムコールの使用を調べることができます。
$ strace -e trace=%file /bin/ls /etc
[...]
stat("/etc", {st_mode=S_IFDIR|0755, ...}) = 0
openat(AT_FDCWD, "/etc", O_RDONLY...) = 3
これは、結果のシステムコールを分析し、ディレクトリ内およびが呼び出されていることls /etc
を示しています。stat
openat
/etc
ディレクトリからファイル操作を呼び出す理由は疑問に思います。 UNIXでは、ディレクトリもファイルです。実際にすべてがファイルです!
ファイル記述子
openat() = 3
上記の出力内容が何であるか疑問に思います。
UNIXでは、ファイルが次に開きます。ファイル記述子、これはプロセスで開かれたファイルの唯一の表現です。ファイル記述子0、1、2は通常予約されています。標準ストリーム(ユーザー入力/出力)なので、初めて開くファイルは3になります。
以下を使用して、特定のプロセスに対して開かれたファイル記述子のリストを取得できます。lsof
(私私SティーああペンF島):
$ cat /dev/urandom > /dev/null &
[1] 3242
$ lsof -p 3242
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
...
cat 3242 user 0u CHR 136,0 0t0 3 /dev/pts/0
cat 3242 user 1w CHR 1,3 0t0 1028 /dev/null
cat 3242 user 2u CHR 136,0 0t0 3 /dev/pts/0
cat 3242 user 3r CHR 1,9 0t0 1033 /dev/urandom
このFD
列にはファイル記述子番号とアクセス権が表示されます。
また、使用することができますfuser
特定のファイルを保存するプロセスを検索します。
$ fuser /dev/urandom
/dev/urandom: ... 3242 ...
プロセス情報擬似ファイルシステム-/proc
今あなたは疑問に思うでしょう:しかし、何をすべきlsof
か?
さあ、一度見てみましょう!
$ strace -e trace=%file lsof -p 3242
...
stat("/proc/3242/", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
openat(AT_FDCWD, "/proc/3242/stat", O_RDONLY) = 4
...
openat(AT_FDCWD, "/proc/3242/fd", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 4
readlink("/proc/3242/fd/0", "/dev/pts/0", 4096) = 10
lstat("/proc/3242/fd/0", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0
stat("/proc/3242/fd/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
openat(AT_FDCWD, "/proc/3242/fdinfo/0", O_RDONLY) = 7
...
したがって、lsof
どのファイルを開くかを確認してください。より多くのファイルを読んでください!特に、ディレクトリ/proc/3242/fd
の下のすべては、/proc
カーネルが保持する「偽の」ファイルシステムです。ls -l
ずっと見ながらその構造を見ることができます。
ファイルを開くのに影響します
ファイルを開くことに影響を与えるために使用できる方法はいくつかありますが、一部のスクリプトを置き換えるのと同じくらい簡単ではありません。
暗号化、キャッシュ、複数のディスクへのファイルの分散など、ファイルの保存やアクセス方法を変更したい場合は、デバイスマッパーあなたのニーズに適しています。
特定のディレクトリ/マウントでファイルを開くことを細かく制御するには、次のように簡単に作成できます。ヒューズファイルシステムをマウントしてマウントします。
プログラム/プロセスレベルでは、次のものを使用できます。LD_予圧Cライブラリ呼び出しを変更し、通常のシステム呼び出しが実行されないようにします。
最も難しいが最も柔軟な方法は、独自のファイルシステムドライバを作成することです。
答え3
ファイルへのアクセスを管理することは、オペレーティングシステムの最初で最も重要な機能です。 DOSは、パーソナルコンピュータで最も古いオペレーティングシステムの1つであり、ディスクオペレーティングシステムを意味します。ほとんどの場合、プログラムはハードウェアに直接アクセスできますが、ファイルにはアクセスできません。プログラムはDOS呼び出しを使用する必要があり、DOSはプログラムがデータを入れたり減算したりするファイルを管理します。ディスクユーティリティのみがDOSからハードドライブとファイルに直接アクセスできます。
最新の保護モードオペレーティングシステム(Linuxなど)はDOSのようにファイルアクセスを処理しますが、プログラム自体(またはメモリを共有するように設定された他のプログラム)以外のすべてのアクセスはカーネル(Linuxはカーネルです)
LinuxのプログラムはCライブラリの関数を呼び出してファイルデータを読み取ったり、ファイルにデータを書き込むことができます。その後、C ライブラリは、プログラムと同じコンテキストで実行され続けながら、ファイル内のデータへのアクセスを構成する役割を果たします。その後、Cライブラリはカーネル(Linux)への正しい関数呼び出しを使用してファイルにアクセスし、CPUをリング0または特権モードに切り替えます。これで、CPUはLinuxファイルシステムドライバとハードディスクドライバソフトウェアを特権モードで実行し、ハードウェアに直接アクセスしてファイルにアクセスします。データは、CライブラリがLinuxにデータを配置するように指示し、CPUがユーザモードに戻り、プログラムのセキュリティコンテキストを持ち、Cライブラリが再開され、必要なすべての処理を実行するメモリ領域にコピーされます。その後、このデータは実行のためにプログラムに返されます。
答え4
簡単に言えば、これはプログラムがファイルに書き込むときに起こるものです。
- プログラムは、
open
書き込みのためにカーネルのパスで指定されたファイルを要求します。 - カーネルはいくつかの内部構造を設定し、ファイルを開くいくつかの操作をファイルシステムタイプに関連するドライバに委任します。その後、カーネルは整数(例:3)のファイル記述子をプログラムに返します。
write
プログラムは、カーネルにファイル記述子が参照するファイルに一連のバイト(文字列など)を追加するように要求します。- カーネルは再びオペレーションをドライバに委任します。
- ステップ3と4は何度も繰り返すことができます。
close
プログラムは、ファイル記述子が参照するファイルをカーネルに要求します。- カーネルは再びオペレーションをドライバに委任し、内部構造を破壊する。
以下は、Greeting.txtファイルに「Hello World!」を書く非常に簡単なアセンブラプログラムです。
.text
.globl _start
_start:
# Open and possible create file
mov $2, %rax # syscall 'open'
mov $path_start, %rdi # path
mov $0101, %rsi # create + write
mov $400, %edx # only user gets read permissions
syscall
mov %rax, %r10 # file descriptor
# Write string to file
mov $1, %rax # syscall 'write'
mov %r10, %rdi # file descriptor
mov $msg_start, %rsi # start of data
mov $msg_length, %edx # length of data
syscall # perform syscall
# Close file
mov $3, %rax # syscall 'close'
mov %r10, %rdi # file descriptor
syscall
# Exit program
mov $60, %rax # syscall 'exit'
syscall # perform syscall
.section .rodata
path_start:
.string "greeting.txt\0"
path_end:
path_length = path_end - path_start
msg_start:
.string "Hello World!\n"
msg_end:
msg_length = msg_end - msg_start
コードをwrite.sに保存して次にビルドします。
as -o write.o write.s
ld -o write write.o
その後実行
./write
すべてが大丈夫であることを願っています。
(注:エラー処理は行いません。これはおもちゃのコードです。)