Di semua bahasa pemrograman (setidaknya yang saya gunakan), Anda harus membuka file sebelum dapat membaca atau menulis.
Tapi apa sebenarnya operasi terbuka ini?
Halaman manual untuk fungsi-fungsi tipikal sebenarnya tidak memberi tahu Anda apa pun selain 'membuka file untuk membaca / menulis':
http://www.cplusplus.com/reference/cstdio/fopen/
https://docs.python.org/3/library/functions.html#open
Jelas, melalui penggunaan fungsi Anda dapat mengatakan itu melibatkan pembuatan beberapa jenis objek yang memfasilitasi mengakses file.
Cara lain untuk meletakkan ini adalah, jika saya mengimplementasikan suatu open
fungsi, apa yang perlu dilakukan di Linux?
C
dan Linux; karena apa yang dilakukan Linux dan Windows berbeda. Kalau tidak, itu agak terlalu luas. Juga, setiap bahasa tingkat yang lebih tinggi pada akhirnya akan memanggil baik C API untuk sistem atau kompilasi ke C untuk mengeksekusi, sehingga meninggalkan pada tingkat "C" meletakkannya di Least Common Denominator.Jawaban:
Di hampir setiap bahasa tingkat tinggi, fungsi yang membuka file adalah pembungkus panggilan sistem kernel yang sesuai. Ini dapat melakukan hal-hal mewah lainnya juga, tetapi dalam sistem operasi kontemporer, membuka file harus selalu melalui kernel.
Inilah sebabnya argumen
fopen
fungsi perpustakaan, atau Pythonopen
sangat mirip dengan argumenopen(2)
panggilan sistem.Selain membuka file, fungsi-fungsi ini biasanya mengatur buffer yang akibatnya akan digunakan dengan operasi baca / tulis. Tujuan dari buffer ini adalah untuk memastikan bahwa setiap kali Anda ingin membaca N byte, panggilan pustaka yang sesuai akan mengembalikan N byte, terlepas dari apakah panggilan ke panggilan sistem yang mendasarinya kurang.
Dalam sistem operasi mirip Unix, panggilan yang berhasil untuk
open
mengembalikan "deskriptor file" yang hanya merupakan bilangan bulat dalam konteks proses pengguna. Deskriptor ini diteruskan ke panggilan apa pun yang berinteraksi dengan file yang dibuka, dan setelah memanggilnyaclose
, deskriptor menjadi tidak valid.Penting untuk dicatat bahwa panggilan untuk
open
bertindak seperti titik validasi di mana berbagai pemeriksaan dilakukan. Jika tidak semua kondisi terpenuhi, panggilan gagal dengan mengembalikan-1
bukan deskriptor, dan jenis kesalahan ditunjukkan dalamerrno
. Pemeriksaan penting adalah:Dalam konteks kernel, harus ada semacam pemetaan antara deskriptor file proses dan file yang dibuka secara fisik. Struktur data internal yang dipetakan ke deskriptor dapat berisi buffer lain yang berhubungan dengan perangkat berbasis blok, atau pointer internal yang menunjuk ke posisi baca / tulis saat ini.
sumber
man dup2
dan periksa kehalusan antara deskriptor file terbuka (yaitu FD yang kebetulan terbuka) dan deskripsi file terbuka (OFD).Saya sarankan Anda melihat panduan ini melalui versi sederhana dari
open()
panggilan sistem . Ini menggunakan potongan kode berikut, yang mewakili apa yang terjadi di balik layar ketika Anda membuka file.Secara singkat, inilah yang dilakukan oleh kode itu, baris demi baris:
The
filp_open
fungsi memiliki implementasiyang melakukan dua hal:
struct file
dengan informasi penting tentang inode dan kembalikan. Struct ini menjadi entri dalam daftar file yang terbuka yang saya sebutkan sebelumnya.Simpan ("instal") struct yang dikembalikan ke daftar proses file yang terbuka.
read()
,write()
, danclose()
. Masing-masing akan menyerahkan kontrol ke kernel, yang dapat menggunakan deskriptor file untuk mencari pointer file yang sesuai dalam daftar proses, dan menggunakan informasi dalam pointer file untuk benar-benar melakukan pembacaan, penulisan, atau penutupan.Jika Anda merasa ambisius, Anda dapat membandingkan contoh yang disederhanakan ini dengan implementasi
open()
pemanggilan sistem di kernel Linux, sebuah fungsi yang disebutdo_sys_open()
. Anda seharusnya tidak kesulitan menemukan kesamaan.Tentu saja, ini hanya "lapisan teratas" dari apa yang terjadi ketika Anda memanggil
open()
- atau lebih tepatnya, ini adalah kode kernel level tertinggi yang dipanggil dalam proses membuka file. Bahasa pemrograman tingkat tinggi mungkin menambahkan lapisan tambahan di atasnya. Ada banyak hal yang terjadi di level bawah. (Terima kasih kepada Ruslan dan pjc50 untuk penjelasannya.) Secara kasar, dari atas ke bawah:open_namei()
dandentry_open()
aktifkan kode sistem file, yang juga merupakan bagian dari kernel, untuk mengakses metadata dan konten untuk file dan direktori. The filesystem membaca byte mentah dari disk dan menafsirkan pola-pola byte sebagai pohon file dan direktori./dev/sda
dan sejenisnya.)Ini mungkin juga agak salah karena caching . :-P Serius, ada banyak detail yang saya tinggalkan - seseorang (bukan saya) bisa menulis banyak buku yang menggambarkan bagaimana seluruh proses ini bekerja. Tapi itu seharusnya memberi Anda ide.
sumber
Setiap sistem file atau sistem operasi yang ingin Anda bicarakan baik-baik saja oleh saya. Bagus!
Pada ZX Spectrum, menginisialisasi
LOAD
perintah akan membuat sistem menjadi loop ketat, membaca garis Audio In.Awal-data ditunjukkan oleh nada konstan, dan setelah itu rangkaian pulsa panjang / pendek mengikuti, di mana pulsa pendek untuk biner
0
dan yang lebih panjang untuk biner1
( https://en.wikipedia.org/ wiki / ZX_Spectrum_software ). Loop beban ketat mengumpulkan bit sampai mengisi satu byte (8 bit), menyimpan ini ke dalam memori, meningkatkan penunjuk memori, kemudian loop kembali untuk memindai bit lebih banyak.Biasanya, hal pertama yang dibaca loader adalah header format pendek, yang menunjukkan setidaknya jumlah byte yang diharapkan, dan mungkin informasi tambahan seperti nama file, jenis file, dan alamat pemuatan. Setelah membaca tajuk singkat ini, program dapat memutuskan apakah akan melanjutkan memuat sebagian besar data, atau keluar dari rutinitas memuat dan menampilkan pesan yang sesuai untuk pengguna.
Status End-of-file dapat dikenali dengan menerima byte sebanyak yang diharapkan (baik jumlah byte tetap, bawaan dalam perangkat lunak, atau nomor variabel seperti yang ditunjukkan dalam header). Kesalahan terjadi jika loop pemuatan tidak menerima pulsa dalam rentang frekuensi yang diharapkan untuk jangka waktu tertentu.
Sedikit latar belakang tentang jawaban ini
Prosedur ini menjelaskan memuat data dari kaset audio biasa - maka kebutuhan untuk memindai Audio Masuk (itu terhubung dengan plug standar ke perekam kaset). Sebuah
LOAD
perintah secara teknis sama denganopen
file - tapi itu secara fisik terikat benar-benar memuat file. Ini karena tape recorder tidak dikontrol oleh komputer, dan Anda tidak dapat (berhasil) membuka file tetapi tidak memuatnya."Loop ketat" disebutkan karena (1) CPU, Z80-A (jika memori berfungsi), benar-benar lambat: 3,5 MHz, dan (2) Spectrum tidak memiliki jam internal! Itu berarti bahwa ia harus secara akurat menghitung T-state (waktu instruksi) untuk setiap. tunggal. petunjuk. di dalam lingkaran itu, hanya untuk mempertahankan waktu bip yang akurat.
Untungnya, kecepatan CPU yang rendah memiliki keuntungan berbeda sehingga Anda dapat menghitung jumlah siklus pada selembar kertas, dan dengan demikian waktu dunia nyata yang akan mereka ambil.
sumber
Itu tergantung pada sistem operasi apa yang sebenarnya terjadi ketika Anda membuka file. Di bawah ini saya jelaskan apa yang terjadi di Linux karena memberi Anda gambaran tentang apa yang terjadi ketika Anda membuka file dan Anda dapat memeriksa kode sumber jika Anda tertarik untuk lebih detail. Saya tidak mencakup izin karena akan membuat jawaban ini terlalu lama.
Di Linux setiap file dikenali oleh struktur yang disebut inode. Setiap struktur memiliki nomor unik dan setiap file hanya mendapat satu nomor inode. Struktur ini menyimpan data meta untuk file, misalnya ukuran file, izin file, stempel waktu dan penunjuk ke blok disk, namun, bukan nama file itu sendiri. Setiap file (dan direktori) berisi entri nama file dan nomor inode untuk pencarian. Saat Anda membuka file, dengan asumsi Anda memiliki izin yang relevan, deskriptor file dibuat menggunakan nomor inode unik yang terkait dengan nama file. Karena banyak proses / aplikasi dapat menunjuk ke file yang sama, inode memiliki bidang tautan yang mempertahankan jumlah total tautan ke file tersebut. Jika suatu file ada dalam suatu direktori, jumlah tautannya adalah satu, jika memiliki tautan keras, jumlah tautannya akan menjadi dua dan jika suatu file dibuka oleh suatu proses, jumlah tautan akan bertambah 1.
sumber
Pembukuan, kebanyakan. Ini termasuk berbagai pemeriksaan seperti "Apakah file itu ada?" dan "Apakah saya memiliki izin untuk membuka file ini untuk menulis?".
Tapi itu semua hal-hal kernel - kecuali jika Anda menerapkan OS mainan Anda sendiri, tidak ada banyak untuk menyelidiki (jika Anda bersenang-senang - itu adalah pengalaman belajar yang hebat). Tentu saja, Anda masih harus mempelajari semua kode kesalahan yang mungkin Anda dapat terima saat membuka file, sehingga Anda dapat menanganinya dengan benar - tetapi itu biasanya abstraksi kecil yang bagus.
Bagian terpenting pada level kode adalah memberi Anda pegangan untuk membuka file, yang Anda gunakan untuk semua operasi lain yang Anda lakukan dengan file. Tidak bisakah Anda menggunakan nama file alih-alih pegangan sewenang-wenang ini? Ya, tentu saja - tetapi menggunakan pegangan memberi Anda beberapa keuntungan:
read
dari posisi terakhir di file Anda. Dengan menggunakan pegangan untuk mengidentifikasi "pembukaan" file tertentu, Anda dapat memiliki beberapa pegangan bersamaan untuk file yang sama, masing-masing membaca dari tempat mereka sendiri. Di satu sisi, pegangan bertindak sebagai jendela yang dapat dipindahkan ke dalam file (dan cara untuk mengeluarkan permintaan I / O asinkron, yang sangat berguna).Ada juga beberapa trik lain yang dapat Anda lakukan (misalnya, berbagi pegangan antara proses untuk memiliki saluran komunikasi tanpa menggunakan file fisik; pada sistem unix, file juga digunakan untuk perangkat dan berbagai saluran virtual lainnya, jadi ini tidak sepenuhnya diperlukan ), tetapi mereka tidak benar-benar terikat pada
open
operasi itu sendiri, jadi saya tidak akan menyelidiki itu.sumber
Pada intinya ketika membuka untuk membaca tidak ada hal-hal mewah yang sebenarnya perlu terjadi. Yang perlu dilakukan adalah memeriksa file yang ada dan aplikasi memiliki cukup hak istimewa untuk membacanya dan membuat pegangan di mana Anda dapat mengeluarkan perintah baca ke file.
Ada pada perintah-perintah itulah pembacaan aktual akan dikirim.
OS akan sering memulai membaca dengan memulai operasi membaca untuk mengisi buffer yang terkait dengan pegangan. Kemudian ketika Anda benar-benar membaca itu dapat mengembalikan isi buffer segera daripada harus menunggu di IO disk.
Untuk membuka file baru untuk menulis, OS perlu menambahkan entri di direktori untuk file baru (saat ini kosong). Dan lagi pegangan dibuat di mana Anda dapat mengeluarkan perintah tulis.
sumber
Pada dasarnya, panggilan untuk membuka perlu menemukan file, dan kemudian merekam apa pun yang diperlukan agar operasi I / O nanti dapat menemukannya lagi. Itu agak kabur, tetapi itu akan berlaku pada semua sistem operasi yang dapat saya pikirkan segera. Spesifikasinya bervariasi dari platform ke platform. Sudah banyak jawaban di sini yang berbicara tentang sistem operasi desktop modern. Saya telah melakukan sedikit pemrograman pada CP / M, jadi saya akan menawarkan pengetahuan saya tentang cara kerjanya pada CP / M (MS-DOS mungkin bekerja dengan cara yang sama, tetapi untuk alasan keamanan, biasanya tidak dilakukan seperti ini hari ini ).
Pada CP / M Anda memiliki sesuatu yang disebut FCB (seperti yang Anda sebutkan C, Anda bisa menyebutnya sebagai struct; ini benar-benar adalah area bersebelahan 35 byte dalam RAM yang berisi berbagai bidang). FCB memiliki bidang untuk menulis nama file dan integer (4-bit) yang mengidentifikasi drive disk. Kemudian, ketika Anda memanggil Open File kernel, Anda melewatkan sebuah pointer ke struct ini dengan menempatkannya di salah satu register CPU. Beberapa waktu kemudian, sistem operasi kembali dengan struct yang sedikit berubah. Apa pun I / O yang Anda lakukan untuk file ini, Anda meneruskan pointer ke struct ini ke panggilan sistem.
Apa yang dilakukan CP / M dengan FCB ini? Ini cadangan bidang tertentu untuk penggunaannya sendiri, dan menggunakannya untuk melacak file, jadi Anda sebaiknya tidak pernah menyentuhnya dari dalam program Anda. Operasi Open File mencari melalui tabel di awal disk untuk file dengan nama yang sama dengan apa yang ada di FCB (karakter wildcard '?' Cocok dengan karakter apa pun). Jika menemukan file, itu menyalin beberapa informasi ke FCB, termasuk lokasi fisik file pada disk, sehingga panggilan I / O berikutnya akhirnya memanggil BIOS yang dapat melewati lokasi ini ke driver disk. Pada level ini, spesifikasinya bervariasi.
sumber
Secara sederhana, ketika Anda membuka file, Anda sebenarnya meminta sistem operasi untuk memuat file yang diinginkan (menyalin isi file) dari penyimpanan sekunder untuk ram untuk diproses. Dan alasan di balik ini (Memuat file) adalah karena Anda tidak dapat memproses file langsung dari Hard-disk karena kecepatannya yang sangat lambat dibandingkan dengan Ram.
Perintah terbuka akan menghasilkan panggilan sistem yang pada gilirannya menyalin isi file dari penyimpanan sekunder (Hard-disk) ke penyimpanan Utama (Ram).
Dan kami 'Tutup' file karena konten yang dimodifikasi dari file harus tercermin ke file asli yang ada di hard-disk. :)
Semoga itu bisa membantu.
sumber