EnglishFrenchSpanyol

Ad


Favicon OnWorks

explain_lca2010 - Dalam Talian di Awan

Jalankan explain_lca2010 dalam penyedia pengehosan percuma OnWorks melalui Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS

Ini ialah arahan explain_lca2010 yang boleh dijalankan dalam penyedia pengehosan percuma OnWorks menggunakan salah satu daripada berbilang stesen kerja dalam talian percuma kami seperti Ubuntu Online, Fedora Online, emulator dalam talian Windows atau emulator dalam talian MAC OS.

JADUAL:

NAMA


explain_lca2010 - Tiada medium ditemui: apabila tiba masanya untuk berhenti mencuba membaca strerror(3)'s
fikiran.

MOTIVASI


Idea untuk libexplain berlaku kepada saya pada awal 1980-an. Setiap kali panggilan sistem
mengembalikan ralat, kernel mengetahui dengan tepat apa yang salah... dan memampatkan ini
kurang daripada 8 bit salah. Ruang pengguna mempunyai akses kepada data yang sama seperti kernel, ia
ruang pengguna sepatutnya dapat mengetahui dengan tepat apa yang berlaku untuk mencetuskan ralat
kembali, dan gunakan ini untuk menulis mesej ralat yang baik.

Bolehkah ia semudah itu?

ralat mesej as keceriaan
Mesej ralat yang baik selalunya ialah tugas "satu peratus" yang digugurkan apabila dijadualkan
tekanan memerah projek anda. Walau bagaimanapun, mesej ralat yang baik boleh membuat besar,
peningkatan yang tidak seimbang dengan pengalaman pengguna, apabila pengguna mengembara ke arah yang menakutkan
wilayah yang tidak diketahui biasanya tidak ditemui. Ini bukan tugas yang mudah.

Sebagai pengaturcara larva, pengarang tidak melihat masalah dengan ralat (sepenuhnya tepat).
mesej seperti ini:
pengecualian terapung (teras dibuang)
sehingga tafsiran bukan pengaturcara alternatif ditunjukkan. Tetapi itu bukan
satu-satunya perkara yang salah dengan mesej ralat Unix. Berapa kerap anda melihat mesej ralat seperti:
$ ./bodoh
tidak boleh membuka fail
$
Terdapat dua pilihan untuk pembangun pada ketika ini:

1.
anda boleh menjalankan penyahpepijat, seperti gdb(1), atau

2.
anda boleh menggunakan helai(1) atau kekuda(1) untuk melihat ke dalam.

· Ingat bahawa pengguna anda mungkin tidak mempunyai akses kepada alatan ini, apatah lagi keupayaan
untuk menggunakannya. (Ia adalah masa yang sangat lama sejak itu Unix pemula bermaksud “hanya telah menulis 1
pemacu peranti”.)

Dalam contoh ini, bagaimanapun, menggunakan helai(1) mendedahkan
$ helai -e jejak=terbuka ./bodoh
open("beberapa/fail", O_RDONLY) = -1 ENOENT (Tiada fail atau direktori sedemikian)
tidak boleh membuka fail
$
Ini adalah lebih banyak maklumat daripada yang diberikan oleh mesej ralat. Lazimnya,
kod sumber bodoh kelihatan seperti ini
int fd = buka("sesuatu/benda", O_RDONLY);
jika (fd < 0)
{
fprintf(stderr, "tidak boleh membuka fail\n");
keluar(1);
}
Pengguna tidak diberitahu yang fail, dan juga gagal memberitahu pengguna yang ralat. Adakah fail itu
walaupun di sana? Adakah terdapat masalah kebenaran? Ia memberitahu anda ia cuba membuka a
fail, tetapi itu mungkin secara tidak sengaja.

Dapatkan kayu petunjuk anda dan pergi mengalahkan pengaturcara larva dengannya. Beritahu dia tentang kesalahan(3).
Kali seterusnya anda menggunakan atur cara anda melihat mesej ralat yang berbeza:
$ ./bodoh
buka: Tiada fail atau direktori sedemikian
$
Kemajuan, tetapi tidak seperti yang kita harapkan. Bagaimana pengguna boleh menyelesaikan masalah jika mesej ralat
tidak memberitahu dia apa masalahnya? Melihat kepada sumber, kita lihat
int fd = buka("sesuatu/benda", O_RDONLY);
jika (fd < 0)
{
perror("terbuka");
keluar(1);
}
Masa untuk larian lain dengan kayu petunjuk. Kali ini, mesej ralat mengambil satu langkah
ke hadapan dan satu langkah ke belakang:
$ ./bodoh
sesuatu/benda: Tidak ada fail atau direktori seperti itu
$
Sekarang kita tahu fail yang cuba dibuka, tetapi tidak lagi dimaklumkan bahawa ia adalah membuka(2)
itu gagal. Dalam kes ini ia mungkin tidak penting, tetapi ia boleh menjadi penting untuk
panggilan sistem lain. Ia boleh jadi mencipta(2) sebaliknya, operasi yang membayangkan bahawa
kebenaran yang berbeza diperlukan.
const char *nama fail = "sesuatu/benda";
int fd = open(nama fail, O_RDONLY);
jika (fd < 0)
{
kesalahan(nama fail);
keluar(1);
}
Kod contoh di atas malangnya adalah tipikal pengaturcara bukan larva juga. Masa
untuk memberitahu pelajar padawan kami tentang strerror(3) panggilan sistem.
$ ./bodoh
membuka sesuatu/benda: Tidak ada fail atau direktori seperti itu
$
Ini memaksimumkan maklumat yang boleh disampaikan kepada pengguna. Kod itu kelihatan seperti
ini:
const char *nama fail = "sesuatu/benda";
int fd = open(nama fail, O_RDONLY);
jika (fd < 0)
{
fprintf(stderr, "buka %s: %s\n", nama fail, strerror(errno));
keluar(1);
}
Sekarang kita mempunyai panggilan sistem, nama fail dan rentetan ralat. Ini mengandungi semua
maklumat yang helai(1) dicetak. Itu adalah sebaik mungkin.

Atau inikah?

Batasan of kesalahan and strerror
Masalah yang penulis lihat, pada tahun 1980-an, ialah mesej ralat tidak lengkap.
Adakah "tiada fail atau direktori sedemikian" merujuk kepada "beberapadirektori ”, atau ke “perkara” fail masuk
yang "beberapa” direktori?

Pandangan pantas pada halaman lelaki untuk strerror(3) memberitahu:
strerror - kembalikan rentetan yang menerangkan nombor ralat
Perhatikan dengan baik: ia menerangkan ralat nombor, bukan kesilapan.

Sebaliknya, kernel tahu apakah kesilapan itu. Terdapat titik tertentu dalam
kod kernel, disebabkan oleh keadaan tertentu, di mana kod kernel bercabang dan berkata "tidak".
Bolehkah program ruang pengguna mengetahui keadaan khusus dan menulis ralat yang lebih baik
mesej?

Namun, masalahnya semakin mendalam. Bagaimana jika masalah itu berlaku semasa membaca(2) sistem
panggilan, bukannya membuka(2) panggilan? Ia mudah untuk mesej ralat yang dikaitkan dengan
membuka(2) untuk memasukkan nama fail, ia ada di sana. Tetapi untuk dapat memasukkan nama fail
dalam kesilapan yang berkaitan dengan membaca(2) panggilan sistem, anda perlu lulus nama fail semua
cara menuruni timbunan panggilan, serta deskriptor fail.

Dan inilah perkara yang menarik: kernel sudah mengetahui nama fail fail tersebut
deskriptor dikaitkan dengan. Mengapa pengaturcara perlu menghantar data berlebihan semua
cara menuruni timbunan panggilan hanya untuk menambah baik mesej ralat yang mungkin tidak pernah dikeluarkan? Dalam
realiti, ramai pengaturcara tidak peduli, dan mesej ralat yang terhasil adalah lebih teruk
ia.

