GNU/Linux >> Belajar Linux >  >> Linux

Penunjuk file C berubah setelah fork dan (gagal) exec

Penghargaan untuk Jonathan Leffler karena mengarahkan kami ke arah yang benar.

Meskipun program Anda tidak menghasilkan perilaku tak terduga yang sama untuk saya di CentOS 7 / GCC 4.8.5 / GLIBC 2.17, masuk akal jika Anda mengamati perilaku yang berbeda. Perilaku program Anda sebenarnya tidak terdefinisi menurut POSIX (yang Anda andalkan untuk fork ). Berikut beberapa kutipan dari bagian yang relevan (penekanan ditambahkan):

Deskripsi file terbuka dapat diakses melalui deskriptor file, yang dibuat menggunakan fungsi seperti open() atau pipe() , atau melalui aliran, yang dibuat menggunakan fungsi seperti fopen() atau popen() .Entah deskriptor file atau aliran disebut "pegangan" pada deskripsi openfile yang dirujuknya; deskripsi file terbuka mungkin memiliki beberapa pegangan.

[...]

Hasil pemanggilan fungsi yang melibatkan salah satu pegangan ("pegangan aktif") didefinisikan di tempat lain dalam volume POSIX.1-2017 ini, tetapi jika dua atau lebih pegangan digunakan, dan salah satunya adalah aliran, aplikasi harus memastikan bahwa mereka tindakan dikoordinasikan seperti yang dijelaskan di bawah ini. Jika ini tidak dilakukan, hasilnya tidak ditentukan .

[...]

Agar pegangan menjadi pegangan aktif, aplikasi harus memastikan bahwa tindakan di bawah ini dilakukan antara penggunaan terakhir pegangan (pegangan aktif saat ini) dan penggunaan pertama pegangan kedua (pegangan aktif mendatang). Pegangan kedua kemudian menjadi pegangan aktif. [...]

Pegangan tidak harus dalam proses yang sama agar aturan ini dapat diterapkan.

Perhatikan bahwa setelah fork() , dua pegangan ada di mana satu ada sebelumnya. Aplikasi harus memastikan bahwa, jika kedua pegangan dapat diakses, keduanya dalam keadaan di mana yang lain bisa menjadi pegangan aktif terlebih dahulu. [Jika tunduk pada kualifikasi sebelumnya,] aplikasi harus mempersiapkan fork() persis seolah-olah itu adalah perubahan pegangan aktif. (Jika satu-satunya tindakan yang dilakukan oleh salah satu proses adalah salah satu fungsi exec atau_exit() (bukan exit() ), pegangan tidak pernah diakses dalam proses itu. )

Untuk penanganan pertama, ketentuan pertama yang berlaku di bawah ini berlaku.[Daftar alternatif yang sangat panjang yang tidak berlaku untuk situasi OP ...]

  • Jika aliran terbuka dengan mode yang memungkinkan pembacaan dan deskripsi file terbuka yang mendasarinya merujuk ke perangkat yang mampu mencari, aplikasi harus melakukan fflush() , atau streaming akan ditutup.

Untuk pegangan kedua:

  • Jika ada pegangan aktif sebelumnya yang telah digunakan oleh fungsi yang secara eksplisit mengubah offset file, kecuali seperti yang diperlukan di atas untuk pegangan pertama, aplikasi harus melakukan lseek() atau fseek() (sesuai dengan jenis pegangan) ke lokasi yang sesuai.

Oleh karena itu, agar program OP dapat mengakses aliran yang sama pada induk dan anak, POSIX menuntut induk fflush() stdin sebelum forking, dan bahwa anak fseek() itu setelah memulai. Kemudian, setelah menunggu anak berhenti, induk harus fseek() aliran. Mengingat bahwa kita tahu exec anak akan gagal, bagaimanapun, persyaratan untuk semua pembilasan dan pencarian dapat dihindari dengan membuat anak menggunakan _exit() (yang tidak mengakses aliran), bukan exit() .

Mematuhi ketentuan POSIX menghasilkan hal berikut:

Ketika peraturan ini diikuti, terlepas dari urutan pegangan yang digunakan, implementasi harus memastikan bahwa aplikasi, bahkan yang terdiri dari beberapa proses, akan memberikan hasil yang benar:tidak ada data yang hilang atau digandakan saat menulis, dan semua data harus ditulis dalam urutan, kecuali sebagai diminta oleh pencari.

Namun, perlu dicatat bahwa

Ini adalah implementasi yang ditentukan apakah, dan dalam kondisi apa, semua input terlihat tepat satu kali.

Saya menghargai bahwa mungkin agak tidak memuaskan hanya mendengar bahwa ekspektasi Anda terhadap perilaku program tidak dibenarkan oleh standar yang relevan, tetapi hanya itu yang ada. Proses induk dan anak memang memiliki beberapa data bersama yang relevan dalam bentuk deskripsi file terbuka yang umum (yang terkait dengan pegangan terpisah), dan sepertinya itu adalah kendaraan untuk perilaku yang tidak diharapkan (dan tidak terdefinisi), tetapi tidak ada dasar untuk memprediksi perilaku spesifik yang Anda lihat, maupun perilaku berbeda yang saya lihat untuk program yang sama.


Linux
  1. Redirect Dan Output Pipa?

  2. Apa itu Exec 3?

  3. File Lisensi cPanel Tidak Valid Setelah Mengubah Kesalahan Nama Host

  1. Menginstal dan mengonfigurasi vsFTPD

  2. Perbedaan antara fork(), vfork(), exec() dan clone()

  3. Pipa, dup2 dan exec()

  1. Linux ext4 mengembalikan hak akses file dan direktori setelah backup/restore yang buruk

  2. vmlinuz dan initrd tidak ditemukan setelah membangun kernel?

  3. Mengubah atribut Tanggal Dibuat dan Terakhir Dimodifikasi file ke file lain