Pada sistem Unix, mengapa kita harus secara eksplisit `membuka ()` dan `menutup ()` file untuk dapat `membaca ()` atau `menulis ()` mereka?


50

Mengapa open()dan close()ada dalam desain sistem file Unix?

Tidak bisakah OS hanya mendeteksi pertama kali read()atau write()dipanggil dan melakukan apa pun yang open()biasanya akan dilakukan?


22
Perlu dicatat bahwa model ini bukan bagian dari sistem file melainkan dari Unix API . Filesystem hanya berkaitan dengan di mana pada disk byte pergi dan di mana meletakkan nama file, dll. Sangat mungkin untuk memiliki model alternatif yang Anda jelaskan di atas sistem file Unix seperti UFS atau ext4, itu akan sampai ke tingkat kernel untuk menerjemahkan panggilan-panggilan tersebut ke dalam pembaruan yang tepat untuk sistem file (seperti sekarang)
marcelm

18
Seperti yang diungkapkan, saya pikir ini lebih tentang mengapa open()ada. "Tidak bisakah OS hanya mendeteksi saat pertama kali membaca () atau menulis () dan melakukan apa pun yang terbuka () biasanya lakukan?" Apakah ada saran yang sesuai untuk kapan penutupan akan terjadi?
Joshua Taylor

7
Bagaimana Anda tahu read()atau write()file mana yang akan diakses? Agaknya dengan melewati jalan setapak. Bagaimana jika jalur file berubah saat Anda mengaksesnya (antara dua read()atau write()panggilan)?
user253751

2
Anda juga biasanya tidak melakukan kontrol akses read()dan write(), hanya pada open().
Pavel Šimerda

6
@ Johnny: Anda mungkin lupa betapa terbatasnya perangkat keras pada masa itu. PDP-7 di mana Unix pertama kali diimplementasikan memiliki (per Google) maksimum 64K RAM dan 0,333 MHz clock - lebih sedikit daripada mikrokontroler sederhana hari ini. Melakukan pengumpulan sampah seperti itu, atau menggunakan kode sistem untuk memantau akses file, akan membuat sistem berlutut.
jamesqf

Jawaban:


60

Dennis Ritchie menyebutkan dalam «Evolusi Sistem Berbagi Waktu Unix» itu opendan closebersama dengan itu read, writedan creathadir dalam sistem sejak awal.

Saya kira sistem tanpa opendan closetidak akan terbayangkan, namun saya percaya itu akan menyulitkan desain. Anda biasanya ingin membuat beberapa panggilan baca dan tulis, bukan hanya satu, dan itu mungkin terutama benar pada komputer-komputer lama dengan RAM yang sangat terbatas yang berasal dari UNIX. Memiliki pegangan yang mempertahankan posisi file Anda saat ini menyederhanakan ini. Jika readatauwriteadalah untuk mengembalikan pegangan, mereka harus mengembalikan sepasang - pegangan dan status pengembalian mereka sendiri. Bagian pegangan dari pasangan tidak akan berguna untuk semua panggilan lain, yang akan membuat pengaturan itu canggung. Membiarkan status kursor ke kernel memungkinkannya untuk meningkatkan efisiensi tidak hanya dengan buffering. Ada juga beberapa biaya yang terkait dengan pencarian jalur - memiliki pegangan memungkinkan Anda membayarnya sekali saja. Selain itu, beberapa file dalam pandangan dunia UNIX bahkan tidak memiliki jalur sistem file (atau tidak - sekarang mereka lakukan dengan hal-hal seperti /proc/self/fd).


7
Biaya pencarian jalur dan pemeriksaan izin dll. Sangat signifikan. Jika Anda ingin membuat sistem tanpa open/ close, Anda pasti akan menerapkan hal-hal seperti /dev/stdoutmengizinkan perpipaan.
Peter Cordes

5
Saya pikir aspek lain untuk ini adalah bahwa Anda dapat menyimpan pegangan itu ke file yang sama saat menggunakan banyak pembacaan ketika Anda membiarkan file tetap terbuka. Jika tidak, Anda dapat memiliki kasus di mana proses lain memutuskan tautan dan membuat ulang file dengan nama yang sama, dan membaca file dalam potongan dapat secara efektif benar-benar tidak koheren. (Beberapa di antaranya mungkin bergantung pada sistem file juga.)
Bruno

2
Saya merancang satu tanpa tutup (); Anda melewatkan nomor inode dan mengimbangi untuk membaca () dan menulis (). Saya tidak dapat melakukannya tanpa open () dengan sangat mudah karena di situlah resolusi nama tinggal.
Joshua