Tetapi itu adalah tahun 1980-an, pada PDP11, dengan sumber terhad dan tiada perpustakaan dikongsi. belakang
maka, tiada perisa Unix disertakan / proc walaupun dalam bentuk asas, dan lsof(1) program
lebih sedekad lagi. Jadi idea itu diketepikan sebagai tidak praktikal.

Tahap Infinity Khidmat Bantuan
Bayangkan anda adalah sokongan infiniti tahap. Perihalan kerja anda mengatakan bahawa anda tidak pernah
pernah perlu bercakap dengan pengguna. Mengapa, kemudian, masih terdapat aliran berterusan orang mahu
anda, guru Unix tempatan, untuk mentafsir satu lagi mesej ralat?

Anehnya, 25 tahun kemudian, walaupun sistem kebenaran yang mudah, dilaksanakan dengan lengkap
konsisten, kebanyakan pengguna Unix masih tidak tahu cara menyahkod "Tiada fail atau direktori sedemikian",
atau mana-mana mesej ralat samar lain yang mereka lihat setiap hari. Atau, sekurang-kurangnya, samar ke
Mereka.

Bukankah lebih baik jika sokongan teknologi peringkat pertama tidak memerlukan mesej ralat ditafsirkan?
Bukankah lebih baik untuk mempunyai mesej ralat yang boleh difahami oleh pengguna tanpa membuat panggilan
sokongan teknikal?

Hari ini / proc pada Linux lebih daripada mampu memberikan maklumat yang diperlukan untuk menyahkod
sebahagian besar mesej ralat, dan arahkan pengguna kepada punca terdekat mereka
masalah. Pada sistem dengan terhad / proc pelaksanaan, yang lsof(1) arahan boleh diisi
banyak jurang.

Pada tahun 2008, aliran permintaan terjemahan berlaku kepada pengarang terlalu kerap. Ia adalah
masa untuk meneliti semula idea berusia 25 tahun itu, dan libexplain adalah hasilnya.

MENGGUNAKAN THE PERPUSTAKAAN


Antara muka ke perpustakaan cuba konsisten, jika boleh. Mari kita mulakan dengan
contoh menggunakan strerror(3):
jika (namakan semula(laluan_lama, laluan_baru) < 0)
{
fprintf(stderr, "namakan semula %s %s: %s\n", old_path, new_path,
strerror(errno));
keluar(1);
}
Idea di sebalik libexplain adalah untuk menyediakan a strerror(3) bersamaan untuk setiap panggilan sistem,
disesuaikan secara khusus untuk panggilan sistem itu, supaya ia boleh memberikan ralat yang lebih terperinci
mesej, yang mengandungi banyak maklumat yang anda lihat di bawah tajuk "ERRORS" bahagian
2 dan 3 lelaki halaman, ditambah dengan maklumat tentang keadaan sebenar, hujah sebenar
nilai, dan had sistem.

. Mudah kes
. strerror(3) penggantian:
jika (namakan semula(laluan_lama, laluan_baru) < 0)
{
fprintf(stderr, "%s\n", explain_rename(old_path, new_path));
keluar(1);
}

. Errno kes
Ia juga mungkin untuk lulus eksplisit salah(3) nilai, jika anda mesti terlebih dahulu melakukan beberapa
pemprosesan yang akan mengganggu salah, seperti pemulihan ralat:
jika (namakan semula(laluan_lama, laluan_baru < 0))
{
int old_errno = errno;
...kod Bahawa menganggu salah...
fprintf(stderr, "%s\n", explain_errno_rename(old_errno,
laluan_lama, laluan_baru));
keluar(1);
}

. Berbilang benang kes
Sesetengah aplikasi berbilang benang, dan dengan itu tidak dapat berkongsi dalaman libexplain
penampan. Anda boleh membekalkan penimbal anda sendiri menggunakan
jika (nyahpaut(nama laluan))
{
mesej char[3000];
explain_message_unlink(message, saiz(mesej), nama laluan);
dialog_ralat(mesej);
pulangan -1;
}
Dan untuk kesempurnaan, kedua-duanya salah(3) dan selamat benang:
ssize_t nbytes = baca(fd, data, sizeof(data));
jika (nbait < 0)
{
mesej char[3000];
int old_errno = errno;
...kesilapan pemulihan...
explain_message_errno_read(message, saiz(mesej),
old_errno, fd, data, saiz(data));
dialog_ralat(mesej);
pulangan -1;
}

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

Antara muka Gula
Satu set fungsi ditambah sebagai fungsi kemudahan, untuk memikat pengaturcara untuk menggunakan
perpustakaan libexplain, ternyata menjadi fungsi libexplain yang paling biasa digunakan oleh pengarang dalam
program baris arahan:
int fd = explain_creat_or_die(nama fail, 0666);
Fungsi ini cuba mencipta fail baharu. Jika ia tidak boleh, ia mencetak mesej ralat dan
keluar dengan EXIT_FAILURE. Jika tiada ralat, ia mengembalikan deskriptor fail baharu.

Fungsi yang berkaitan:
int fd = explain_creat_on_error(nama fail, 0666);
akan mencetak mesej ralat pada kegagalan, tetapi juga mengembalikan hasil ralat asal, dan
salah(3) tidak diganggu, juga.

SEMUA yang lain sistem panggilan
Secara umum, setiap panggilan sistem mempunyai fail termasuk sendiri
#termasuknama.h>
yang mentakrifkan prototaip fungsi untuk enam fungsi:

· terangkan_nama,

· explain_errno_nama,

· explain_message_nama,

· explain_message_errno_nama,

· terangkan_nama_atau_mati dan

· terangkan_nama_on_error.

Setiap prototaip fungsi mempunyai dokumentasi Doxygen, dan dokumentasi ini is tidak dilucutkan
apabila fail sertakan dipasang.

. tunggu(2) panggilan sistem (dan rakan) mempunyai beberapa varian tambahan yang juga mentafsir kegagalan
menjadi status keluar yang bukan EXIT_SUCCESS. Ini terpakai kepada sistem(3) dan pclose(3) sebagai
juga.

Liputan termasuk 221 panggilan sistem dan 547 permintaan ioctl. Terdapat banyak lagi sistem
panggilan masih belum dilaksanakan. Panggilan sistem yang tidak pernah kembali, seperti keluar(2), tidak hadir
di perpustakaan, dan tidak akan pernah. The exec keluarga panggilan sistem adalah disokong, kerana
mereka kembali apabila terdapat kesilapan.

Kucing
Beginilah rupa program "kucing" hipotesis, dengan pelaporan ralat penuh,
menggunakan libexplain.
#termasuk
#sertakan
#termasuk
Terdapat satu termasuk untuk libexplain, ditambah dengan suspek biasa. (Jika anda ingin mengurangkan
beban prapemproses, anda boleh menggunakan khususnama.h> termasuk.)
kekosongan statik
proses(FAIL *fp)
{
untuk (;;)
{
penampan char[4096];
size_t n = explain_fread_or_die(buffer, 1, sizeof(buffer), fp);
jika (!n)
memecahkan;
explain_fwrite_or_die(buffer, 1, n, stdout);
}
}
. proses fungsi menyalin aliran fail ke output standard. Sekiranya ralat berlaku
untuk sama ada membaca atau menulis, ia dilaporkan (dan nama laluan akan disertakan dalam
ralat) dan arahan keluar dengan EXIT_FAILURE. Kami tidak bimbang untuk menjejaki
nama laluan, atau menghantarnya ke timbunan panggilan.
int
utama(int argc, char **argv)
{
untuk (;;)
{
int c = getopt(argc, argv, "o:");
jika (c == EOF)
memecahkan;
suis (c)
{
kes 'o':
explain_freopen_or_die(optarg, "w", stdout);
memecahkan;
Bahagian yang menyeronokkan kod ini ialah libexplain boleh melaporkan ralat termasuk yang nama jalan walaupun
jika anda tidak buka semula stdout secara eksplisit seperti yang dilakukan di sini. Kami tidak risau pun
menjejaki nama fail.
lalai:
fprintf(stderr, "Penggunaan: %ss [ -o ] ...\n",
argv[0]);
kembali EXIT_FAILURE;
}
}
jika (optind == argc)
proses(stdin);
lagi
{
manakala (optind < argc)
{
FAIL *fp = explain_fopen_or_die(argv[optind]++, "r");
proses(fp);
explain_fclose_or_die(fp);
}
}
Output standard akan ditutup secara tersirat, tetapi sudah terlambat untuk laporan ralat
dikeluarkan, jadi kami melakukannya di sini, sekiranya I/O buffer belum menulis apa-apa lagi, dan
terdapat ralat ENOSPC atau sesuatu.
explain_fflush_or_die(stdout);
kembalikan EXIT_SUCCESS;
}
Itu sahaja. Pelaporan ralat penuh, kod jelas.

