Dua nomor file descriptor dapat mengubah file offset yang sama. Di Linux, hal ini terjadi ketika kedua descriptor merujuk pada satu open file description, seperti setelah dup() atau pada descriptor yang diwariskan setelah fork().

Perbedaan ini penting karena file descriptor adalah integer yang terlihat oleh process, sedangkan open file description adalah objek kernel yang menyimpan state untuk satu instance file yang dibuka. Menganggap kedua lapisan ini sama dapat menyebabkan interferensi offset, perubahan status flag yang melintasi batas descriptor, dan perilaku mengejutkan setelah process dibuat.

Descriptor menunjuk ke open file description

Pemanggilan open() yang berhasil membuat open file description baru dan mengembalikan file descriptor yang merujuk kepadanya. Open file description menyimpan state termasuk current file offset dan file status flag.

Membuka pathname yang sama dua kali biasanya membuat dua open file description terpisah:

int a = open("events.log", O_RDONLY);
int b = open("events.log", O_RDONLY);

Kedua descriptor dapat merujuk ke underlying file yang sama sambil tetap memiliki offset independen. Pembacaan melalui a memajukan offset yang terkait dengan open file description milik a; operasi itu tidak memajukan state independen di balik b.

dup() memiliki semantics berbeda:

int a = open("events.log", O_RDONLY);
int b = dup(a);

Di sini, a dan b adalah nomor descriptor berbeda yang merujuk ke open file description yang sama. Objek bersama tersebut, bukan integer descriptor, yang memiliki current offset.

Perubahan offset melintasi descriptor hasil duplikasi

Misalkan a dan b berbagi satu open file description. Seek melalui salah satu descriptor mengubah offset yang diamati melalui keduanya:

lseek(a, 4096, SEEK_SET);
read(b, buf, sizeof buf);

read() dimulai dari offset 4096, tunduk pada semantics normal dari underlying file dan call tersebut. Pembacaan yang berhasil kemudian memajukan shared offset.

Ini bukan aliasing pada lapisan pathname. Rename atau unlink pathname tidak memisahkan open file description. Descriptor tetap merujuk pada file object yang sudah terbuka selama referensi tersebut masih valid.

Properti shared-offset yang sama juga berlaku pada sequential read. Dua execution context yang memakai satu open file description bersama tidak memiliki cursor privat hanya karena nomor descriptor mereka berbeda.

fork mempertahankan objek kernel yang sama

Setelah fork(), child menerima salinan file descriptor milik parent. Descriptor yang diwariskan tersebut merujuk ke open file description yang sama dengan pasangan descriptor di sisi parent.

Jika parent membuka regular file lalu melakukan fork, pembacaan di child dapat memajukan offset yang kemudian dilihat parent. Batas process membuat descriptor table terpisah, tetapi tidak membuat open file description baru untuk entry yang diwariskan.

Process yang membutuhkan file position independen memerlukan open file description terpisah. Membuka ulang file adalah salah satu cara umum untuk mendapatkan pemisahan itu. Menduplikasi descriptor yang sudah ada bukan caranya.

File status flag juga milik shared description

Offset hanyalah sebagian dari shared state. File status flag seperti O_APPEND dan O_NONBLOCK terkait dengan open file description.

Karena itu, mengubah flag semacam ini dengan fcntl() melalui satu duplicated descriptor memengaruhi operasi melalui descriptor lain yang terhubung ke open file description yang sama. Ini berbeda dari file descriptor flag seperti FD_CLOEXEC, yang melekat pada entry descriptor table individual.

Perbedaannya membentuk boundary penting:

  • file status flag menggambarkan open file description yang dibagikan;
  • file descriptor flag menggambarkan satu descriptor entry.

Kode yang menduplikasi descriptor untuk mengisolasi perubahan status flag tidak menciptakan isolasi tersebut.

close menghapus referensi, bukan selalu open state

Menutup salah satu duplicated descriptor menghapus referensi milik descriptor tersebut. Open file description tetap hidup selama descriptor lain masih merujuk kepadanya.

Aturan lifetime ini muncul pada beberapa interface Linux. Objek yang diregistrasikan ke event facility atau state yang terkait dengan open-file-description dapat tetap hidup setelah satu descriptor ditutup jika duplicate lain masih mempertahankan referensi ke underlying open file description.

Nomor descriptor sendiri juga dapat digunakan kembali setelah close(). Descriptor berikutnya dengan nilai integer yang sama bukan bukti bahwa ia merujuk ke open file description yang sama.

Identitas descriptor dan identitas open state adalah hal berbeda

Systems code sering melacak descriptor sebagai integer karena system call menerima integer tersebut. Representasi ini tidak cukup ketika correctness bergantung pada shared open state.

Dua integer berbeda dapat berbagi satu offset dan satu set status flag. Nilai integer yang sama pada waktu berbeda dapat merujuk ke open file description yang sama sekali tidak terkait. Dua descriptor untuk inode yang sama pun dapat memiliki open file description independen.

Karena itu, boundary yang tahan lama bukan kesamaan descriptor atau pathname. Boundary-nya adalah open file description kernel yang direferensikan oleh setiap descriptor. Operasi yang menduplikasi atau mewariskan descriptor mempertahankan objek bersama tersebut; open() baru membuat objek baru.