InggrisPerancisSpanyol

Ad


favorit OnWorks

explain_lca2010 - Daring di Awan

Jalankan explain_lca2010 di penyedia hosting gratis OnWorks melalui Ubuntu Online, Fedora Online, emulator online Windows, atau emulator online MAC OS

Ini adalah perintah explain_lca2010 yang dapat dijalankan di penyedia hosting gratis OnWorks menggunakan salah satu dari beberapa workstation online gratis kami seperti Ubuntu Online, Fedora Online, emulator online Windows atau emulator online MAC OS

PROGRAM:

NAMA


explain_lca2010 - Tidak ada media yang ditemukan: ketika saatnya berhenti mencoba membaca strerror(3)
pikiran.

MOTIVASI


Ide untuk libexplain muncul di benak saya di awal 1980-an. Setiap kali panggilan sistem
mengembalikan kesalahan, kernel tahu persis apa yang salah... dan mengompresnya menjadi
kurang dari 8 bit salah. Ruang pengguna memiliki akses ke data yang sama dengan kernel, itu
seharusnya memungkinkan bagi ruang pengguna untuk mengetahui dengan tepat apa yang terjadi sehingga memicu kesalahan
kembali, dan gunakan ini untuk menulis pesan kesalahan yang baik.

Mungkinkah sesederhana itu?

error pesan as kemahiran
Pesan kesalahan yang baik seringkali merupakan tugas "satu persen" yang dijatuhkan saat dijadwalkan
tekanan meremas proyek Anda. Namun, pesan kesalahan yang baik dapat membuat kesalahan besar,
peningkatan yang tidak proporsional untuk pengalaman pengguna, ketika pengguna mengembara ke dalam ketakutan
wilayah yang tidak diketahui biasanya tidak ditemui. Ini bukan tugas yang mudah.

Sebagai programmer larva, penulis tidak melihat masalah dengan kesalahan (sepenuhnya akurat)
pesan seperti ini:
pengecualian mengambang (inti dibuang)
sampai interpretasi alternatif non-programmer ditunjukkan. Tapi itu bukan
satu-satunya hal yang salah dengan pesan kesalahan Unix. Seberapa sering Anda melihat pesan kesalahan seperti:
$ ./bodoh
tidak bisa membuka file
$
Ada dua opsi untuk pengembang saat ini:

1.
anda dapat menjalankan debugger, seperti gdb(1), atau

2.
Kamu dapat memakai jejak(1) atau tiang penopang(1) untuk melihat ke dalam.