milik Rusty Skala of Antara muka Kebaikan
Bagi anda yang tidak biasa dengannya, Rusty Russel "Bagaimana Saya Membuat Ini Sukar untuk Disalahgunakan?"
halaman mesti dibaca untuk pereka API.
http://ozlabs.org/~rusty/index.cgi/tech/2008‐03‐30.html

10. ia mustahil kepada mendapatkan salah.

Matlamat perlu ditetapkan tinggi, bercita-cita tinggi, supaya anda tidak mencapainya dan menganggap anda berjaya
selesai apabila anda tidak.

Pustaka libexplain mengesan penunjuk palsu dan banyak parameter panggilan sistem palsu yang lain,
dan secara amnya cuba mengelakkan segfault walaupun dalam keadaan yang paling mencabar.

Pustaka libexplain direka bentuk untuk selamat untuk benang. Lebih banyak penggunaan dunia sebenar mungkin
mendedahkan tempat ini boleh diperbaiki.

Masalah terbesar adalah dengan nama fungsi sebenar itu sendiri. Kerana C tidak mempunyai
name‐spaces, perpustakaan libexplain sentiasa menggunakan awalan nama explain_. Ini adalah
cara tradisional untuk mencipta ruang nama-pseudo untuk mengelakkan konflik simbol.
Walau bagaimanapun, ia menghasilkan beberapa nama yang tidak wajar.

9. . pengkompil or Pautan tidak akan biarkan anda mendapatkan it salah.

Kesilapan biasa ialah menggunakan explain_open di mana explain_open_or_die dimaksudkan.
Nasib baik, pengkompil sering akan mengeluarkan ralat jenis pada ketika ini (contohnya tidak boleh menetapkan
const char * rvalue kepada int lvalue).

8. . pengkompil akan memberi amaran kepada if anda mendapatkan it salah.

Jika explain_rename digunakan apabila explain_rename_or_die dimaksudkan, ini boleh menyebabkan lain
masalah. GCC mempunyai atribut fungsi warn_unused_result yang berguna dan libexplain
perpustakaan melampirkannya pada semua explain_nama fungsi panggilan untuk menghasilkan amaran apabila anda
membuat kesilapan ini. Gabungkan ini dengan gcc -Werror untuk mempromosikan ini ke tahap 9 kebaikan.

7. . Jelas penggunaan is (mungkin) yang membetulkan one.

Nama fungsi telah dipilih untuk menyampaikan maksudnya, tetapi ini tidak selalunya
berjaya. Sambil terangkan_nama_atau_mati dan terangkan_nama_on_error adalah agak deskriptif,
varian selamat benang yang kurang digunakan adalah lebih sukar untuk dinyahkod. Prototaip fungsi membantu
pengkompil ke arah pemahaman, dan komen Doxygen dalam fail pengepala membantu pengguna
ke arah persefahaman.

6. . nama memberitahu anda bagaimana kepada penggunaan ia.

Ia amat penting untuk membaca explain_nama_or_die sebagai “terangkan (nama atau mati)".
Menggunakan awalan ruang nama explain_ yang konsisten mempunyai beberapa kesan sampingan yang malang dalam
jabatan kejelasan, juga.

Susunan perkataan dalam nama juga menunjukkan susunan hujah. Hujahnya
senarai sentiasa akhir dengan hujah yang sama seperti yang dihantar kepada panggilan sistem; semua of mereka. Jika
_errno_ muncul dalam nama, hujahnya sentiasa mendahului argumen panggilan sistem. Jika
_message_ muncul dalam nama, dua hujahnya sentiasa didahulukan.

5. Do it kanan or it akan memecahkan at masa berjalan.

Pustaka libexplain mengesan penunjuk palsu dan banyak parameter panggilan sistem palsu yang lain,
dan secara amnya cuba mengelakkan segfault walaupun dalam keadaan yang paling mencabar. Sepatutnya
tidak pernah putus pada masa jalanan, tetapi lebih banyak penggunaan dunia nyata pasti akan menambah baik perkara ini.

Sesetengah mesej ralat ditujukan kepada pembangun dan penyelenggara dan bukannya pengguna akhir, kerana ini
boleh membantu dengan penyelesaian pepijat. Bukan "berehat pada masa jalan" sebagai "bermaklumat di
runtime” (selepas barfs panggilan sistem).

4. Ikut biasa konvensyen and awak akan mendapatkan it betul.

Oleh kerana C tidak mempunyai ruang nama, perpustakaan libexplain sentiasa menggunakan nama explain_
awalan. Ini adalah cara tradisional untuk mencipta ruang nama-pseudo untuk mengelakkan
konflik simbol.

Argumen belakang semua panggilan libexplain adalah sama dengan panggilan sistem mereka
sedang menerangkan. Ini bertujuan untuk menyediakan konvensyen yang konsisten sama dengan
sistem memanggil diri mereka sendiri.

3. Baca yang dokumentasi and awak akan mendapatkan it betul.

Pustaka libexplain bertujuan untuk mempunyai dokumentasi Doxygen yang lengkap untuk setiap satu
panggilan API awam (dan juga secara dalaman).

MESEJ KANDUNGAN


Mengerjakan libexplain adalah sedikit seperti melihat bahagian bawah kereta anda apabila ia dihidupkan
pengangkat di mekanik. Terdapat beberapa barang hodoh di bawah sana, ditambah lumpur dan kerak, dan
pengguna jarang melihatnya. Mesej ralat yang baik perlu bermaklumat, walaupun untuk pengguna yang
telah cukup bernasib baik kerana tidak perlu melihat bahagian bawah dengan kerap, dan juga
bermaklumat untuk mekanik mendengar penerangan pengguna melalui telefon. Ini adalah
tiada tugas yang mudah.

Mengimbas semula contoh pertama kami, kod itu akan menyukai ini jika ia menggunakan libexplain:
int fd = explain_open_or_die("some/thing", O_RDONLY, 0);
akan gagal dengan mesej ralat seperti ini
buka (nama laluan = "beberapa/fail", bendera = O_RDONLY) gagal, Tiada fail atau direktori sedemikian
(2, ENOENT) kerana tiada direktori "beberapa" dalam direktori semasa
Ini terpecah kepada tiga bahagian
panggilan sistem gagal, ralat sistem kerana
penerangan

Sebelum Kerana
Adalah mungkin untuk melihat bahagian mesej sebelum "kerana" sebagai terlalu teknikal kepada bukan
pengguna teknikal, kebanyakannya hasil daripada mencetak dengan tepat panggilan sistem itu sendiri di
permulaan mesej ralat. Dan ia kelihatan seperti helai(1) output, untuk geek bonus
mata.
buka (nama laluan = "beberapa/fail", bendera = O_RDONLY) gagal, Tiada fail atau direktori sedemikian
(2, ENOENT)
Bahagian mesej ralat ini penting kepada pembangun semasa dia menulis kod,
dan sama pentingnya kepada penyelenggara yang perlu membaca laporan pepijat dan membetulkan pepijat dalam
kod. Ia mengatakan dengan tepat apa yang gagal.

