Contoh reproduksi C POSIX runnable minimal
Saya merekomendasikan untuk memahami API yang mendasarinya untuk melihat dengan lebih baik apa yang sedang terjadi.
sleep.c
#define _XOPEN_SOURCE 700
#include <unistd.h>
int main(void) {
sleep(10000);
}
busy.c
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(void) {
int ret = open("sleep.out", O_WRONLY|O_TRUNC);
assert(errno == ETXTBSY);
perror("");
assert(ret == -1);
}
Kompilasi dan jalankan:
gcc -std=c99 -o sleep.out ./sleep.c
gcc -std=c99 -o busy.out ./busy.c
./sleep.out &
./busy.out
busy.outmelewati pernyataan, dan perrorkeluaran:
Text file busy
jadi kami menyimpulkan bahwa pesan tersebut di-hardcode dalam glibc itu sendiri.
Kalau tidak:
echo asdf > sleep.out
membuat output Bash:
-bash: sleep.out: Text file busy
Untuk aplikasi yang lebih kompleks, Anda juga dapat mengamatinya dengan strace:
strace ./busy.out
yang mengandung:
openat(AT_FDCWD, "sleep.out", O_WRONLY) = -1 ETXTBSY (Text file busy)
Diuji pada Ubuntu 18.04, kernel Linux 4.15.0.
Kesalahan tidak terjadi jika Anda unlinkterlebih dahulu
notbusy.c:
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void) {
assert(unlink("sleep.out") == 0);
assert(open("sleep.out", O_WRONLY|O_CREAT) != -1);
}
Kemudian kompilasi dan jalankan secara analog dengan yang di atas, dan mereka menegaskan lulus.
Ini menjelaskan mengapa ini bekerja untuk program tertentu tetapi tidak untuk yang lain. Misal jika Anda melakukannya:
gcc -std=c99 -o sleep.out ./sleep.c
./sleep.out &
gcc -std=c99 -o sleep.out ./sleep.c
itu tidak menghasilkan kesalahan, meskipun gccpanggilan kedua menulis sleep.out.
Quick stracemenunjukkan bahwa GCC memutuskan tautan terlebih dahulu sebelum menulis:
strace -f gcc -std=c99 -o sleep.out ./sleep.c |& grep sleep.out
mengandung:
[pid 3992] unlink("sleep.out") = 0
[pid 3992] openat(AT_FDCWD, "sleep.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
Alasannya tidak gagal adalah bahwa ketika Anda unlinkdan menulis ulang file, itu menciptakan inode baru, dan membuat inode menggantung sementara untuk menjalankan file yang dapat dieksekusi.
Tetapi jika Anda hanya writetanpa unlink, maka itu mencoba untuk menulis ke inode yang dilindungi yang sama dengan menjalankan executable.
POSIX 7 open()
http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html
[ETXTBSY]
File tersebut adalah file prosedur murni (teks bersama) yang sedang dieksekusi dan oflag adalah O_WRONLY atau O_RDWR.
man 2 terbuka
ETXTBSY
pathname mengacu pada gambar yang dapat dieksekusi yang sedang dieksekusi dan akses tulis diminta.
Text file busykesalahan dalam spesifik tentang mencoba untuk memodifikasi executable ketika sedang mengeksekusi. "Teks" di sini merujuk pada fakta bahwa file yang sedang dimodifikasi adalah segmen teks untuk program yang sedang berjalan. Ini adalah kasus yang sangat istimewa, dan bukan yang umum yang tampaknya disarankan oleh jawaban Anda. Meski begitu, jawaban Anda tidak sepenuhnya salah.