3
@ Yosua: Sistem seperti itu memiliki semantik yang berbeda secara mendasar karena deskriptor file unix tidak merujuk ke file (inode) tetapi untuk membuka deskripsi file , yang mungkin ada banyak untuk file yang diberikan (inode).
R ..

@ Yosua, Anda baru saja mengganti nama open()menjadi get_inode()dan membuat keseluruhan sistem lebih kaku (tidak mungkin membaca / menulis file yang sama di beberapa posisi secara bersamaan).
vonbrand

53

Maka semua panggilan readdan writeharus melewati informasi ini pada setiap operasi:

  • nama file
  • izin file
  • apakah pemanggil menambahkan atau membuat
  • apakah pemanggil selesai bekerja dengan file (untuk membuang buffer yang tidak digunakan dan memastikan buffer penulisan benar-benar selesai menulis)

Apakah Anda mempertimbangkan independen panggilan open , read, writedan closemenjadi lebih sederhana daripada tujuan tunggal I / O pesan didasarkan pada filosofi desain Anda. Pengembang Unix memilih untuk menggunakan operasi dan program sederhana yang dapat digabungkan dalam banyak cara, daripada operasi tunggal (atau program) yang melakukan segalanya.


Penelepon juga dalam banyak kasus harus menentukan offset yang diinginkan dalam suatu file. Ada beberapa situasi (misalnya protokol UDP yang memungkinkan akses ke data) di mana setiap permintaan secara independen mengidentifikasi file dan offset dapat membantu karena menghilangkan kebutuhan server untuk mempertahankan keadaan, tetapi secara umum lebih mudah untuk memiliki server melacak posisi file. Lebih lanjut, seperti disebutkan di tempat lain, kode yang akan menulis file sering perlu menguncinya sebelumnya dan menguncinya sesudahnya; menyisir operasi tersebut dengan buka / tutup sangat mudah.
supercat

5
"File" mungkin tidak memiliki nama atau izin di tempat pertama; readdan writetidak terbatas pada file yang hidup pada sistem file, dan itu adalah keputusan desain mendasar di Unix, seperti dijelaskan pjc50.
reinierpost

1
Juga di mana dalam file untuk membaca / menulis itu - awal, akhir, atau posisi arbitrer (biasanya setelah akhir membaca / menulis terakhir) - kernel melacak ini untuk Anda (dengan mode untuk arahkan semua tulis ke akhir file, atau file dibuka dengan posisi di awal dan maju dengan masing-masing baca / tulis dan dapat dipindahkan dengan lseek)
Random832

51

Konsep pegangan file penting karena pilihan desain UNIX bahwa "semuanya adalah file", termasuk hal-hal yang bukan bagian dari sistem file. Seperti tape drive, keyboard dan layar (atau teletype!), Pembaca kartu / tape, koneksi serial, koneksi jaringan, dan (penemuan UNIX kunci) koneksi langsung ke program lain yang disebut "pipa".

Jika Anda melihat banyak utilitas standar UNIX sederhana seperti grep, terutama dalam versi aslinya, Anda akan melihat bahwa mereka tidak memasukkan panggilan ke open()dan close()tetapi hanya readdan write. Pegangan file diatur di luar program oleh shell dan diteruskan ketika dimulai. Jadi program tidak perlu peduli apakah itu menulis ke file atau ke program lain.

Serta open, cara lain untuk mendapatkan deskriptor file yang socket, listen, pipe, dup, dan sangat mekanisme Heath Robinson untuk mengirimkan file deskriptor lebih pipa: https://stackoverflow.com/questions/28003921/sending-file-descriptor-by-linux -stopkontak

Sunting: beberapa catatan kuliah yang menjelaskan lapisan tipuan dan bagaimana ini memungkinkan O_APPEND bekerja dengan masuk akal. Perhatikan bahwa menyimpan data inode dalam memori menjamin sistem tidak perlu pergi dan mengambilnya lagi untuk operasi penulisan berikutnya.


1
Juga creat, dan listentidak membuat fd, tetapi ketika (dan jika) permintaan masuk saat mendengarkan acceptmembuat dan mengembalikan fd untuk soket (terhubung) yang baru.
dave_thompson_085

18
Ini adalah jawaban yang benar. Rangkaian operasi (kecil) yang terkenal pada deskriptor file adalah API pemersatu untuk semua jenis sumber daya yang menghasilkan atau menggunakan data. Konsep ini sangat sukses. Sebuah string dapat memiliki sintaks yang mendefinisikan jenis sumber daya bersama dengan lokasi sebenarnya (URL siapa?), Tetapi untuk menyalin string sekitar yang menempati beberapa persen dari RAM yang tersedia (apa itu pada PDP 7? 16 kB?) Tampaknya berlebihan .
Peter - Reinstate Monica