Jika teks ini tidak dibentangkan kepada pengguna maka pengguna tidak boleh menyalin dan menampalnya ke dalam a
laporan pepijat, dan jika ia tiada dalam laporan pepijat, penyelenggara tidak dapat mengetahui perkara yang sebenarnya berlaku
salah.

Selalunya kakitangan teknologi akan menggunakan helai(1) atau kekuda(1) untuk mendapatkan maklumat yang tepat ini, tetapi
jalan ini tidak dibuka apabila membaca laporan pepijat. Sistem wartawan pepijat jauh
jauh, dan, sekarang, dalam keadaan yang jauh berbeza. Justeru, maklumat ini perlu ada dalam
laporan pepijat, yang bermaksud ia mesti berada dalam mesej ralat.

Perwakilan panggilan sistem juga memberikan konteks kepada seluruh mesej. Jika perlu
timbul, hujah panggilan sistem yang menyinggung boleh dirujuk dengan nama dalam penjelasan
selepas "kerana". Di samping itu, semua rentetan dipetik sepenuhnya dan terlepas rentetan C, jadi
baris baharu tertanam dan aksara bukan cetakan tidak akan menyebabkan terminal pengguna hilang
bermasalah.

. ralat sistem adalah apa yang keluar daripada strerror(2), ditambah dengan simbol ralat. Tidak sabar dan
sysadmin pakar boleh berhenti membaca pada ketika ini, tetapi pengalaman penulis setakat ini
bahawa membaca lebih lanjut adalah berfaedah. (Jika ia tidak memberi ganjaran, ia mungkin kawasan
libexplain yang boleh diperbaiki. Sumbangan kod dialu-alukan, sudah tentu.)

selepas Kerana
Ini ialah bahagian mesej ralat yang ditujukan kepada pengguna bukan teknikal. Ia kelihatan di luar
argumen panggilan sistem yang mudah, dan mencari sesuatu yang lebih khusus.
tiada direktori "beberapa" dalam direktori semasa
Bahagian ini cuba menerangkan punca proksimal ralat dalam bahasa biasa, dan ia
di sinilah pengantarabangsaan adalah penting.

Secara umum, dasar ini adalah untuk memasukkan seberapa banyak maklumat yang mungkin, supaya pengguna
tidak perlu pergi mencarinya (dan tidak meninggalkannya daripada laporan pepijat).

Pengantarabangsaan
Kebanyakan mesej ralat dalam perpustakaan libexplain telah diantarabangsakan. di sana
masih belum ada penyetempatan, jadi jika anda mahukan penjelasan dalam bahasa ibunda anda,
sila menyumbang.

Kelayakan "sebahagian besar", di atas, berkaitan dengan fakta bahawa bukti-konsep
pelaksanaan tidak termasuk sokongan pengantarabangsaan. Pangkalan kod adalah sedang
disemak secara progresif, biasanya hasil daripada pemfaktoran semula mesej supaya setiap ralat
rentetan mesej muncul dalam kod tepat sekali.

Peruntukan telah dibuat untuk bahasa yang perlu mengumpulkan bahagian
panggilan sistem gagal, ralat sistem kerana penerangan
dalam susunan yang berbeza untuk tatabahasa yang betul dalam mesej ralat setempat.

Postmortem
Ada kalanya program masih belum menggunakan libexplain, dan anda tidak boleh menggunakannya helai(1)
sama ada. Ada satu menjelaskan(1) arahan disertakan dengan libexplain yang boleh digunakan untuk
mentafsir mesej ralat, jika keadaan sistem asas tidak terlalu banyak berubah.
$ menjelaskan menamakan semula foo /tmp/bar/baz -e ENOENT
rename(oldpath = "foo", newpath = "/tmp/bar/baz") gagal, Tiada fail atau direktori sedemikian
(2, ENOENT) kerana tiada direktori "bar" dalam newpath "/ tmp"direktori
$
Perhatikan cara kekaburan laluan diselesaikan dengan menggunakan nama argumen panggilan sistem. Daripada
Sudah tentu, anda perlu mengetahui ralat dan panggilan sistem menjelaskan(1) menjadi berguna. Sebagai sebuah
Selain itu, ini adalah salah satu cara yang digunakan oleh suite ujian automatik libexplain untuk mengesahkannya
libexplain berfungsi.

Falsafah
“Beritahu saya segala-galanya, termasuk perkara yang saya tidak tahu untuk mencari.”

Perpustakaan dilaksanakan dalam cara yang apabila dipautkan secara statik, hanya kod anda
sebenarnya penggunaan akan dipautkan. Ini dicapai dengan mempunyai satu fungsi setiap fail sumber,
bila-bila boleh.

Apabila mungkin untuk membekalkan lebih banyak maklumat, libexplain akan berbuat demikian. Semakin kurang pengguna
perlu menjejaki sendiri, lebih baik. Ini bermakna bahawa UID disertakan dengan
nama pengguna, GID disertakan dengan nama kumpulan, PID disertakan dengan proses
nama, deskriptor fail dan aliran disertakan dengan nama laluan, dan lain-lain.

Apabila menyelesaikan laluan, jika komponen laluan tidak wujud, libexplain akan mencari yang serupa
nama, untuk mencadangkan alternatif untuk kesilapan tipografi.

Pustaka libexplain cuba menggunakan timbunan sesedikit mungkin, dan biasanya tiada. Ini adalah
untuk mengelak mengganggu keadaan proses, sejauh mungkin, walaupun kadangkala ia berlaku
tidak dapat dielakkan.

Pustaka libexplain cuba untuk menjadi thread selamat, dengan mengelakkan pembolehubah global, menyimpan
nyatakan pada timbunan sebanyak mungkin. Terdapat satu penimbal mesej biasa, dan
fungsi yang menggunakannya didokumenkan sebagai tidak selamat untuk benang.

Pustaka libexplain tidak mengganggu pengendali isyarat proses. Ini menjadikan
menentukan sama ada penunjuk akan segfault cabaran, tetapi tidak mustahil.

Apabila maklumat tersedia melalui panggilan sistem serta tersedia melalui a / proc
kemasukan, panggilan sistem lebih disukai. Ini adalah untuk mengelak daripada mengganggu keadaan proses.
Terdapat juga masa apabila tiada deskriptor fail tersedia.

Pustaka libexplain disusun dengan sokongan fail yang besar. Tidak ada yang besar/kecil
skizofrenia. Apabila ini menjejaskan jenis hujah dalam API, dan ralat akan dikeluarkan
jika takrifan fail besar yang diperlukan tiada.

FIXME: Kerja diperlukan untuk memastikan kuota sistem fail dikendalikan dalam kod. ini
terpakai kepada sesetengah orang getrlimit(2) sempadan, juga.

Terdapat kes apabila laluan saudara tidak bermaklumat. Contohnya: daemon sistem,
pelayan dan proses latar belakang. Dalam kes ini, laluan mutlak digunakan dalam ralat
penjelasan.

PATH RESOLUSI


Versi pendek: lihat penyelesaian_laluan(7).

Versi panjang: Kebanyakan pengguna tidak pernah mendengarnya penyelesaian_laluan(7), dan ramai pengguna lanjutan
tidak pernah membacanya. Berikut ialah versi beranotasi:

Langkah 1: Start of yang resolusi proses
Jika nama laluan bermula dengan aksara slash (“/”), direktori carian permulaan ialah
direktori akar proses panggilan.

Jika nama laluan tidak bermula dengan aksara slash(“/”), carian permulaan
direktori proses resolusi ialah direktori kerja semasa proses tersebut.

Langkah 2: Berjalan bersama-sama yang jalan
Tetapkan direktori carian semasa kepada direktori carian permulaan. Sekarang, bagi setiap bukan
komponen akhir nama laluan, di mana komponen ialah subrentetan yang dibatasi oleh garis miring (“/”)
aksara, komponen ini dicari dalam direktori carian semasa.

