Jika saya ingin tailfilefile 25 GB, apakah tailperintah membaca seluruh file?
Karena file mungkin tersebar di disk saya bayangkan itu harus, tetapi saya tidak mengerti internal seperti itu dengan baik.
Jika saya ingin tailfilefile 25 GB, apakah tailperintah membaca seluruh file?
Karena file mungkin tersebar di disk saya bayangkan itu harus, tetapi saya tidak mengerti internal seperti itu dengan baik.
Jawaban:
Tidak, tailtidak membaca keseluruhan file, ia mencari sampai akhir lalu membaca blok ke belakang sampai jumlah garis yang diharapkan telah tercapai, kemudian menampilkan garis dalam arah yang benar sampai akhir file, dan mungkin tetap memantau file jika -fopsi digunakan.
Namun perhatikan bahwa tailtidak ada pilihan selain membaca seluruh data jika memberikan input yang tidak dapat dicari, misalnya saat membaca dari sebuah pipa.
Demikian pula, ketika diminta untuk mencari baris mulai dari awal file, dengan menggunakan tail -n +linenumbersintaks atau tail +linenumberopsi non-standar ketika didukung, tailjelas membaca seluruh file (kecuali terganggu).
tail +nakan membaca seluruh file - pertama untuk menemukan jumlah baris baru yang diinginkan, kemudian untuk mengeluarkan sisanya.
tailimplementasi melakukannya atau melakukannya dengan benar. Misalnya busybox 1.21.1 tailrusak dalam hal itu. Perhatikan juga bahwa perilaku bervariasi ketika menggunakan tailstdin dan di mana stdin adalah file biasa dan posisi awal dalam file tidak di awal ketika taildipanggil (seperti di { cat > /dev/null; tail; } < file)
Anda bisa melihat cara tailkerjanya sendiri. Yang Anda bisa untuk salah satu file saya readdilakukan tiga kali dan total sekitar 10K byte dibaca:
strace 2>&1 tail ./huge-file >/dev/null | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY) = 3
lseek(3, 0, SEEK_CUR) = 0
lseek(3, 0, SEEK_END) = 80552644
lseek(3, 80551936, SEEK_SET) = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET) = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3) = 0
stracemenunjukkan apa yang taildilakukan panggilan sistem saat dijalankan. Beberapa pengantar tentang panggilan sistem dapat Anda baca di sini en.wikipedia.org/wiki/System_call . Secara singkat - buka - membuka file dan mengembalikan pegangan (3 dalam contoh ini), lseekposisi di mana Anda akan membaca dan readhanya membaca dan karena Anda dapat melihatnya mengembalikan berapa byte yang dibaca,
Karena file mungkin tersebar di disk saya bayangkan itu harus [membaca file secara berurutan], tapi saya tidak mengerti internal seperti itu dengan baik.
Seperti yang Anda ketahui, tailhanya mencari ke akhir file (dengan panggilan sistem lseek), dan bekerja mundur. Tetapi dalam komentar yang dikutip di atas, Anda bertanya-tanya "bagaimana ekor tahu di mana pada disk untuk menemukan akhir file?"
Jawabannya sederhana: Ekor tidak tahu. Proses tingkat pengguna melihat file sebagai aliran kontinu, sehingga yang tailbisa diketahui adalah offset dari awal file. Tetapi dalam sistem file, "inode" file (entri direktori) dikaitkan dengan daftar angka yang menunjukkan lokasi fisik blok data file. Ketika Anda membaca dari file, kernel / driver perangkat mencari tahu bagian mana yang Anda butuhkan, menentukan lokasinya pada disk dan mengambilnya untuk Anda.
Itulah jenis sistem operasi yang kami miliki: jadi Anda tidak perlu khawatir tentang di mana blok file Anda tersebar.
Jika headatau tail tampaknya membaca seluruh file, kemungkinan alasannya adalah bahwa file tersebut berisi sedikit atau tidak ada karakter baris baru . Saya tersandung ini beberapa bulan yang lalu dengan gumpalan JSON yang sangat besar (gigabytes) yang telah diserialkan tanpa spasi apa pun, bahkan dalam string.
Jika Anda memiliki GNU head / tail yang dapat Anda gunakan -c Nuntuk mencetak byte pertama / terakhir alih-alih garis , tapi sayangnya ini bukan fitur POSIX.
Seperti yang Anda lihat di baris kode sumber 525, Anda dapat melihat komentar untuk implementasi.
/* Print the last N_LINES lines from the end of file FD.
Go backward through the file, reading 'BUFSIZ' bytes at a time (except
probably the first), until we hit the start of the file or have
read NUMBER newlines.
START_POS is the starting position of the read pointer for the file
associated with FD (may be nonzero).
END_POS is the file offset of EOF (one larger than offset of last byte).
Return true if successful. */