Mungkin itu akan terjadi, jika panggilan tingkat rendah dan shell dikembangkan pada saat yang sama. Tetapi pipediperkenalkan beberapa tahun setelah pengembangan di Unix dimulai.
Thomas Dickey

1
@Thomas Dickey: Yang hanya menunjukkan seberapa bagus desain aslinya, karena memungkinkan perpanjangan sederhana untuk pipa & c :-)
jamesqf

Tetapi mengikuti garis argumen itu, jawaban ini tidak memberikan apa pun yang baru.
Thomas Dickey

10

Jawabannya adalah tidak, karena buka () dan tutup () buat dan hancurkan pegangan masing-masing. Ada waktu (yah, sepanjang waktu, sungguh) di mana Anda mungkin ingin menjamin bahwa Anda adalah satu-satunya penelepon dengan tingkat akses tertentu, karena penelepon lain (misalnya) menulis ke file yang Anda parsing secara tidak terduga dapat meninggalkan aplikasi dalam keadaan yang tidak diketahui atau mengarah ke livelock atau jalan buntu, misalnya lemma Filsuf Makan.

Bahkan tanpa pertimbangan itu, ada implikasi kinerja yang harus dipertimbangkan; close () memungkinkan sistem file untuk (jika sesuai atau jika Anda memanggilnya) membilas buffer yang Anda tempati, sebuah operasi yang mahal. Beberapa pengeditan berurutan ke aliran dalam memori jauh lebih efisien daripada beberapa siklus baca-tulis-ubah yang pada dasarnya tidak terkait dengan sistem file yang, sepengetahuan Anda, ada setengah dunia yang tersebar di pusat data dengan penyimpanan massal laten tinggi. Bahkan dengan penyimpanan lokal, memori biasanya banyak urutan besarnya lebih cepat daripada penyimpanan massal.


7

Open () menawarkan cara untuk mengunci file saat sedang digunakan. Jika file dibuka secara otomatis, baca / tulis dan kemudian ditutup lagi oleh OS tidak akan ada yang menghentikan aplikasi lain mengubah file-file tersebut di antara operasi.

Meskipun ini dapat dikelola (banyak sistem mendukung akses file non-eksklusif) untuk kesederhanaan sebagian besar aplikasi menganggap bahwa file yang mereka buka tidak berubah.


5

Karena jalur file mungkin bergerak sementara Anda menganggap itu akan tetap sama.


4

Membaca dan menulis ke sistem file mungkin melibatkan berbagai skema penyangga, pemeliharaan sistem operasi, manajemen disk tingkat rendah, dan sejumlah tindakan potensial lainnya. Jadi tindakan open()dan close()berfungsi sebagai set-up untuk jenis kegiatan di bawah tenda. Implementasi yang berbeda dari sistem file dapat sangat disesuaikan sesuai kebutuhan dan tetap transparan untuk program pemanggilan.

Jika OS tidak memiliki buka / tutup, maka dengan readatau write, tindakan file tersebut masih harus melakukan inisialisasi, pembilasan buffer / manajemen, dll setiap waktu. Itu banyak overhead untuk memaksakan membaca dan menulis berulang.


Tidak lupa bahwa open () dan close () juga menyimpan posisi dalam file (untuk selanjutnya baca atau tulis selanjutnya). Jadi pada akhir atau read () dan write () akan membutuhkan struct untuk menangani semua parameter, atau perlu argumen untuk setiap parameter. Membuat struktur adalah setara (situs programmer) dengan open, jadi jika OS juga tahu tentang open, kita hanya memiliki lebih banyak keuntungan.
Giacomo Catenazzi

1

Mantra Unix adalah "menawarkan satu cara melakukan sesuatu", yang berarti "memfaktorkan" ke dalam bagian-bagian (dapat digunakan kembali) untuk digabungkan sesuka hati. Yaitu, dalam hal ini pisahkan pembuatan dan penghancuran file menangani dari penggunaannya. Manfaat penting datang kemudian, dengan koneksi pipa dan jaringan (mereka juga dimanipulasi melalui pegangan file, tetapi mereka diciptakan dengan cara lain). Mampu mengirim file menangani sekitar (misalnya menyerahkannya ke proses anak sebagai "file terbuka" yang bertahan exec(2), dan bahkan untuk proses yang tidak terkait melalui pipa) hanya mungkin dengan cara ini. Terutama jika Anda ingin menawarkan akses terkontrol ke file yang dilindungi. Jadi Anda bisa misalnya membuka/etc/passwd untuk menulis, dan meneruskannya ke proses anak yang tidak diizinkan untuk membuka file itu untuk ditulis (ya, saya tahu ini adalah contoh yang konyol, silakan mengedit dengan sesuatu yang lebih realistis).

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.