Jika proses itu tidak mempunyai kebenaran carian pada direktori carian semasa, EACCES
ralat dikembalikan ("Kebenaran ditolak").
open(pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) gagal,
Kebenaran dinafikan (13, EACCES) kerana proses itu tidak mempunyai kebenaran carian
ke direktori "/home/archives/.ssh" nama laluan, proses berkesan GID 1000
"pmiller" tidak sepadan dengan pemilik direktori 1001 "arkib" jadi pemilik
mod kebenaran "rwx" diabaikan, mod kebenaran yang lain ialah "---", dan mod kebenaran
proses tidak mempunyai keistimewaan (tidak mempunyai keupayaan DAC_READ_SEARCH)

Jika komponen tidak ditemui, ralat ENOENT dikembalikan ("Tiada fail atau direktori sedemikian").
nyahpaut(nama laluan = "/home/microsoft/rubbish") gagal, Tiada fail atau direktori sedemikian (2,
ENOENT) kerana tiada direktori "microsoft" dalam nama laluan "/ home"direktori

Terdapat juga beberapa sokongan untuk pengguna apabila mereka salah menaip nama laluan, membuat cadangan apabila
ENOENT dikembalikan:
open(pathname = "/user/include/fcntl.h", flags = O_RDONLY) gagal, Tiada fail atau
direktori (2, ENOENT) kerana tiada direktori "pengguna" dalam nama laluan "/"
direktori, adakah anda maksudkan direktori "usr" sebaliknya?

Jika komponen ditemui, tetapi bukan direktori mahupun pautan simbolik, ENOTDIR
ralat dikembalikan ("Bukan direktori").
open(pathname = "/home/pmiller/.netrc/lca", flags = O_RDONLY) gagal, Bukan a
direktori (20, ENOTDIR) kerana fail biasa ".netrc" dalam nama laluan
Direktori "/home/pmiller" sedang digunakan sebagai direktori apabila tidak

Jika komponen ditemui dan merupakan direktori, kami menetapkan direktori carian semasa kepadanya
direktori, dan pergi ke komponen seterusnya.

Jika komponen ditemui dan merupakan pautan simbolik (symlink), kami terlebih dahulu menyelesaikan simbolik ini
pautan (dengan direktori carian semasa sebagai direktori carian permulaan). Atas kesilapan, itu
ralat dikembalikan. Jika hasilnya bukan direktori, ralat ENOTDIR dikembalikan.
nyahpaut(nama laluan = "/tmp/dangling/rubbish") gagal, Tiada fail atau direktori sedemikian (2,
ENOENT) kerana pautan simbolik "berjuntai" dalam nama laluan "/ tmp"direktori
merujuk kepada "tiada tempat" yang tidak wujud
Jika resolusi symlink berjaya dan mengembalikan direktori, kami menetapkan arus
cari direktori ke direktori itu, dan pergi ke komponen seterusnya. Perhatikan bahawa
proses penyelesaian di sini melibatkan rekursi. Untuk melindungi kernel daripada timbunan
limpahan, dan juga untuk melindungi daripada penafian perkhidmatan, terdapat had maksimum
kedalaman rekursi, dan pada bilangan maksimum pautan simbolik yang diikuti. Ralat ELOOP ialah
dikembalikan apabila melebihi maksimum ("Terlalu banyak peringkat pautan simbolik").
open(pathname = "/tmp/dangling", flags = O_RDONLY) gagal, Terlalu banyak tahap
pautan simbolik (40, ELOOP) kerana gelung pautan simbolik ditemui dalam
nama laluan, bermula pada "/tmp/dangling"
Ia juga mungkin untuk mendapatkan ralat ELOOP atau EMLINK jika terdapat terlalu banyak symlink, tetapi tiada
gelung telah dikesan.
open(pathname = "/tmp/rabbit‐hole", flags = O_RDONLY) gagal, Terlalu banyak peringkat
pautan simbolik (40, ELOOP) kerana terlalu banyak pautan simbolik ditemui dalam
nama laluan (8)
Perhatikan bagaimana had sebenar juga dicetak.

Langkah 3: Cari yang akhir kemasukan
Carian komponen akhir nama laluan berjalan sama seperti yang lain
komponen, seperti yang diterangkan dalam langkah sebelumnya, dengan dua perbezaan:

(i) Komponen akhir tidak semestinya direktori (sekurang-kurangnya sejauh resolusi laluan
proses berkenaan. Ia mungkin perlu menjadi direktori, atau bukan direktori, kerana
keperluan panggilan sistem tertentu).

(Ii)
Ia tidak semestinya ralat jika komponen akhir tidak dijumpai; mungkin kita hanya
menciptanya. Butiran mengenai rawatan kemasukan akhir diterangkan dalam
halaman manual bagi panggilan sistem tertentu.

(iii)
Ia juga mungkin mempunyai masalah dengan komponen terakhir jika ia adalah pautan simbolik
dan ia tidak sepatutnya diikuti. Sebagai contoh, menggunakan membuka(2) O_NOFOLLOW bendera:
open(pathname = "a‐symlink", flags = O_RDONLY | O_NOFOLLOW) gagal, Terlalu banyak tahap
pautan simbolik (ELOOP) kerana O_NOFOLLOW telah ditentukan tetapi nama laluan merujuk kepada a
pautan simbolik

(iv)
Ia adalah perkara biasa bagi pengguna untuk membuat kesilapan semasa menaip nama laluan. Perpustakaan libexplain
cuba membuat cadangan apabila ENOENT dikembalikan, sebagai contoh:
open(pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) gagal, Tiada fail atau
direktori (2, ENOENT) kerana tiada fail biasa "filecontrl.h" dalam nama laluan
"/ usr / sertakan" direktori, adakah anda maksudkan fail biasa "fcntl.h" sebaliknya?

(v) Mungkin juga komponen akhir dikehendaki menjadi sesuatu selain daripada a
fail biasa:
pautan baca(nama laluan = "hanya-a-fail", data = 0x7F930A50, saiz_data = 4097) gagal,
Argumen tidak sah (22, EINVAL) kerana nama laluan ialah fail biasa, bukan pautan simbolik

(vi)
FIXME: pengendalian bit "t".

Batas
Terdapat beberapa had yang berkaitan dengan nama laluan dan nama fail.

Had panjang nama laluan
Terdapat panjang maksimum untuk nama laluan. Jika nama laluan (atau beberapa perantaraan
nama laluan yang diperoleh semasa menyelesaikan pautan simbolik) terlalu panjang, ENAMETOOLONG
ralat dikembalikan ("Nama fail terlalu panjang"). Perhatikan bagaimana had sistem disertakan
dalam mesej ralat.
buka(nama laluan = "sangat panjang", bendera = O_RDONLY) gagal, Nama fail terlalu panjang (36,
ENAMETOOLONG) kerana nama laluan melebihi panjang laluan maksimum sistem (4096)

Had panjang nama fail
Sesetengah varian Unix mempunyai had pada bilangan bait dalam setiap komponen laluan.
Sesetengah daripada mereka menangani perkara ini secara senyap, dan ada yang memberikan ENAMETOOLONG; libexplain itu
kegunaan perpustakaan pathconf(3) _PC_NO_TRUNC untuk memberitahu yang mana. Jika ralat ini berlaku,
perpustakaan libexplain akan menyatakan had dalam mesej ralat, hadnya ialah
diperoleh daripada pathconf(3) _PC_NAME_MAX. Perhatikan bagaimana had sistem disertakan
dalam mesej ralat.
buka(nama laluan = "system7/hanya-ada-14-aksara", bendera = O_RDONLY) gagal, Fail
nama terlalu panjang (36, ENAMETOOLONG) kerana komponen "hanya-ada-14-aksara" ialah
lebih lama daripada had sistem (14)

Nama laluan kosong
Dalam Unix asal, nama laluan kosong merujuk kepada direktori semasa.
Pada masa kini POSIX menetapkan bahawa nama laluan kosong tidak boleh diselesaikan dengan jayanya.
open(pathname = "", flags = O_RDONLY) gagal, Tiada fail atau direktori sedemikian (2,
ENOENT) kerana POSIX menetapkan bahawa nama laluan kosong tidak boleh diselesaikan
berjaya