· Ingatlah bahwa pengguna Anda mungkin tidak memiliki akses ke alat ini, apalagi kemampuannya
untuk menggunakannya. (Sudah sangat lama sejak Unix pemula berarti "hanya menulis" satu
driver perangkat".)

Dalam contoh ini, bagaimanapun, menggunakan jejak(1) mengungkapkan
$ jejak -e jejak = buka ./bodoh
open("some/file", O_RDONLY) = -1 ENOENT (Tidak ada file atau direktori seperti itu)
tidak bisa membuka file
$
Ini jauh lebih banyak informasi daripada yang disediakan oleh pesan kesalahan. Biasanya,
kode sumber bodoh terlihat seperti ini
int fd = buka("sesuatu", O_RDONLY);
jika (fd < 0)
{
fprintf(stderr, "file tidak bisa dibuka\n");
keluar(1);
}
Pengguna tidak diberitahu yang file, dan juga gagal memberi tahu pengguna yang kesalahan. Apakah file itu?
di sana sekalipun? Apakah ada masalah izin? Itu memberi tahu Anda bahwa itu mencoba membuka
file, tapi itu mungkin secara tidak sengaja.

Ambil tongkat petunjuk Anda dan kalahkan programmer larva dengan itu. Ceritakan padanya tentang kesalahan(3).
Lain kali Anda menggunakan program, Anda melihat pesan kesalahan yang berbeda:
$ ./bodoh
buka: Tidak ada file atau direktori seperti itu
$
Kemajuan, tetapi tidak seperti yang kami harapkan. Bagaimana pengguna dapat memperbaiki masalah jika pesan kesalahan
tidak memberitahunya apa masalahnya? Melihat sumbernya, kita melihat
int fd = buka("sesuatu", O_RDONLY);
jika (fd < 0)
{
perror("buka");
keluar(1);
}
Saatnya untuk lari lagi dengan tongkat petunjuk. Kali ini, pesan kesalahan mengambil satu langkah
maju dan mundur satu langkah:
$ ./bodoh
sesuatu: Tidak ada berkas atau direktori seperti itu
$
Sekarang kami tahu file yang coba dibuka, tetapi tidak lagi diberitahu bahwa itu adalah Buka(2)
yang gagal. Dalam hal ini mungkin tidak signifikan, tetapi bisa signifikan untuk
panggilan sistem lainnya. Bisa saja creat(2) sebagai gantinya, sebuah operasi yang menyiratkan bahwa
izin yang berbeda diperlukan.
const char *nama file = "sesuatu";
int fd = buka(nama file, O_RDONLY);
jika (fd < 0)
{
kesalahan(nama file);
keluar(1);
}
Sayangnya, contoh kode di atas juga tipikal untuk pemrogram non-larva. Waktu
untuk memberi tahu pelajar padawan kami tentang strerror(3) panggilan sistem.
$ ./bodoh
Buka sesuatu: Tidak ada berkas atau direktori seperti itu
$
Ini memaksimalkan informasi yang dapat disajikan kepada pengguna. Kodenya terlihat seperti
ini:
const char *nama file = "sesuatu";
int fd = buka(nama file, O_RDONLY);
jika (fd < 0)
{
fprintf(stderr, "buka %s: %s\n", nama file, strerror(errno));
keluar(1);
}
Sekarang kita memiliki panggilan sistem, nama file, dan string kesalahan. Ini berisi semua
informasi itu jejak(1) dicetak. Itu bagus.

Atau itu?

keterbatasan of kesalahan dan strerror
Masalah yang penulis lihat, pada tahun 1980-an, adalah bahwa pesan kesalahan tidak lengkap.
Apakah "tidak ada file atau direktori seperti itu" mengacu pada "beberapa”, atau ke “hal”berkas di
"beberapa" direktori?

Sekilas melihat halaman manual untuk strerror(3) menceritakan:
strerror - mengembalikan string yang menjelaskan nomor kesalahan
Perhatikan baik-baik: ini menggambarkan kesalahan jumlah, bukan kesalahannya.

Di sisi lain, kernel tahu apa kesalahannya. Ada titik tertentu di
kode kernel, disebabkan oleh kondisi tertentu, di mana kode kernel bercabang dan berkata “tidak”.
Bisakah program ruang pengguna mengetahui kondisi spesifik dan menulis kesalahan yang lebih baik?
pesan?

Namun, masalahnya semakin dalam. Bagaimana jika masalah terjadi selama Baca baca(2) sistem
panggilan, bukan Buka(2) panggilan? Sederhana untuk pesan kesalahan yang terkait dengan
Buka(2) untuk memasukkan nama file, itu ada di sana. Tetapi untuk dapat memasukkan nama file
dalam kesalahan yang terkait dengan Baca baca(2) panggilan sistem, Anda harus memberikan nama file semua
jalan ke bawah tumpukan panggilan, serta deskriptor file.

Dan inilah bagian yang perlu diperhatikan: kernel sudah tahu nama file apa file tersebut
deskriptor dikaitkan dengan. Mengapa seorang programmer harus melewatkan semua data yang berlebihan?
cara menurunkan tumpukan panggilan hanya untuk memperbaiki pesan kesalahan yang mungkin tidak pernah dikeluarkan? Di
kenyataannya, banyak programmer tidak peduli, dan pesan kesalahan yang dihasilkan lebih buruk untuk
.

Tapi itu tahun 1980-an, pada PDP11, dengan sumber daya terbatas dan tidak ada perpustakaan bersama. Kembali
maka, tidak ada rasa Unix yang disertakan / proc bahkan dalam bentuk yang belum sempurna, dan lsof(1) program
sudah lebih dari satu dekade. Jadi ide itu disimpan sebagai tidak praktis.

Tingkat Angka tak terbatas Bantuan
Bayangkan bahwa Anda adalah dukungan tingkat tak terhingga. Deskripsi pekerjaan Anda mengatakan bahwa Anda tidak pernah
pernah harus berbicara dengan pengguna. Lalu, mengapa masih ada aliran konstan orang yang menginginkan
Anda, guru Unix lokal, untuk menguraikan lagi pesan kesalahan?

Anehnya, 25 tahun kemudian, meskipun sistem perizinannya sederhana, diimplementasikan dengan lengkap
konsistensi, sebagian besar pengguna Unix masih tidak tahu bagaimana memecahkan kode "Tidak ada file atau direktori",
atau pesan kesalahan samar lainnya yang mereka lihat setiap hari. Atau, setidaknya, samar untuk
Mereka.

Bukankah lebih baik jika dukungan teknis tingkat pertama tidak memerlukan pesan kesalahan yang diuraikan?
Bukankah lebih baik memiliki pesan kesalahan yang dapat dipahami pengguna tanpa menelepon?
dukungan teknologi?

Hari ini / proc di Linux lebih dari mampu memberikan informasi yang diperlukan untuk memecahkan kode
sebagian besar pesan kesalahan, dan mengarahkan pengguna ke penyebab terdekat dari
masalah. Pada sistem dengan keterbatasan / proc implementasi, lsof(1) perintah dapat mengisi
banyak celah.

Pada tahun 2008, aliran permintaan terjemahan terlalu sering terjadi pada penulis. Dulu
waktu untuk memeriksa kembali ide berusia 25 tahun itu, dan libexplain adalah hasilnya.

MENGGUNAKAN THE PERPUSTAKAAN


Antarmuka ke perpustakaan mencoba untuk konsisten, jika memungkinkan. Mari kita mulai dengan
contoh menggunakan strerror(3):
jika (ganti nama (jalur_lama, jalur_baru) < 0)
{
fprintf(stderr, "ganti nama %s %s: %s\n", jalur_lama, jalur_baru,
strerror(errno));
keluar(1);
}
Ide di balik libexplain adalah untuk menyediakan strerror(3) setara untuk setiap panggilan sistem,
disesuaikan secara khusus untuk panggilan sistem itu, sehingga dapat memberikan kesalahan yang lebih detail
pesan, berisi banyak informasi yang Anda lihat di bawah judul "ERRORS" bagian
2 dan 3 pria halaman, dilengkapi dengan informasi tentang kondisi aktual, argumen aktual
nilai, dan batas sistem.

Grafik Sederhana Kasus
Grafik strerror(3) penggantian:
jika (ganti nama (jalur_lama, jalur_baru) < 0)
{
fprintf(stderr, "%s\n", jelaskan_rename(jalur_lama, jalur_baru));
keluar(1);
}

Grafik salah Kasus
Dimungkinkan juga untuk melewati eksplisit salah(3) nilai, jika Anda harus terlebih dahulu melakukan beberapa
pemrosesan yang akan mengganggu salah, seperti pemulihan kesalahan:
if (ganti nama (jalur_lama, jalur_baru <0))
{
int lama_errno = salah;
...kode bahwa mengganggu salah...
fprintf(stderr, "%s\n", jelaskan_errno_rename(lama_errno,
jalur_lama, jalur_baru));
keluar(1);
}

Grafik Multi-utas kasus
Beberapa aplikasi multi-threaded, dan karenanya tidak dapat berbagi internal libexplain
penyangga. Anda dapat menyediakan buffer Anda sendiri menggunakan
jika (batalkan tautan (nama jalur))
{
pesan karakter[3000];
jelaskan_pesan_batalkan tautan(pesan, ukuran dari(pesan), nama jalur);
kesalahan_dialog(pesan);
kembali -1;
}
Dan untuk kelengkapan, keduanya salah(3) dan thread-safe:
ssize_t nbytes = baca(fd, data, sizeof(data));
jika (nbyte < 0)
{
pesan karakter[3000];
int lama_errno = salah;
...kesalahan pemulihan...
jelaskan_pesan_errno_baca(pesan, ukuran dari(pesan),
old_errno, fd, data, ukuran(data));
kesalahan_dialog(pesan);
kembali -1;
}

Ini adalah pengganti untuk strerror_r(3), pada sistem yang memilikinya.

Antarmuka Gula
Satu set fungsi ditambahkan sebagai fungsi kenyamanan, untuk merayu programmer untuk menggunakan
libexplain library, ternyata menjadi fungsi libexplain yang paling umum digunakan penulis di
program baris perintah:
int fd = jelaskan_buat_atau_mati(nama file, 0666);
Fungsi ini mencoba membuat file baru. Jika tidak bisa, itu mencetak pesan kesalahan dan
keluar dengan EXIT_FAILURE. Jika tidak ada kesalahan, itu mengembalikan deskriptor file baru.

Fungsi terkait:
int fd = explain_creat_on_error(nama file, 0666);
akan mencetak pesan kesalahan saat gagal, tetapi juga mengembalikan hasil kesalahan asli, dan
salah(3) tidak diganggu, juga.

Semua itu lain sistem panggilan
Secara umum, setiap panggilan sistem memiliki file include-nya sendiri
#termasuknama.h>
yang mendefinisikan prototipe fungsi untuk enam fungsi:

· menjelaskan_nama,

· jelaskan_errno_nama,

· jelaskan_pesan_nama,

· jelaskan_pesan_errno_nama,

· menjelaskan_nama_atau_mati dan

· menjelaskan_nama_pada_kesalahan.

Setiap prototipe fungsi memiliki dokumentasi Doxygen, dan dokumentasi ini is tidak dilucuti
ketika file include diinstal.

Grafik menunggu(2) panggilan sistem (dan teman-teman) memiliki beberapa varian tambahan yang juga mengartikan kegagalan
menjadi status keluar yang bukan EXIT_SUCCESS. Ini berlaku untuk sistem(3) dan tutup(3) sebagai
baik.

Cakupan mencakup 221 panggilan sistem dan 547 permintaan ioctl. Masih banyak lagi sistemnya
panggilan belum diterapkan. Panggilan sistem yang tidak pernah kembali, seperti keluar(2), tidak hadir
di perpustakaan, dan tidak akan pernah ada. Itu eksekutif keluarga panggilan sistem adalah didukung, karena
mereka kembali ketika ada kesalahan.

Kucing
Seperti inilah tampilan program "kucing" hipotetis, dengan pelaporan kesalahan penuh,
menggunakan libexplain.
#termasuk
#include
#termasuk
Ada satu termasuk untuk libexplain, ditambah tersangka biasa. (Jika Anda ingin mengurangi
beban praprosesor, Anda dapat menggunakan yang spesifiknama.h> termasuk.)
kekosongan statis
proses(FILE *fp)
{
untuk (;;)
{
penyangga karakter[4096];
size_t n = jelaskan_fread_or_die(buffer, 1, sizeof(buffer), fp);
jika (!n)
break;
jelaskan_fwrite_or_die(penyangga, 1, n, stdout);
}
}
Grafik proses fungsi menyalin aliran file ke output standar. Jika terjadi kesalahan
baik untuk membaca atau menulis, dilaporkan (dan nama path akan dimasukkan dalam
error) dan perintah keluar dengan EXIT_FAILURE. Kami bahkan tidak khawatir tentang pelacakan
nama path, atau meneruskannya ke tumpukan panggilan.
int
utama(int argc, char **argv)
{
untuk (;;)
{
int c = getopt(argc, argv, "o:");
jika (c == EOF)
break;
beralih (c)
{
kasus 'o':
jelaskan_freopen_or_die(optarg, "w", stdout);
break;
Bagian yang menyenangkan dari kode ini adalah libexplain dapat melaporkan kesalahan termasuk itu nama jalur bahkan
jika Anda tidak secara eksplisit membuka kembali stdout seperti yang dilakukan di sini. Kami bahkan tidak khawatir tentang
melacak nama file.
default:
fprintf(stderr, "Penggunaan: %ss [ -o ] ...\n",
argv[0]);
kembali EXIT_FAILURE;
}
}
jika (optind == argc)
proses(stdin);
lain
{
sementara (optind < argc)
{
FILE *fp = explain_fopen_or_die(argv[optind]++, "r");
proses (fp);
jelaskan_fclose_or_die(fp);
}
}
Output standar akan ditutup secara implisit, tetapi sudah terlambat untuk laporan kesalahan
dikeluarkan, jadi kami melakukannya di sini, untuk berjaga-jaga jika I/O yang di-buffer belum menulis apa pun, dan
ada kesalahan ENOSPC atau sesuatu.
jelaskan_fflush_or_die(stdout);
kembali EXIT_SUCCESS;
}
Itu saja. Pelaporan kesalahan penuh, kode yang jelas.

Rusty's Skala of Antarmuka Kebaikan
Bagi Anda yang tidak akrab dengannya, Rusty Russel's "Bagaimana Saya Membuat Ini Sulit Disalahgunakan?"
halaman harus dibaca untuk desainer API.
http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html

10. Sekarang mustahil untuk mendapatkan salah.

Tujuan perlu ditetapkan tinggi, ambisius tinggi, jangan sampai Anda mencapainya dan berpikir Anda melakukannya
selesai ketika Anda tidak.

Pustaka libexplain mendeteksi pointer palsu dan banyak parameter panggilan sistem palsu lainnya,
dan umumnya mencoba menghindari segfault bahkan dalam situasi yang paling sulit sekalipun.

Pustaka libexplain dirancang agar aman untuk utas. Lebih banyak penggunaan di dunia nyata kemungkinan akan terjadi
mengungkapkan tempat ini dapat ditingkatkan.

Masalah terbesar adalah dengan nama fungsi yang sebenarnya itu sendiri. Karena C tidak memiliki
name-spaces, perpustakaan libexplain selalu menggunakan awalan nama explain_. Ini adalah
cara tradisional untuk menciptakan ruang nama semu untuk menghindari konflik simbol.
Namun, itu menghasilkan beberapa nama yang terdengar tidak wajar.

9. Grafik penyusun or linker biasa membiarkan kamu mendapatkan it salah.

Kesalahan umum adalah menggunakan explain_open di mana explain_open_or_die dimaksudkan.
Untungnya, kompiler akan sering mengeluarkan kesalahan tipe pada saat ini (misalnya tidak dapat menetapkan
const char * rvalue ke int lvalue).

8. Grafik penyusun akan memperingatkan if kamu mendapatkan it salah.

Jika explain_rename digunakan saat explain_rename_or_die dimaksudkan, ini dapat menyebabkan
masalah. GCC memiliki atribut fungsi warn_unused_result yang berguna, dan libexplain
perpustakaan melampirkannya ke semua penjelasan_nama fungsi panggilan untuk menghasilkan peringatan ketika Anda
membuat kesalahan ini. Gabungkan ini dengan gcc -Kesalahan untuk mempromosikan ini ke tingkat 9 kebaikan.

7. Grafik Jelas menggunakan is (mungkin) itu benar satu.

Nama fungsi telah dipilih untuk menyampaikan artinya, tetapi ini tidak selalu
berhasil. Sambil menjelaskan_nama_atau_mati dan jelaskan_nama_on_error cukup deskriptif,
varian thread safe yang jarang digunakan lebih sulit untuk didekode. Prototipe fungsi membantu
compiler menuju pemahaman, dan komentar Doxygen di file header membantu pengguna
menuju pemahaman.

6. Grafik nama mengatakan kamu bagaimana untuk menggunakan .

Sangat penting untuk membaca menjelaskan_nama_atau_mati sebagai “jelaskan (nama atau mati)".
Menggunakan awalan ruang nama-jelaskan yang konsisten memiliki beberapa efek samping yang tidak menguntungkan dalam
departemen kejelasan, juga.

Urutan kata dalam nama juga menunjukkan urutan argumen. Argumen
daftar selalu akhir dengan argumen yang sama seperti yang diteruskan ke panggilan sistem; semua of mereka. Jika
_errno_ muncul di nama, argumennya selalu mendahului argumen panggilan sistem. Jika
_message_ muncul di nama, dua argumennya selalu didahulukan.

5. Do it benar or it akan istirahat at waktu berjalan.

Pustaka libexplain mendeteksi pointer palsu dan banyak parameter panggilan sistem palsu lainnya,
dan umumnya mencoba menghindari segfault bahkan dalam situasi yang paling sulit sekalipun. Itu harus
tidak pernah rusak saat runtime, tetapi lebih banyak penggunaan di dunia nyata tidak diragukan lagi akan meningkatkan ini.

Beberapa pesan kesalahan ditujukan untuk pengembang dan pengelola daripada pengguna akhir, karena ini
dapat membantu dengan resolusi bug. Tidak begitu banyak "istirahat saat runtime" sebagai "informatif di
runtime” (setelah panggilan sistem barfs).

4. Mengikuti umum konvensi dan kamu akan mendapatkan it kanan.

Karena C tidak memiliki name-spaces, library libexplain selalu menggunakan nama explain_
awalan. Ini adalah cara tradisional untuk membuat ruang nama-semu untuk menghindari
konflik simbol.

Argumen tambahan dari semua panggilan libexplain identik dengan panggilan sistem mereka
sedang menggambarkan. Hal ini dimaksudkan untuk memberikan konvensi yang konsisten yang sama dengan
sistem memanggil diri mereka sendiri.

3. Baca itu dokumentasi dan kamu akan mendapatkan it kanan.

Perpustakaan libexplain bertujuan untuk memiliki dokumentasi Doxygen lengkap untuk setiap
panggilan API publik (dan juga secara internal).

PESAN KONTEN


Mengerjakan libexplain sedikit mirip dengan melihat bagian bawah mobil Anda saat menyala
kerekan di mekanik. Ada beberapa barang jelek di bawah sana, ditambah lumpur dan kotoran, dan
pengguna jarang melihatnya. Pesan kesalahan yang baik harus informatif, bahkan untuk pengguna yang
telah cukup beruntung untuk tidak terlalu sering melihat ke bawah, dan juga
informatif untuk mekanik mendengarkan deskripsi pengguna melalui telepon. Ini
tidak ada tugas yang mudah.

Meninjau kembali contoh pertama kami, kode akan seperti ini jika menggunakan libexplain:
int fd = explain_open_or_die("sesuatu/sesuatu", O_RDONLY, 0);
akan gagal dengan pesan kesalahan seperti ini
open(pathname = "some/file", flags = O_RDONLY) gagal, Tidak ada file atau direktori seperti itu
(2, ENOENT) karena tidak ada direktori "beberapa" di direktori saat ini
Ini dipecah menjadi tiga bagian
panggilan sistem gagal, sistem bermasalah karena
penjelasan

Sebelum Karena
Hal ini dimungkinkan untuk melihat bagian dari pesan sebelum "karena" sebagai terlalu teknis untuk non-
pengguna teknis, sebagian besar sebagai hasil dari pencetakan yang akurat dari panggilan sistem itu sendiri di
awal pesan kesalahan. Dan sepertinya jejak(1) keluaran, untuk bonus geek
poin.
open(pathname = "some/file", flags = O_RDONLY) gagal, Tidak ada file atau direktori seperti itu
(2, ENON)
Bagian dari pesan kesalahan ini penting bagi pengembang saat dia menulis kode,
dan sama pentingnya dengan pengelola yang harus membaca laporan bug dan memperbaiki bug di
kode. Ia mengatakan dengan tepat apa yang gagal.

Jika teks ini tidak disajikan kepada pengguna, maka pengguna tidak dapat menyalin dan menempelkannya ke dalam
laporan bug, dan jika tidak ada dalam laporan bug, pengelola tidak dapat mengetahui apa yang sebenarnya terjadi
salah.

Staf teknologi sering akan menggunakan jejak(1) atau tiang penopang(1) untuk mendapatkan informasi yang tepat ini, tetapi
jalan ini tidak terbuka saat membaca laporan bug. Sistem reporter bug jauh
jauh, dan, sekarang, dalam keadaan yang jauh berbeda. Dengan demikian, informasi ini perlu di
laporan bug, yang berarti harus ada dalam pesan kesalahan.

Representasi panggilan sistem juga memberikan konteks ke seluruh pesan. Jika perlu
muncul, argumen panggilan sistem yang menyinggung dapat disebut dengan nama dalam penjelasan
setelah “karena”. Selain itu, semua string dikutip sepenuhnya dan keluar dari string C, jadi
baris baru yang disematkan dan karakter non-cetak tidak akan menyebabkan terminal pengguna pergi
kusut.

Grafik sistem bermasalah adalah apa yang keluar dari strerror(2), ditambah simbol kesalahan. Tidak sabar dan
sysadmin ahli dapat berhenti membaca pada titik ini, tetapi pengalaman penulis hingga saat ini adalah
bahwa membaca lebih lanjut bermanfaat. (Jika tidak bermanfaat, itu mungkin area
libexplain yang dapat ditingkatkan. Kontribusi kode dipersilakan, tentu saja.)

Setelah Karena
Ini adalah bagian dari pesan kesalahan yang ditujukan untuk pengguna non-teknis. Itu terlihat di luar
argumen panggilan sistem sederhana, dan mencari sesuatu yang lebih spesifik.
tidak ada direktori "beberapa" di direktori saat ini
Bagian ini mencoba menjelaskan penyebab proksimal kesalahan dalam bahasa sederhana, dan itu
di sinilah internasionalisasi menjadi penting.

Secara umum, kebijakannya adalah memasukkan informasi sebanyak mungkin, sehingga pengguna
tidak perlu mencarinya (dan tidak mengabaikannya dari laporan bug).

Internasionalisasi
Sebagian besar pesan kesalahan di perpustakaan libexplain telah diinternasionalkan. Di sana
belum ada pelokalan, jadi jika Anda menginginkan penjelasan dalam bahasa ibu Anda,
silakan berkontribusi.

Kualifikasi "paling banyak", di atas, berkaitan dengan fakta bahwa bukti konsep
implementasi tidak termasuk dukungan internasionalisasi. Basis kode sedang
direvisi secara progresif, biasanya sebagai hasil dari pemfaktoran ulang pesan sehingga setiap kesalahan
string pesan muncul dalam kode tepat satu kali.

Ketentuan telah dibuat untuk bahasa yang perlu mengumpulkan bagian-bagian dari
panggilan sistem gagal, sistem bermasalah karena penjelasan
dalam urutan yang berbeda untuk tata bahasa yang benar dalam pesan kesalahan lokal.

Post mortem
Ada kalanya sebuah program belum menggunakan libexplain, dan Anda tidak dapat menggunakan jejak(1)
salah satu. ada menjelaskan(1) perintah yang disertakan dengan libexplain yang dapat digunakan untuk
menguraikan pesan kesalahan, jika keadaan sistem yang mendasarinya tidak terlalu banyak berubah.
$ menjelaskan mengubah nama foo /tmp/bar/baz -e ENON
rename(oldpath = "foo", newpath = "/tmp/bar/baz") gagal, Tidak ada file atau direktori seperti itu
(2, ENOENT) karena tidak ada direktori "bar" di jalur baru "/ Tmp" direktori
$
Perhatikan bagaimana ambiguitas jalur diselesaikan dengan menggunakan nama argumen panggilan sistem. Dari
tentu saja, Anda harus mengetahui kesalahan dan panggilan sistem untuk menjelaskan(1) menjadi berguna. sebagai
selain itu, ini adalah salah satu cara yang digunakan oleh rangkaian pengujian otomatis libexplain untuk memverifikasi itu
libexplain berfungsi.

filsafat
"Ceritakan semuanya, termasuk hal-hal yang saya tidak tahu harus dicari."

Pustaka diimplementasikan sedemikian rupa sehingga ketika ditautkan secara statis, hanya kode yang Anda
benar-benar digunakan akan ditautkan. Ini dicapai dengan memiliki satu fungsi per file sumber,
bila memungkinkan.

Jika memungkinkan untuk memberikan lebih banyak informasi, libexplain akan melakukannya. Semakin sedikit pengguna
harus melacak sendiri, semakin baik. Ini berarti bahwa UID disertai dengan:
nama pengguna, GID disertai dengan nama grup, PID disertai dengan proses
nama, deskriptor file, dan aliran disertai dengan nama path, dll.

Saat menyelesaikan jalur, jika komponen jalur tidak ada, libexplain akan mencari yang serupa
nama, untuk menyarankan alternatif untuk kesalahan ketik.

Pustaka libexplain mencoba menggunakan tumpukan sesedikit mungkin, dan biasanya tidak ada. Ini
untuk menghindari gangguan status proses, sejauh mungkin, meskipun kadang-kadang
tak terhindarkan.

Pustaka libexplain mencoba untuk mengamankan utas, dengan menghindari variabel global, menjaga
negara pada stack sebanyak mungkin. Ada satu buffer pesan umum, dan
fungsi yang menggunakannya didokumentasikan sebagai tidak aman untuk thread.

Pustaka libexplain tidak mengganggu penangan sinyal proses. Ini membuat
menentukan apakah pointer akan melakukan segfault suatu tantangan, tetapi bukan tidak mungkin.

Ketika informasi tersedia melalui panggilan sistem serta tersedia melalui a / proc
entri, panggilan sistem lebih disukai. Ini untuk menghindari mengganggu status proses.
Ada juga saat-saat ketika tidak ada deskriptor file yang tersedia.

Pustaka libexplain dikompilasi dengan dukungan file besar. Tidak ada besar/kecil
skizofrenia. Di mana ini memengaruhi tipe argumen di API, dan kesalahan akan dikeluarkan
jika definisi file besar yang diperlukan tidak ada.

FIXME: Pekerjaan diperlukan untuk memastikan bahwa kuota sistem file ditangani dalam kode. Ini
berlaku untuk beberapa getrlimit(2) batas, juga.

Ada kasus ketika jalur kerabat tidak informatif. Misalnya: daemon sistem,
server dan proses latar belakang. Dalam kasus ini, jalur absolut digunakan dalam kesalahan
penjelasan.

PATH RESOLUSI


Versi singkat: lihat jalan_resolusi(7).

Versi panjang: Sebagian besar pengguna belum pernah mendengarnya jalan_resolusi(7), dan banyak pengguna tingkat lanjut
belum pernah membacanya. Ini adalah versi beranotasi:

Langkah 1: Start of itu resolusi proses
Jika nama path dimulai dengan karakter slash (“/”), direktori pencarian awal adalah
direktori root dari proses pemanggilan.

Jika nama path tidak dimulai dengan karakter slash(“/”), pencarian awal
direktori proses resolusi adalah direktori kerja proses saat ini.

Langkah 2: Berjalan sepanjang itu path
Atur direktori pencarian saat ini ke direktori pencarian awal. Sekarang, untuk setiap non-
komponen terakhir dari nama path, di mana komponen adalah substring yang dibatasi oleh garis miring (“/”)
karakter, komponen ini dicari di direktori pencarian saat ini.

Jika proses tidak memiliki izin pencarian pada direktori pencarian saat ini, EACCES
kesalahan dikembalikan ("Izin ditolak").
open(pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) gagal,
Izin ditolak (13, EACCES) karena prosesnya tidak memiliki izin pencarian
ke direktori pathname "/home/archives/.ssh", prosesnya efektif GID 1000
"pmiller" tidak cocok dengan pemilik direktori 1001 "arsip" jadi pemiliknya
mode izin "rwx" diabaikan, mode izin lainnya adalah "---", dan
proses tidak diistimewakan (tidak memiliki kemampuan DAC_READ_SEARCH)

Jika komponen tidak ditemukan, kesalahan ENOENT dikembalikan ("Tidak ada file atau direktori seperti itu").
unlink(pathname = "/home/microsoft/rubbish") gagal, Tidak ada file atau direktori seperti itu (2,
ENOENT) karena tidak ada direktori "microsoft" di nama path "/ Home" direktori

Ada juga beberapa dukungan untuk pengguna ketika mereka salah mengetik nama path, memberikan saran ketika
ENOENT dikembalikan:
open(pathname = "/user/include/fcntl.h", flags = O_RDONLY) gagal, Tidak ada file atau
direktori (2, ENOENT) karena tidak ada direktori "pengguna" di nama path "/"
direktori, maksud Anda direktori "usr" bukan?

Jika komponen ditemukan, tetapi bukan direktori atau tautan simbolik, sebuah ENOTDIR
kesalahan dikembalikan ("Bukan direktori").
open(pathname = "/home/pmiller/.netrc/lca", flags = O_RDONLY) gagal, Bukan
direktori (20, ENOTDIR) karena file biasa ".netrc" di nama path
Direktori "/ home/pmiler" digunakan sebagai direktori ketika tidak

Jika komponen ditemukan dan merupakan direktori, kami mengatur direktori pencarian saat ini ke itu
direktori, dan pergi ke komponen berikutnya.

Jika komponen ditemukan dan merupakan tautan simbolik (symlink), pertama-tama kita selesaikan simbolik ini
link (dengan direktori pencarian saat ini sebagai direktori pencarian awal). Atas kesalahan, itu
kesalahan dikembalikan. Jika hasilnya bukan direktori, kesalahan ENOTDIR dikembalikan.
unlink(pathname = "/tmp/dangling/rubbish") gagal, Tidak ada file atau direktori seperti itu (2,
ENOENT) karena tautan simbolik "menggantung" di nama path "/ Tmp" direktori
mengacu pada "tempat" yang tidak ada
Jika resolusi symlink berhasil dan mengembalikan direktori, kami mengatur arus
cari direktori ke direktori itu, dan pergi ke komponen berikutnya. Perhatikan bahwa
proses resolusi di sini melibatkan rekursi. Untuk melindungi kernel dari tumpukan
overflow, dan juga untuk melindungi dari penolakan layanan, ada batasan maksimum
kedalaman rekursi, dan jumlah maksimum tautan simbolik yang diikuti. Kesalahan ELOOP adalah
dikembalikan ketika maksimum terlampaui ("Terlalu banyak level tautan simbolik").
open(pathname = "/tmp/dangling", flags = O_RDONLY) gagal, Terlalu banyak level
tautan simbolik (40, ELOOP) karena loop tautan simbolik ditemukan di
pathname, mulai dari "/tmp/menggantung"
Dimungkinkan juga untuk mendapatkan kesalahan ELOOP atau EMLINK jika ada terlalu banyak symlink, tetapi tidak
lingkaran terdeteksi.
open(pathname = "/tmp/rabbit-hole", flags = O_RDONLY) gagal, Terlalu banyak level
tautan simbolik (40, ELOOP) karena terlalu banyak tautan simbolik ditemukan di
nama jalur (8)
Perhatikan bagaimana batas sebenarnya juga dicetak.

Langkah 3: Menemukan itu terakhir masuk
Pencarian komponen terakhir dari nama path berjalan seperti yang lainnya
komponen, seperti yang dijelaskan pada langkah sebelumnya, dengan dua perbedaan:

(i) Komponen terakhir tidak perlu berupa direktori (setidaknya sejauh resolusi jalur
proses yang bersangkutan. Mungkin harus berupa direktori, atau non-direktori, karena
persyaratan panggilan sistem tertentu).

(Ii)
Ini belum tentu merupakan kesalahan jika komponen akhir tidak ditemukan; mungkin kita hanya
menciptakannya. Rincian tentang perawatan entri terakhir dijelaskan dalam
halaman manual dari panggilan sistem tertentu.

(aku aku aku)
Mungkin juga ada masalah dengan komponen terakhir jika itu adalah tautan simbolik
dan tidak harus diikuti. Misalnya, menggunakan Buka(2) Bendera O_NOFOLLOW:
open(pathname = "a-symlink", flags = O_RDONLY | O_NOFOLLOW) gagal, Terlalu banyak level
tautan simbolik (ELOOP) karena O_NOFOLLOW telah ditentukan tetapi nama path mengacu pada a
tautan simbolis

(iv)
Adalah umum bagi pengguna untuk membuat kesalahan saat mengetik nama path. Perpustakaan libexplain
mencoba membuat saran ketika ENOENT dikembalikan, misalnya:
open(pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) gagal, Tidak ada file atau
direktori (2, ENOENT) karena tidak ada file biasa "filecontrl.h" di nama path
"/ usr / include" direktori, apakah yang Anda maksud adalah file biasa "fcntl.h"?

(v) Mungkin juga bahwa komponen akhir diperlukan untuk menjadi sesuatu selain a
berkas biasa:
readlink(pathname = "hanya-a-file", data = 0x7F930A50, data_size = 4097) gagal,
Argumen tidak valid (22, EINVAL) karena nama path adalah file biasa, bukan tautan simbolik

(vi)
FIXME: penanganan bit "t".

Batas
Ada sejumlah batasan sehubungan dengan nama path dan nama file.

Batas panjang nama jalur
Ada panjang maksimum untuk nama path. Jika nama path (atau perantara
pathname diperoleh saat menyelesaikan tautan simbolik) terlalu panjang, sebuah ENAMETOOLONG
kesalahan dikembalikan ("Nama file terlalu panjang"). Perhatikan bagaimana batas sistem disertakan
dalam pesan kesalahan.
buka(nama jalur = "sangat lama", flags = O_RDONLY) gagal, Nama file terlalu panjang (36,
ENAMETOOLONG) karena nama jalur melebihi panjang jalur maksimum sistem (4096)

Batas panjang nama file
Beberapa varian Unix memiliki batasan jumlah byte di setiap komponen jalur.
Beberapa dari mereka menangani ini secara diam-diam, dan beberapa memberikan ENAMETOOLONG; penjelasan lib
perpustakaan menggunakan pathconf(3) _PC_NO_TRUNC untuk membedakan yang mana. Jika kesalahan ini terjadi,
perpustakaan libexplain akan menyatakan batas dalam pesan kesalahan, batasnya adalah
diperoleh dari pathconf(3) _PC_NAME_MAX. Perhatikan bagaimana batas sistem disertakan
dalam pesan kesalahan.
buka(nama jalur = "system7/hanya-memiliki-14-karakter", flags = O_RDONLY) gagal, File
nama terlalu panjang (36, ENAMETOOLONG) karena komponen "hanya memiliki 14 karakter" adalah
lebih lama dari batas sistem (14)

Nama jalur kosong
Di Unix asli, nama path kosong merujuk ke direktori saat ini.
Saat ini POSIX menetapkan bahwa nama path kosong tidak boleh diselesaikan dengan sukses.
open(pathname = "", flags = O_RDONLY) gagal, Tidak ada file atau direktori seperti itu (2,
ENOENT) karena POSIX memutuskan bahwa nama path kosong tidak boleh diselesaikan
berhasil

izin
Bit izin file terdiri dari tiga kelompok tiga bit. Kelompok pertama
tiga digunakan ketika ID pengguna yang efektif dari proses panggilan sama dengan ID pemilik dari
mengajukan. Grup kedua dari tiga digunakan ketika ID grup file sama dengan
ID grup efektif dari proses panggilan, atau merupakan salah satu ID grup tambahan dari
proses panggilan. Ketika tidak ada yang berlaku, grup ketiga digunakan.
buka(nama jalur = "/ etc / passwd", flags = O_WRONLY) gagal, Izin ditolak (13,
EACCES) karena prosesnya tidak memiliki izin menulis ke "passwd" reguler
file dalam nama path "/ Etc" direktori, proses efektif UID 1000 "pmiler"
tidak cocok dengan pemilik file biasa 0 "root" jadi mode izin pemilik "rw-"
diabaikan, mode izin lainnya adalah "r--", dan prosesnya tidak diistimewakan
(tidak memiliki kemampuan DAC_OVERRIDE)
Beberapa ruang yang cukup besar diberikan untuk penjelasan ini, karena sebagian besar pengguna tidak tahu bahwa ini
adalah bagaimana sistem perizinan bekerja. Khususnya: pemilik, grup, dan lainnya
izin eksklusif, mereka tidak "ATAU" bersama-sama.

ANEH DAN MENARIK SISTEM PANGGILAN


Proses penulisan penangan kesalahan khusus untuk setiap panggilan sistem sering mengungkapkan
kebiasaan menarik dan kondisi batas, atau tidak jelas salah(3) nilai.

ENOMEDIUM, Tidak medium ditemukan
Tindakan menyalin CD adalah sumber judul makalah ini.
$ dd jika=/dev/cdrom dari=fubar.iso
dd: membuka "/ dev/cdrom": Tidak ada media yang ditemukan
$
Penulis bertanya-tanya mengapa komputernya mengatakan kepadanya bahwa tidak ada yang namanya paranormal
sedang. Terlepas dari kenyataan bahwa sejumlah besar penutur asli bahasa Inggris tidak
bahkan menyadari bahwa "media" adalah jamak, apalagi "medium" adalah tunggalnya, string
dikembalikan oleh strerror(3) untuk ENOMEDIUM sangat singkat sehingga hampir sepenuhnya bebas dari
konten.

Ketika Buka(2) mengembalikan ENOMEDIUM alangkah baiknya jika perpustakaan libexplain dapat berkembang
sedikit tentang ini, berdasarkan jenis drive itu. Sebagai contoh:
... karena tidak ada disk di floppy drive
... karena tidak ada disk dalam drive CD-ROM
... karena tidak ada tape di tape drive
... karena tidak ada memory stick di card reader

Dan terjadilah...
open(pathname = "/dev/cdrom", flags = O_RDONLY) gagal, Tidak ada media yang ditemukan (123,
ENOMEDIUM) karena tampaknya tidak ada disk dalam drive CD-ROM
Triknya, yang sebelumnya tidak disadari oleh penulis, adalah membuka perangkat menggunakan
Bendera O_NONBLOCK, yang memungkinkan Anda membuka drive tanpa media di dalamnya. Anda kemudian
masalah perangkat tertentu ioctl(2) permintaan sampai Anda mengetahui apa itu. (Bukan
yakin apakah ini POSIX, tetapi tampaknya juga berfungsi seperti itu di BSD dan Solaris, menurut
itu Wodim(1) sumber.)

Perhatikan juga perbedaan penggunaan "disk" dan "disk" dalam konteksnya. Standar CD berasal
di Prancis, tetapi yang lainnya memiliki "k".

KESALAHAN, Buruk alamat
Setiap panggilan sistem yang menggunakan argumen pointer dapat mengembalikan EFAULT. Perpustakaan libexplain
dapat mengetahui argumen mana yang salah, dan melakukannya tanpa mengganggu prosesnya
(atau benang) penanganan sinyal.

Bila tersedia, inti kecil(2) panggilan sistem digunakan, untuk menanyakan apakah wilayah memori valid.
Itu dapat mengembalikan tiga hasil: dipetakan tetapi tidak di memori fisik, dipetakan dan di fisik
memori, dan tidak dipetakan. Saat menguji validitas pointer, dua yang pertama adalah "ya"
dan yang terakhir adalah "tidak".

Memeriksa string C lebih sulit, karena alih-alih pointer dan ukuran, kami hanya
memiliki penunjuk. Untuk menentukan ukurannya, kita harus menemukan NUL, dan itu bisa
segfault, tangkap-22.

Untuk mengatasi ini, perpustakaan libexplain menggunakan status(2) panggilan sistem (dengan yang diketahui
argumen kedua yang bagus) untuk menguji validitas string C. Kegagalan kembali && errno == EFAULT
adalah "tidak", dan yang lainnya adalah "ya". Ini, tentu saja membatasi string ke PATH_MAX
karakter, tapi itu biasanya bukan masalah untuk perpustakaan libexplain, karena itu
hampir selalu senar terpanjang yang dipedulikannya.

EMFILE, Terlalu banyak Buka arsip
Kesalahan ini terjadi ketika proses sudah memiliki jumlah maksimum deskriptor file yang terbuka.
Jika batas sebenarnya akan dicetak, dan perpustakaan libexplain mencoba, Anda tidak dapat membuka
sebuah file di / proc untuk membaca apa adanya.
open_max = sysconf(_SC_OPEN_MAX);
Yang ini tidak begitu sulit, ada sysconf(3) cara mendapatkan limit.

ENFIL, Terlalu banyak Buka arsip in sistem
Kesalahan ini terjadi ketika batas sistem pada jumlah total file yang terbuka telah
tercapai. Dalam hal ini tidak ada gunanya sysconf(3) cara mendapatkan limit.

Menggali lebih dalam, orang mungkin menemukan bahwa di Linux ada / proc entri yang bisa kita baca
mendapatkan nilai ini. Catch-22: kami kehabisan deskriptor file, jadi kami tidak dapat membuka file untuk
baca batasnya.

Di Linux ada panggilan sistem untuk mendapatkannya, tetapi tidak memiliki fungsi pembungkus [e]glibc, jadi
Anda harus melakukannya dengan sangat hati-hati:
panjang
jelaskan_maxfile(kosong)
{
#ifdef __linux__
struct __sysctl_args argumen;
file maks int32_t;
ukuran_t maxfile_size = ukuran dari(file maks);
int nama[] = { CTL_FS, FS_MAXFILE };
memset(&args, 0, sizeof(struct __sysctl_args));
args.nama = nama;
args.nlen = 2;
args.oldval = &maxfile;
args.oldlenp = &maxfile_size;
if (syscall(SYS__sysctl, &args) >= 0)
kembali maxfile;
#berakhir jika
kembali -1;
}
Ini memungkinkan batas untuk disertakan dalam pesan kesalahan, jika tersedia.

ENVAL "Tidak sah argumen" vs ENOSYS "Fungsi tidak dilaksanakan”
Tindakan yang tidak didukung (seperti tautan simbolik(2) pada sistem file FAT) tidak dilaporkan
secara konsisten dari satu panggilan sistem ke panggilan berikutnya. Dimungkinkan untuk memiliki EINVAL atau
ENOSYS kembali.

Akibatnya, perhatian harus diberikan pada kasus kesalahan ini untuk memperbaikinya, terutama
karena EINVAL juga dapat merujuk pada masalah dengan satu atau lebih argumen panggilan sistem.

Note bahwa salah(3) is tidak selalu set
Ada kalanya kita perlu membaca sumber [e]glibc untuk menentukan bagaimana dan
ketika kesalahan dikembalikan untuk beberapa panggilan sistem.

feof(3) fileno(3)
Sering diasumsikan bahwa fungsi-fungsi ini tidak dapat mengembalikan kesalahan. Ini hanya benar jika
itu aliran argumen valid, namun mereka mampu mendeteksi yang tidak valid
penunjuk.

fpathconf(3) pathconf(3)
Nilai kembali dari fpathconf(2) dan pathconf(2) secara sah bisa menjadi -1, jadi
perlu untuk melihat apakah salah(3) telah diatur secara eksplisit.

ioctl(2)
Nilai kembali dari ioctl(2) secara sah bisa menjadi -1, jadi perlu untuk melihat apakah
salah(3) telah diatur secara eksplisit.

bacadir(3)
Nilai kembali dari bacadir(3) adalah NULL untuk kesalahan dan akhir file. Dia
perlu untuk melihat apakah salah(3) telah diatur secara eksplisit.

setbuf(3) setbuffer(3) setlinebuf(3) setvbuf(3)
Semua kecuali yang terakhir dari fungsi ini kembali batal. Dan setvbuf(3) hanya didokumentasikan sebagai
mengembalikan "bukan nol" pada kesalahan. Itu perlu untuk melihat apakah salah(3) telah secara eksplisit
ditetapkan.

jalan(3) jalan-jalan(3) berjalan(3) jalan-jalan(3) strtoul(3) jalan-jalan(3)
Fungsi-fungsi ini mengembalikan 0 pada kesalahan, tetapi itu juga merupakan nilai pengembalian yang sah. Dia
perlu untuk melihat apakah salah(3) telah diatur secara eksplisit.

tidak dll(3)
Meskipun hanya satu karakter cadangan yang diamanatkan oleh standar ANSI C, ternyata
bahwa [e]glibc mengizinkan lebih... tapi itu berarti bisa gagal dengan ENOMEM. Bisa
juga gagal dengan EBADF jika fp adalah palsu. Yang paling sulit dari semuanya, jika Anda melewati EOF kesalahan
kembali terjadi, tetapi errno tidak disetel.

Pustaka libexplain mendeteksi semua kesalahan ini dengan benar, bahkan dalam kasus di mana
nilai kesalahan didokumentasikan dengan buruk, jika sama sekali.

ENOSPC, Tidak ruang meninggalkan on alat
Ketika kesalahan ini merujuk ke file pada sistem file, perpustakaan libexplain mencetak mount
titik sistem file dengan masalah. Ini bisa membuat sumber kesalahan banyak
lebih jelas.
tulis(fildes = 1 "contoh", data = 0xbfff2340, data_size = 5) gagal, Tidak ada ruang tersisa
pada perangkat (28, ENOSPC) karena sistem file yang berisi fildes ("/ Home") tidak punya
lebih banyak ruang untuk data
Karena lebih banyak dukungan perangkat khusus ditambahkan, pesan kesalahan diharapkan untuk menyertakan perangkat
nama dan ukuran sebenarnya dari perangkat.

EROFS, Hanya baca fillet sistem
Ketika kesalahan ini merujuk ke file pada sistem file, perpustakaan libexplain mencetak mount
titik sistem file dengan masalah. Ini bisa membuat sumber kesalahan banyak
lebih jelas.

Karena lebih banyak dukungan perangkat khusus ditambahkan, pesan kesalahan diharapkan untuk menyertakan perangkat
nama dan jenis.
buka(nama jalur = "/ dev/fd0", O_RDWR, 0666) gagal, Sistem file read-only (30, EROFS)
karena floppy disk memiliki set tab proteksi tulis

...karena CD-ROM tidak dapat ditulisi
...karena kartu memori memiliki set tab proteksi tulis
...karena pita magnetik inci tidak memiliki cincin tulis

mengubah nama
Grafik mengubah nama(2) panggilan sistem digunakan untuk mengubah lokasi atau nama file, memindahkannya
antar direktori jika diperlukan. Jika nama jalur tujuan sudah ada, itu akan menjadi
diganti secara atom, sehingga tidak ada titik di mana proses lain mencoba untuk
mengaksesnya akan menemukannya hilang.

Namun ada batasannya: Anda hanya dapat mengganti nama direktori di atas direktori lain
direktori jika direktori tujuan tidak kosong.
rename(oldpath = "foo", newpath = "bar") gagal, Direktori tidak kosong (39,
ENOTEMPTY) karena newpath bukan direktori kosong; yaitu, berisi entri
Selain daripada "." dan ".."
Anda juga tidak dapat mengganti nama direktori di atas non-direktori.
rename(oldpath = "foo", newpath = "bar") gagal, Bukan direktori (20, ENOTDIR)
karena oldpath adalah direktori, tetapi newpath adalah file biasa, bukan direktori
Kebalikannya juga tidak diperbolehkan
rename(oldpath = "foo", newpath = "bar") gagal, Apakah direktori (21, EISDIR)
karena newpath adalah direktori, tetapi oldpath adalah file biasa, bukan direktori

Hal ini tentu saja membuat pekerjaan perpustakaan libexplain menjadi lebih rumit, karena
batalkan tautan(2) atau adalah rm(2) panggilan sistem disebut secara implisit oleh mengubah nama(2), dan semua
batalkan tautan(2) atau adalah rm(2) kesalahan juga harus dideteksi dan ditangani.

dup2
Grafik dup2(2) panggilan sistem digunakan untuk membuat deskriptor file kedua yang mereferensikan
objek yang sama dengan deskriptor file pertama. Biasanya ini digunakan untuk mengimplementasikan input shell
dan pengalihan keluaran.

Hal yang menyenangkan adalah, sama seperti mengubah nama(2) secara atom dapat mengganti nama file di atas an
file yang ada dan hapus file lama, dup2(2) dapat melakukan ini ke file yang sudah terbuka
deskriptor.

Sekali lagi, ini membuat pekerjaan perpustakaan libexplain lebih rumit, karena menutup penjualan(2)
panggilan sistem disebut secara implisit oleh dup2(2), dan semua dari menutup penjualan(2) kesalahan harus
terdeteksi dan ditangani, juga.

PETUALANGAN IN IOCTL SUPPORT


Grafik ioctl(2) panggilan sistem menyediakan cara bagi pembuat driver perangkat untuk berkomunikasi dengan
ruang pengguna yang tidak sesuai dengan API kernel yang ada. Melihat ioctl_list(2).

decoding Meminta Bilangan
Dari pandangan sepintas pada ioctl(2) antarmuka, tampaknya ada yang besar tapi terbatas
jumlah kemungkinan ioctl(2) permintaan. Masing-masing berbeda ioctl(2) permintaan efektif
panggilan sistem lain, tetapi tanpa keamanan jenis apa pun - kompiler tidak dapat membantu a
programmer mendapatkan hak ini. Ini mungkin motivasi di baliknya tcflush(3) dan
teman.

Kesan awalnya adalah Anda bisa memecahkan kode ioctl(2) permintaan menggunakan sakelar besar
penyataan. Ini ternyata tidak mungkin karena seseorang dengan cepat menemukan bahwa itu adalah
tidak mungkin untuk memasukkan semua header sistem yang diperlukan yang mendefinisikan berbagai ioctl(2)
permintaan, karena mereka mengalami kesulitan bermain baik satu sama lain.

Pandangan yang lebih dalam mengungkapkan bahwa ada berbagai nomor permintaan "pribadi", dan perangkat
penulis driver didorong untuk menggunakannya. Ini berarti ada kemungkinan yang jauh lebih besar
serangkaian permintaan, dengan nomor permintaan yang ambigu, daripada yang segera terlihat. Juga,
ada beberapa ambiguitas sejarah juga.

Kami sudah tahu bahwa sakelar itu tidak praktis, tetapi sekarang kami tahu bahwa untuk memilih
nama permintaan dan penjelasan yang sesuai, kami harus mempertimbangkan tidak hanya nomor permintaan tetapi
juga deskriptor file.

Penerapan ioctl(2) dukungan dalam perpustakaan libexplain adalah memiliki tabel
petunjuk untuk ioctl(2) deskriptor permintaan. Masing-masing deskriptor ini menyertakan opsi
pointer ke fungsi disambiguasi.

Setiap permintaan sebenarnya diimplementasikan dalam file sumber yang terpisah, sehingga diperlukan
termasuk file dibebaskan dari kewajiban untuk bermain baik dengan orang lain.

Perwakilan
Filosofi di balik perpustakaan libexplain adalah untuk memberikan informasi sebanyak
mungkin, termasuk representasi akurat dari panggilan sistem. Dalam kasus
ioctl(2) ini berarti mencetak nomor permintaan yang benar (berdasarkan nama) dan juga benar (atau
setidaknya berguna) representasi dari argumen ketiga.

Grafik ioctl(2) prototipe terlihat seperti ini:
int ioctl(int fildes, int permintaan, ...);
yang seharusnya membuat alarm tipe-keselamatan Anda berbunyi. Internal ke [e]glibc, ini diaktifkan
menjadi berbagai bentuk:
int __ioctl(int fildes, permintaan int, argumen panjang);
int __ioctl(int fildes, permintaan int, void *arg);
dan antarmuka syscall kernel Linux mengharapkan
asmlinkage long sys_ioctl(file int yang tidak ditandatangani, permintaan int yang tidak ditandatangani, panjang yang tidak ditandatangani
argumen);
Variabilitas ekstrim dari argumen ketiga adalah sebuah tantangan, ketika libexplain library
mencoba mencetak representasi dari argumen ketiga itu. Namun, begitu nomor permintaan
telah disamarkan, setiap entri dalam tabel ioctl perpustakaan libexplain memiliki a
fungsi print_data kustom (OO dilakukan secara manual).

Penjelasan
Ada lebih sedikit masalah dalam menentukan penjelasan yang akan digunakan. Setelah nomor permintaan
telah disamarkan, setiap entri di tabel ioctl perpustakaan libexplain memiliki kebiasaan
fungsi print_explanation (sekali lagi, OO dilakukan secara manual).

Tidak seperti panggilan sistem bagian 2 dan bagian 3, sebagian besar ioctl(2) permintaan tidak memiliki kesalahan
didokumentasikan. Ini berarti, untuk memberikan deskripsi kesalahan yang baik, perlu membaca kernel
sumber untuk ditemukan

· Apa salah(3) nilai dapat dikembalikan, dan

· penyebab setiap kesalahan.

Karena sifat OO dari pengiriman panggilan fungsi di dalam kernel, Anda perlu membaca
semua sumber yang menerapkan itu ioctl(2) permintaan, bukan hanya implementasi generik. Dia
diharapkan bahwa kernel yang berbeda akan memiliki nomor kesalahan yang berbeda dan secara halus
penyebab kesalahan yang berbeda.

ENVAL vs ENOTI
Situasinya bahkan lebih buruk untuk ioctl(2) permintaan daripada panggilan sistem, dengan EINVAL dan
ENOTTY keduanya digunakan untuk menunjukkan bahwa ioctl(2) permintaan tidak pantas dalam hal itu
konteks, dan kadang-kadang ENOSYS, ENOTSUP dan EOPNOTSUPP (dimaksudkan untuk digunakan untuk soket) sebagai
dengan baik. Ada komentar di sumber kernel Linux yang tampaknya menunjukkan progresif
pembersihan sedang berlangsung. Untuk kekacauan ekstra, BSD menambahkan ENOIOCTL ke kebingungan.

Akibatnya, perhatian harus diberikan pada kasus kesalahan ini untuk memperbaikinya, terutama
karena EINVAL juga dapat merujuk pada masalah dengan satu atau lebih argumen panggilan sistem.

intptr_t
Standar C99 mendefinisikan tipe integer yang dijamin dapat menahan pointer apa pun
tanpa kehilangan representasi.

Prototipe syscall fungsi di atas akan lebih baik ditulis
long sys_ioctl(file int tidak ditandatangani, permintaan int tidak ditandatangani, intptr_t arg);
Masalahnya adalah disonansi kognitif yang disebabkan oleh spesifik perangkat atau spesifik sistem file
ioctl(2) implementasi, seperti:
long vfs_ioctl(file struct *filp, unsigned int cmd, unsigned long arg);
Mayoritas ioctl(2) permintaan sebenarnya memiliki argumen ketiga int *arg. Tapi memilikinya
menyatakan lead panjang ke kode yang memperlakukan ini sebagai *arg. Ini tidak berbahaya pada 32-bit
(sizeof(long) == sizeof(int)) tetapi buruk pada 64-bit (sizeof(long) != sizeof(int)).
Tergantung pada endian-ness, Anda mendapatkan atau tidak mendapatkan nilai yang Anda harapkan, tetapi Anda selalu mendapatkan
coretan memori atau coretan tumpukan juga.

Menulis semua ini sebagai
int ioctl(int fildes, int permintaan, ...);
int __ioctl(int fildes, int permintaan, intptr_t arg);
long sys_ioctl(file int tidak ditandatangani, permintaan int tidak ditandatangani, intptr_t arg);
long vfs_ioctl(file struct *filp, cmd int yang tidak ditandatangani, intptr_t arg);
menekankan bahwa bilangan bulat hanyalah bilangan bulat untuk mewakili besaran yang hampir
selalu tipe pointer yang tidak berhubungan.

KESIMPULAN


Gunakan libexplain, pengguna Anda akan menyukainya.

HAK CIPTA


libexplain versi 1.4
Hak Cipta (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Peter Miller

Gunakan explain_lca2010 online menggunakan layanan onworks.net


Server & Workstation Gratis

Unduh aplikasi Windows & Linux

  • 1
    menenggak
    menenggak
    SWIG adalah alat pengembangan perangkat lunak
    yang menghubungkan program yang ditulis dalam C dan
    C++ dengan berbagai level tinggi
    bahasa pemrograman. SWIG digunakan dengan
    berbeda...
    Unduh SWIG.dll
  • 2
    Tema WooCommerce Nextjs React
    Tema WooCommerce Nextjs React
    Bereaksi tema WooCommerce, dibangun dengan
    JS berikutnya, Webpack, Babel, Node, dan
    Express, menggunakan GraphQL dan Apollo
    Klien. Toko WooCommerce di React(
    berisi: Produk...
    Unduh WooCommerce Nextjs React Theme
  • 3
    archlabs_repo
    archlabs_repo
    Repo paket untuk ArchLabs Ini adalah
    aplikasi yang juga bisa diambil
    dari
    https://sourceforge.net/projects/archlabs-repo/.
    Ini telah dihosting di OnWorks di ...
    Unduh archlabs_repo
  • 4
    Proyek Zephyr
    Proyek Zephyr
    Proyek Zephyr adalah generasi baru
    sistem operasi waktu-nyata (RTOS) yang
    mendukung banyak perangkat keras
    ilmu bangunan. Hal ini didasarkan pada
    kernel jejak kecil...
    Unduh Proyek Zephyr
  • 5
    SCon
    SCon
    SCons adalah alat konstruksi perangkat lunak
    itu adalah alternatif yang unggul untuk
    alat pembuatan "Buat" klasik yang
    kita semua tahu dan cinta. SCon adalah
    dilaksanakan...
    Unduh SCons.dll
  • 6
    PSeInt
    PSeInt
    PSeInt adalah penerjemah kode semu untuk
    siswa pemrograman berbahasa Spanyol.
    Tujuan utamanya adalah menjadi alat untuk
    belajar dan memahami dasar
    konsep...
    Unduh PSeInt.dll
  • Lebih banyak lagi »

Perintah Linux

Ad