Kebenaran
Bit kebenaran fail terdiri daripada tiga kumpulan tiga bit. Kumpulan pertama
tiga digunakan apabila ID pengguna yang berkesan bagi proses panggilan sama dengan ID pemilik bagi
fail. Kumpulan kedua daripada tiga digunakan apabila ID kumpulan fail sama ada sama dengan
ID kumpulan yang berkesan bagi proses panggilan, atau merupakan salah satu ID kumpulan tambahan bagi
proses memanggil. Apabila kedua-duanya tidak dipegang, kumpulan ketiga digunakan.
buka(nama laluan = "/ etc / passwd", bendera = O_WRONLY) gagal, Kebenaran ditolak (13,
EACCES) kerana proses itu tidak mempunyai kebenaran menulis kepada biasa "passwd".
fail dalam nama laluan "/ Etc" direktori, proses berkesan UID 1000 "pmiller"
tidak sepadan dengan pemilik fail biasa 0 "root" jadi mod kebenaran pemilik "rw-"
diabaikan, mod kebenaran yang lain ialah "r--", dan prosesnya tidak mempunyai keistimewaan
(tidak mempunyai keupayaan DAC_OVERRIDE)
Beberapa ruang yang besar diberikan kepada penjelasan ini, kerana kebanyakan pengguna tidak mengetahui bahawa ini
ialah cara sistem kebenaran berfungsi. Khususnya: pemilik, kumpulan dan lain-lain
kebenaran adalah eksklusif, ia tidak "ATAU" bersama-sama.

KETAT DAN MENARIK SISTEM PANGGILAN


Proses menulis pengendali ralat khusus untuk setiap panggilan sistem sering didedahkan
kebiasaan dan keadaan sempadan yang menarik, atau kabur salah(3) nilai.

ENOMEDIUM, Tidak sederhana ditemui
Tindakan menyalin CD adalah sumber tajuk untuk kertas ini.
$ dd jika=/dev/cdrom daripada=fubar.iso
dd: membuka “/dev/cdrom”: Tiada medium ditemui
$
Penulis tertanya-tanya mengapa komputernya memberitahunya bahawa tiada perkara seperti psikik
sederhana. Agak selain daripada fakta bahawa sejumlah besar penutur asli bahasa Inggeris tidak
walaupun sedar bahawa "media" adalah jamak, apatah lagi "medium" adalah tunggalnya, rentetan
dikembalikan oleh strerror(3) untuk ENOMEDIUM sangat ringkas sehingga hampir bebas sepenuhnya
kandungan.

Bila membuka(2) mengembalikan ENOMEDIUM alangkah baiknya jika perpustakaan libexplain dapat mengembangkan a
sedikit tentang ini, berdasarkan jenis pemacunya. Sebagai contoh:
... kerana tiada cakera dalam pemacu liut
... kerana tiada cakera dalam pemacu CD‐ROM
... kerana tiada pita dalam pemacu pita
... kerana tiada memory stick dalam pembaca kad

Dan jadilah...
open(pathname = "/dev/cdrom", flags = O_RDONLY) gagal, Tiada medium ditemui (123,
ENOMEDIUM) kerana nampaknya tiada cakera dalam pemacu CD-ROM
Caranya, yang sebelum ini tidak diketahui oleh pengarang, adalah dengan membuka peranti menggunakan
Bendera O_NONBLOCK, yang membolehkan anda membuka pemacu tanpa medium di dalamnya. Anda kemudian
mengeluarkan peranti khusus ioctls(2) meminta sehingga anda mengetahui apa sebenarnya itu. (bukan
pasti jika ini POSIX, tetapi ia juga nampaknya berfungsi seperti itu di BSD dan Solaris, menurut
yang wodim(1) sumber.)

Perhatikan juga penggunaan "cakera" dan "cakera" yang berbeza dalam konteks. Piawaian CD berasal
di Perancis, tetapi semua yang lain mempunyai "k".

EFAULT, Buruk alamat
Sebarang panggilan sistem yang mengambil hujah penunjuk boleh mengembalikan EFAULT. Perpustakaan libexplain
boleh mengetahui hujah mana yang salah, dan ia melakukannya tanpa mengganggu proses
(atau benang) pengendalian isyarat.

Apabila tersedia, mincore(2) panggilan sistem digunakan, untuk bertanya sama ada kawasan memori adalah sah.
Ia boleh mengembalikan tiga hasil: dipetakan tetapi tidak dalam ingatan fizikal, dipetakan dan dalam fizikal
ingatan, dan tidak dipetakan. Apabila menguji kesahihan penunjuk, dua yang pertama ialah "ya"
dan yang terakhir ialah "tidak".

Menyemak rentetan C adalah lebih sukar, kerana bukannya penunjuk dan saiz, kita sahaja
mempunyai penunjuk. Untuk menentukan saiz kita perlu mencari NUL, dan itu boleh
segfault, tangkap‐22.

Untuk mengatasinya, perpustakaan libexplain menggunakan lstat(2) panggilan sysem (dengan yang dikenali
hujah kedua yang baik) untuk menguji rentetan C untuk kesahihan. Pemulangan kegagalan && errno == EFAULT
ialah "tidak", dan apa-apa lagi ialah "ya". Ini, sudah tentu mengehadkan rentetan kepada PATH_MAX
aksara, tetapi itu biasanya tidak menjadi masalah untuk perpustakaan libexplain, kerana itu
hampir selalu tali terpanjang yang penting.

EMFILE, Terlalu banyak membuka fail
Ralat ini berlaku apabila proses sudah mempunyai bilangan maksimum deskriptor fail terbuka.
Jika had sebenar hendak dicetak, dan perpustakaan libexplain cuba melakukannya, anda tidak boleh membukanya
fail dalam / proc untuk membaca apa itu.
open_max = sysconf(_SC_OPEN_MAX);
Yang ini tidak begitu sukar, ada sysconf(3) cara mendapatkan had.

ENFILE, Terlalu banyak membuka fail in sistem
Ralat ini berlaku apabila had sistem pada jumlah bilangan fail terbuka telah
dicapai. Dalam kes ini tidak ada yang berguna sysconf(3) cara mendapatkan had.

Menggali lebih dalam, seseorang mungkin mendapati bahawa di Linux terdapat a / proc entri yang boleh kita baca
mendapatkan nilai ini. Catch‐22: kami kehabisan deskriptor fail, jadi kami tidak boleh membuka fail ke
baca hadnya.

Di Linux terdapat panggilan sistem untuk mendapatkannya, tetapi ia tidak mempunyai fungsi pembungkus [e]glibc, jadi
anda perlu melakukannya dengan berhati-hati:
lama
explain_maxfile(void)
{
#ifdef __linux__
struct __sysctl_args args;
int32_t maxfile;
size_t maxfile_size = saiz(maxfile);
nama int[] = { CTL_FS, FS_MAXFILE };
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = nama;
args.nlen = 2;
args.oldval = &maxfile;
args.oldlenp = &maxfile_size;
if (syscall(SYS__sysctl, &args) >= 0)
kembalikan maxfile;
#endif
pulangan -1;
}
Ini membenarkan had untuk disertakan dalam mesej ralat, apabila tersedia.

EINVAL “Tidak sah hujah” vs ENOSYS “Fungsi tidak dilaksanakan"
Tindakan yang tidak disokong (seperti pautan simbol(2) pada sistem fail FAT) tidak dilaporkan
secara konsisten dari satu panggilan sistem ke panggilan seterusnya. Ia adalah mungkin untuk mempunyai sama ada EINVAL atau
ENOSYS kembali.

Akibatnya, perhatian mesti diberikan kepada kes ralat ini untuk membetulkannya, terutamanya
kerana EINVAL juga boleh merujuk kepada masalah dengan satu atau lebih argumen panggilan sistem.

Nota Bahawa salah(3) is tidak sentiasa menetapkan
Ada kalanya perlu membaca sumber [e]glibc untuk menentukan cara dan
apabila ralat dikembalikan untuk beberapa panggilan sistem.

feof(3), failno(3)
Selalunya diandaikan bahawa fungsi ini tidak dapat mengembalikan ralat. Ini hanya benar jika
yang aliran hujah adalah sah, namun mereka mampu mengesan yang tidak sah
penunjuk.

fpathconf(3), pathconf(3)
Nilai pulangan sebanyak fpathconf(2) dan pathconf(2) boleh menjadi -1 secara sah, jadi begitu
perlu untuk melihat jika salah(3) telah ditetapkan dengan jelas.

ioctls(2)
Nilai pulangan sebanyak ioctls(2) boleh menjadi -1 secara sah, jadi adalah perlu untuk melihat sama ada
salah(3) telah ditetapkan dengan jelas.

readdir(3)
Nilai pulangan sebanyak readdir(3) adalah NULL untuk kedua-dua ralat dan akhir fail. Ia adalah
perlu untuk melihat jika salah(3) telah ditetapkan dengan jelas.

setbuf(3), setbuffer(3), setlinebuf(3), setvbuf(3)
Semua kecuali fungsi terakhir ini kembali tidak sah. Dan setvbuf(3) hanya didokumenkan sebagai
mengembalikan "bukan sifar" apabila ralat. Ia adalah perlu untuk melihat jika salah(3) telah jelas
ditetapkan.

strtod(3), strtol(3), strtold(3), berjalan kaki(3), strtoul(3), strtoull(3)
Fungsi ini mengembalikan 0 apabila ralat, tetapi itu juga merupakan nilai pulangan yang sah. Ia adalah
perlu untuk melihat jika salah(3) telah ditetapkan dengan jelas.

ungetc(3)
Walaupun hanya satu aksara sandaran yang diberi mandat oleh standard ANSI C, ia bertukar
bahawa [e]glibc membenarkan lebih banyak lagi... tetapi ini bermakna ia boleh gagal dengan ENOMEM. Ia boleh
juga gagal dengan EBADF jika fp adalah palsu. Paling sukar, jika anda lulus EOF ralat
pulangan berlaku, tetapi errno tidak ditetapkan.

Pustaka libexplain mengesan semua ralat ini dengan betul, walaupun dalam kes di mana fail
nilai ralat tidak didokumenkan dengan baik, jika ada.

ENOSPC, Tidak ruang kiri on peranti
Apabila ralat ini merujuk kepada fail pada sistem fail, perpustakaan libexplain mencetak pelekap
titik sistem fail dengan masalah. Ini boleh menjadikan punca ralat banyak
lebih jelas.
write(fildes = 1 "contoh", data = 0xbfff2340, data_size = 5) gagal, Tiada ruang yang tinggal
pada peranti (28, ENOSPC) kerana sistem fail yang mengandungi fail ("/ home") tidak mempunyai
lebih banyak ruang untuk data
Memandangkan lebih banyak sokongan peranti khas ditambahkan, mesej ralat dijangka menyertakan peranti itu
nama dan saiz sebenar peranti.

EROFS, Baca sahaja fail sistem
Apabila ralat ini merujuk kepada fail pada sistem fail, perpustakaan libexplain mencetak pelekap
titik sistem fail dengan masalah. Ini boleh menjadikan punca ralat banyak
lebih jelas.

Memandangkan lebih banyak sokongan peranti khas ditambahkan, mesej ralat dijangka menyertakan peranti itu
nama dan jenis.
open(pathname = "/dev/fd0", O_RDWR, 0666) gagal, Sistem fail baca sahaja (30, EROFS)
kerana cakera liut mempunyai set tab perlindungan tulis

...kerana CD‐ROM tidak boleh ditulis
... kerana kad memori mempunyai set tab perlindungan tulis
...kerana pita magnetik ½ inci tidak mempunyai gelang tulis

menamakan semula
. menamakan semula(2) panggilan sistem digunakan untuk menukar lokasi atau nama fail, mengalihkannya
antara direktori jika diperlukan. Jika nama laluan destinasi sudah wujud ia akan menjadi
digantikan secara atom, supaya tidak ada gunanya proses lain cuba melakukannya
akses ia akan mendapati ia hilang.

Walau bagaimanapun, terdapat had: anda hanya boleh menamakan semula direktori di atas direktori lain
direktori jika direktori destinasi tidak kosong.
rename(oldpath = "foo", newpath = "bar") gagal, Direktori tidak kosong (39,
ENOTEMPTY) kerana newpath bukan direktori kosong; iaitu ia mengandungi entri
Selain itu "." dan ".."
Anda juga tidak boleh menamakan semula direktori di atas bukan direktori.
rename(oldpath = "foo", newpath = "bar") gagal, Bukan direktori (20, ENOTDIR)
kerana oldpath ialah direktori, tetapi newpath ialah fail biasa, bukan direktori
Dan sebaliknya tidak dibenarkan
rename(oldpath = "foo", newpath = "bar") gagal, Adakah direktori (21, EISDIR)
kerana newpath ialah direktori, tetapi oldpath ialah fail biasa, bukan direktori

Ini, sudah tentu, menjadikan tugas perpustakaan libexplain lebih rumit, kerana
nyahpaut(2) atau ialah rm(2) panggilan sistem dipanggil secara tersirat oleh menamakan semula(2), dan seterusnya semua
nyahpaut(2) atau ialah rm(2) ralat mesti dikesan dan dikendalikan, juga.

dup2
. dup2(2) panggilan sistem digunakan untuk mencipta deskriptor fail kedua yang merujuk kepada
objek yang sama seperti deskriptor fail pertama. Biasanya ini digunakan untuk melaksanakan input shell
dan pengalihan keluaran.

Perkara yang menyeronokkan ialah, sama seperti menamakan semula(2) boleh menamakan semula fail secara atom di atas fail
fail sedia ada dan keluarkan fail lama, dup2(2) boleh melakukan ini pada fail yang sudah terbuka
deskriptor.

Sekali lagi, ini menjadikan tugas perpustakaan libexplain lebih rumit, kerana rapat(2)
panggilan sistem dipanggil secara tersirat oleh dup2(2), dan seterusnya semua rapat(2) kesilapan mestilah
dikesan dan dikendalikan, juga.

KELEBIHAN IN IOCTL PERTANYAAN


. ioctls(2) panggilan sistem menyediakan pengarang pemacu peranti cara untuk berkomunikasi dengannya
ruang pengguna yang tidak sesuai dalam API kernel sedia ada. Lihat ioctl_list(2).

Mentafsirkan Meminta nombor
Dari pandangan sepintas lalu pada ioctls(2) antara muka, nampaknya ada yang besar tetapi terhingga
bilangan yang mungkin ioctls(2) permintaan. Masing-masing berbeza ioctls(2) permintaan adalah berkesan
panggilan sistem lain, tetapi tanpa sebarang jenis-keselamatan sama sekali - pengkompil tidak dapat membantu a
pengaturcara mendapatkan hak ini. Ini mungkin motivasi di belakang tcflush(3) dan
kawan-kawan.

Tanggapan awal ialah anda boleh menyahkod ioctls(2) permintaan menggunakan suis besar
kenyataan. Ini ternyata tidak dapat dilaksanakan kerana seseorang dengan cepat mendapati bahawa ia adalah
mustahil untuk memasukkan semua pengepala sistem yang diperlukan yang mentakrifkan pelbagai ioctls(2)
permintaan, kerana mereka mempunyai masa yang sukar untuk bermain dengan baik antara satu sama lain.

Pandangan yang lebih mendalam mendedahkan bahawa terdapat julat nombor permintaan dan peranti "peribadi".
pengarang pemandu digalakkan untuk menggunakannya. Ini bermakna terdapat kemungkinan yang jauh lebih besar
set permintaan, dengan nombor permintaan yang samar-samar, daripada yang kelihatan serta-merta. Juga,
terdapat beberapa kekaburan sejarah juga.

Kami sudah tahu bahawa suis itu tidak praktikal, tetapi kini kami tahu bahawa untuk memilih
nama permintaan yang sesuai dan penjelasan kita mesti mempertimbangkan bukan sahaja nombor permintaan tetapi
juga deskriptor fail.

Pelaksanaan ioctls(2) sokongan dalam perpustakaan libexplain adalah untuk mempunyai jadual
petunjuk kepada ioctls(2) deskriptor permintaan. Setiap deskriptor ini termasuk pilihan
penunjuk kepada fungsi nyahkekaburan.

Setiap permintaan sebenarnya dilaksanakan dalam fail sumber yang berasingan, supaya yang diperlukan
sertakan fail dilepaskan daripada kewajipan untuk bermain dengan baik dengan orang lain.

Perwakilan
Falsafah di sebalik perpustakaan libexplain adalah untuk menyediakan maklumat sebanyak
mungkin, termasuk perwakilan tepat bagi panggilan sistem. Dalam kes
ioctls(2) ini bermakna mencetak nombor permintaan yang betul (mengikut nama) dan juga nombor yang betul (atau
sekurang-kurangnya berguna) perwakilan hujah ketiga.

. ioctls(2) prototaip kelihatan seperti ini:
int ioctl(int fildes, int request, ...);
yang sepatutnya mempunyai penggera keselamatan jenis anda berbunyi. Dalaman ke [e]glibc, ini dihidupkan
ke dalam pelbagai bentuk:
int __ioctl(int fildes, int request, long arg);
int __ioctl(int fildes, int request, void *arg);
dan antara muka syscall kernel Linux menjangkakan
asmlinkage long sys_ioctl(unsigned int fildes, unsigned int request, unsigned long
arg);
Kebolehubahan melampau bagi hujah ketiga adalah satu cabaran, apabila perpustakaan libexplain
cuba mencetak representasi hujah ketiga itu. Walau bagaimanapun, apabila nombor permintaan
telah dinyahkekaburan, setiap entri dalam jadual ioctl perpustakaan libexplain mempunyai a
fungsi print_data tersuai (OO dilakukan secara manual).

Penjelasan
Terdapat lebih sedikit masalah dalam menentukan penjelasan yang akan digunakan. Setelah nombor permintaan
telah dinyahkekaburan, setiap entri dalam jadual ioctl perpustakaan libexplain mempunyai tersuai
fungsi print_explanation (sekali lagi, OO dilakukan secara manual).

Tidak seperti panggilan sistem seksyen 2 dan seksyen 3, kebanyakannya ioctls(2) permintaan tidak mempunyai ralat
didokumenkan. Ini bermakna, untuk memberikan penerangan ralat yang baik, perlu membaca kernel
sumber untuk ditemui

· apa salah(3) nilai boleh dikembalikan, dan

· punca setiap kesilapan.

Kerana sifat OO fungsi penghantaran panggilan dengan kernel, anda perlu membaca
semua sumber yang melaksanakannya ioctls(2) permintaan, bukan hanya pelaksanaan generik. Ia
adalah dijangkakan bahawa kernel yang berbeza akan mempunyai nombor ralat yang berbeza dan secara halus
punca ralat yang berbeza.

EINVAL vs ENOTTY
Keadaan lebih teruk lagi ioctls(2) permintaan daripada untuk panggilan sistem, dengan EINVAL dan
ENOTTY kedua-duanya digunakan untuk menunjukkan bahawa an ioctls(2) permintaan adalah tidak sesuai dalam hal itu
konteks, dan kadangkala ENOSYS, ENOTSUP dan EOPNOTSUPP (bermaksud untuk digunakan untuk soket) sebagai
baiklah. Terdapat ulasan dalam sumber kernel Linux yang nampaknya menunjukkan progresif
pembersihan sedang dijalankan. Untuk kekacauan tambahan, BSD menambah ENOIOCTL kepada kekeliruan.

Akibatnya, perhatian mesti diberikan kepada kes ralat ini untuk membetulkannya, terutamanya
kerana EINVAL juga boleh merujuk kepada masalah dengan satu atau lebih argumen panggilan sistem.

inpttr_t
Piawaian C99 mentakrifkan jenis integer yang dijamin boleh memegang sebarang penunjuk
tanpa kehilangan perwakilan.

Prototaip syscall fungsi di atas akan ditulis dengan lebih baik
sys_ioctl panjang(unsigned int fildes, unsigned int request, intptr_t arg);
Masalahnya ialah percanggahan kognitif yang disebabkan oleh khusus peranti atau khusus sistem fail.
ioctls(2) pelaksanaan, seperti:
vfs_ioctl panjang(fail struct *filp, unsigned int cmd, unsigned long arg);
Majoriti ioctls(2) permintaan sebenarnya mempunyai int *arg hujah ketiga. Tetapi memilikinya
diisytiharkan panjang membawa kepada kod yang merawat ini selama *arg. Ini tidak berbahaya pada 32-bit
(sizeof(long) == sizeof(int)) tetapi jahat pada 64‐bit (sizeof(long) != sizeof(int)).
Bergantung pada endian-ness, anda mendapat atau tidak mendapat nilai yang anda harapkan, tetapi anda sentiasa mendapatkan
coretan ingatan atau coretan tindanan juga.

Menulis semua ini sebagai
int ioctl(int fildes, int request, ...);
int __ioctl(int fildes, int request, intptr_t arg);
sys_ioctl panjang(unsigned int fildes, unsigned int request, intptr_t arg);
vfs_ioctl panjang(fail struct *filp, unsigned int cmd, intptr_t arg);
menekankan bahawa integer hanyalah integer untuk mewakili kuantiti yang hampir
sentiasa jenis penunjuk yang tidak berkaitan.

KESIMPULAN


Gunakan libexplain, pengguna anda akan menyukainya.

HAKCIPTA


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

Gunakan explain_lca2010 dalam talian menggunakan perkhidmatan onworks.net


Pelayan & Stesen Kerja Percuma

Muat turun apl Windows & Linux

  • 1
    SWIG
    SWIG
    SWIG ialah alat pembangunan perisian
    yang menghubungkan atur cara yang ditulis dalam C dan
    C++ dengan pelbagai peringkat tinggi
    bahasa pengaturcaraan. SWIG digunakan dengan
    berbeza...
    Muat turun SWIG
  • 2
    Tema WooCommerce Nextjs React
    Tema WooCommerce Nextjs React
    Tema WooCommerce React, dibina dengan
    Seterusnya JS, Webpack, Babel, Node dan
    Ekspres, menggunakan GraphQL dan Apollo
    Pelanggan. Kedai WooCommerce dalam React(
    mengandungi: Produk...
    Muat turun Tema WooCommerce Nextjs React
  • 3
    archlabs_repo
    archlabs_repo
    Repo pakej untuk ArchLabs Ini adalah
    aplikasi yang juga boleh diambil
    dari
    https://sourceforge.net/projects/archlabs-repo/.
    Ia telah dihoskan dalam OnWorks di...
    Muat turun archlabs_repo
  • 4
    Projek Zephyr
    Projek Zephyr
    Projek Zephyr ialah generasi baharu
    sistem pengendalian masa nyata (RTOS) yang
    menyokong pelbagai perkakasan
    seni bina. Ia berdasarkan a
    inti tapak kecil...
    Muat turun Projek Zephyr
  • 5
    SCON
    SCON
    SCons ialah alat pembinaan perisian
    itu adalah alternatif yang lebih baik daripada
    alat binaan klasik "Buat" yang
    kita semua tahu dan suka. SCons ialah
    melaksanakan...
    Muat turun SCons
  • 6
    PSeInt
    PSeInt
    PSeInt ialah penterjemah kod pseudo untuk
    pelajar pengaturcaraan berbahasa Sepanyol.
    Tujuan utamanya adalah untuk menjadi alat untuk
    mempelajari dan memahami asas
    konsep...
    Muat turun PSeInt
  • Lebih »

Arahan Linux

Ad