ນີ້ແມ່ນຄໍາສັ່ງອະທິບາຍ_lca2010 ທີ່ສາມາດດໍາເນີນການໄດ້ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີໂດຍໃຊ້ຫນຶ່ງໃນຫຼາຍໆບ່ອນເຮັດວຽກອອນໄລນ໌ຂອງພວກເຮົາເຊັ່ນ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator
ໂຄງການ:
NAME
explain_lca2010 - ບໍ່ພົບສື່ກາງ: ເມື່ອເຖິງເວລາຢຸດພະຍາຍາມອ່ານ ຄວາມຜິດພາດ(3) ຂອງ
ຈິດໃຈ.
ແຮງຈູງໃຈ
ແນວຄວາມຄິດສໍາລັບ libexplain ເກີດຂຶ້ນກັບຂ້ອຍໃນຕົ້ນຊຸມປີ 1980. ທຸກຄັ້ງທີ່ລະບົບໂທ
ສົ່ງຄືນຂໍ້ຜິດພາດ, kernel ຮູ້ສິ່ງທີ່ຜິດພາດ ... ແລະບີບອັດມັນເຂົ້າໄປໃນ
ຫນ້ອຍກວ່າ 8 bits ຂອງ ຜິດພາດ. ພື້ນທີ່ຜູ້ໃຊ້ມີການເຂົ້າເຖິງຂໍ້ມູນດຽວກັນກັບ kernel, ມັນ
ຄວນຈະເປັນໄປໄດ້ສໍາລັບພື້ນທີ່ຜູ້ໃຊ້ທີ່ຈະຄິດອອກຢ່າງແທ້ຈິງສິ່ງທີ່ເກີດຂຶ້ນເພື່ອ provoke ຄວາມຜິດພາດ
ກັບຄືນ, ແລະໃຊ້ນີ້ເພື່ອຂຽນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ດີ.
ມັນອາດຈະເປັນແບບງ່າຍໆບໍ?
Error ຂໍ້ຄວາມ as ຄວາມງາມ
ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ດີມັກຈະເປັນ "ຫນຶ່ງເປີເຊັນ" ວຽກງານທີ່ຫຼຸດລົງໃນເວລາທີ່ກໍານົດເວລາ
ຄວາມກົດດັນບີບບັງຄັບໂຄງການຂອງທ່ານ. ຢ່າງໃດກໍຕາມ, ຂໍ້ຄວາມຜິດພາດທີ່ດີສາມາດເຮັດໃຫ້ຂະຫນາດໃຫຍ່,
ການປັບປຸງທີ່ບໍ່ສົມດຸນກັບປະສົບການຂອງຜູ້ໃຊ້, ເມື່ອຜູ້ໃຊ້ເຂົ້າໄປໃນຄວາມຢ້ານ
ອານາເຂດທີ່ບໍ່ຮູ້ຈັກມັກຈະບໍ່ພົບ. ນີ້ບໍ່ແມ່ນວຽກງ່າຍ.
ໃນຖານະເປັນນັກຂຽນໂປລແກລມຕົວອ່ອນ, ຜູ້ຂຽນບໍ່ໄດ້ເຫັນບັນຫາທີ່ມີຄວາມຜິດພາດ (ຖືກຕ້ອງຢ່າງສົມບູນ)
ຂໍ້ຄວາມຄືອັນນີ້:
ຂໍ້ຍົກເວັ້ນແບບເລື່ອນ (ຫຼັກຖືກຖິ້ມ)
ຈົນກ່ວາການຕີລາຄາທີ່ບໍ່ແມ່ນໂຄງການທາງເລືອກໄດ້ຖືກຊີ້ອອກ. ແຕ່ນັ້ນບໍ່ແມ່ນ
ສິ່ງດຽວທີ່ຜິດພາດກັບຂໍ້ຄວາມຜິດພາດ Unix. ເຈົ້າເຫັນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດເລື້ອຍໆສໍ່າໃດເຊັ່ນ:
$ ./ໂງ່
ບໍ່ສາມາດເປີດໄຟລ໌ໄດ້
$
ມີສອງທາງເລືອກສໍາລັບນັກພັດທະນາໃນຈຸດນີ້:
1.
ທ່ານສາມາດດໍາເນີນການ debugger ໄດ້, ເຊັ່ນ: gdb(1), ຫຼື
2.
ທ່ານສາມາດໃຊ້ ສາຍແຮ່(1) ຫຼື ມັດ(1) ເພື່ອເບິ່ງພາຍໃນ.
· ຈື່ໄວ້ວ່າຜູ້ໃຊ້ຂອງທ່ານອາດຈະບໍ່ມີການເຂົ້າເຖິງເຄື່ອງມືເຫຼົ່ານີ້, ປ່ອຍໃຫ້ຄວາມສາມາດ
ເພື່ອໃຊ້ພວກມັນ. (ມັນເປັນເວລາດົນນານຫຼາຍນັບຕັ້ງແຕ່ Unix ຜູ້ເລີ່ມຕົ້ນ ຫມາຍຄວາມວ່າ "ໄດ້ຂຽນພຽງແຕ່ ຫນຶ່ງ
ໄດເວີອຸປະກອນ”.)
ໃນຕົວຢ່າງນີ້, ຢ່າງໃດກໍຕາມ, ການນໍາໃຊ້ ສາຍແຮ່(1) ເປີດເຜີຍ
$ ສາຍແຮ່ -e trace=ເປີດ ./ໂງ່
open("some/file", O_RDONLY) = -1 ENOENT (ບໍ່ມີໄຟລ໌ ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ)
ບໍ່ສາມາດເປີດໄຟລ໌ໄດ້
$
ນີ້ແມ່ນຂໍ້ມູນຫຼາຍຫຼາຍກ່ວາຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ. ໂດຍປົກກະຕິ, ໄດ້
ລະຫັດແຫຼ່ງ stupid ເບິ່ງຄືວ່ານີ້
int fd = ເປີດ("ບາງສິ່ງບາງຢ່າງ", O_RDONLY);
ຖ້າ (fd < 0)
{
fprintf(stderr, "ບໍ່ສາມາດເປີດໄຟລ໌ໄດ້\n");
ການທ່ອງທ່ຽວ(1)
}
ຜູ້ໃຊ້ບໍ່ໄດ້ບອກ ທີ່ ໄຟລ໌, ແລະຍັງບໍ່ສາມາດບອກຜູ້ໃຊ້ໄດ້ ທີ່ ຄວາມຜິດພາດ. ແມ່ນໄຟລ໌
ແມ້ແຕ່ມີ? ມີບັນຫາການອະນຸຍາດບໍ? ມັນບອກເຈົ້າວ່າມັນກໍາລັງພະຍາຍາມເປີດ a
ໄຟລ໌, ແຕ່ວ່າອາດຈະເປັນໂດຍບັງເອີນ.
ຈັບໄມ້ຄ້ອນເທົ້າຂອງເຈົ້າແລ້ວໄປຕີໂປຣແກມເມີເຕີຕົວອ່ອນກັບມັນ. ບອກລາວກ່ຽວກັບ ຄວາມຜິດພາດ(3).
ໃນຄັ້ງຕໍ່ໄປທີ່ທ່ານໃຊ້ໂປຣແກຣມ ທ່ານຈະເຫັນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ແຕກຕ່າງກັນ:
$ ./ໂງ່
ເປີດ: ບໍ່ມີໄຟລ໌ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ
$
ຄວາມກ້າວຫນ້າ, ແຕ່ບໍ່ແມ່ນສິ່ງທີ່ພວກເຮົາຄາດຫວັງ. ຜູ້ໃຊ້ສາມາດແກ້ໄຂບັນຫາໄດ້ແນວໃດຖ້າຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ
ບໍ່ບອກລາວວ່າບັນຫາແມ່ນຫຍັງ? ຊອກຫາຢູ່ໃນແຫຼ່ງ, ພວກເຮົາເຫັນ
int fd = ເປີດ("ບາງສິ່ງບາງຢ່າງ", O_RDONLY);
ຖ້າ (fd < 0)
{
perror("ເປີດ");
ການທ່ອງທ່ຽວ(1)
}
ເວລາສໍາລັບການແລ່ນອີກຄັ້ງດ້ວຍໄມ້ຄ້ອນເທົ້າ. ເວລານີ້, ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດໃຊ້ເວລາຫນຶ່ງຂັ້ນຕອນ
ໄປຂ້າງຫນ້າແລະຫນຶ່ງບາດກ້າວກັບຄືນໄປບ່ອນ:
$ ./ໂງ່
ບາງສິ່ງບາງຢ່າງ: ບໍ່ມີເອກະສານຫລືໄດເລກະທໍລີດັ່ງກ່າວ
$
ດຽວນີ້ພວກເຮົາຮູ້ວ່າໄຟລ໌ທີ່ມັນພະຍາຍາມເປີດ, ແຕ່ບໍ່ໄດ້ແຈ້ງວ່າມັນແມ່ນ ເປີດ(2)
ລົ້ມເຫລວ. ໃນກໍລະນີນີ້ມັນອາດຈະບໍ່ມີຄວາມສໍາຄັນ, ແຕ່ວ່າມັນສາມາດສໍາຄັນສໍາລັບການ
ໂທລະບົບອື່ນໆ. ມັນອາດຈະເປັນ ສ້າງສັນ(2) ແທນທີ່ຈະເປັນ, ການດໍາເນີນງານຫມາຍຄວາມວ່າ
ການອະນຸຍາດທີ່ແຕກຕ່າງກັນແມ່ນມີຄວາມຈໍາເປັນ.
const char *filename = "ບາງສິ່ງບາງຢ່າງ";
int fd = ເປີດ(ຊື່ໄຟລ໌, O_RDONLY);
ຖ້າ (fd < 0)
{
ຜິດພາດ (ຊື່ໄຟລ໌);
ການທ່ອງທ່ຽວ(1)
}
ລະຫັດຕົວຢ່າງຂ້າງເທິງແມ່ນຫນ້າເສຍດາຍປົກກະຕິຂອງນັກຂຽນໂປລແກລມທີ່ບໍ່ແມ່ນຕົວອ່ອນເຊັ່ນກັນ. ເວລາ
ເພື່ອບອກຜູ້ຮຽນ padawan ຂອງພວກເຮົາກ່ຽວກັບ ຄວາມຜິດພາດ(3) ລະບົບການໂທ.
$ ./ໂງ່
ເປີດ ບາງສິ່ງບາງຢ່າງ: ບໍ່ມີເອກະສານຫລືໄດເລກະທໍລີດັ່ງກ່າວ
$
ນີ້ເຮັດໃຫ້ຂໍ້ມູນສູງສຸດທີ່ສາມາດນໍາສະເຫນີໃຫ້ຜູ້ໃຊ້ໄດ້. ລະຫັດເບິ່ງຄືວ່າ
ນີ້:
const char *filename = "ບາງສິ່ງບາງຢ່າງ";
int fd = ເປີດ(ຊື່ໄຟລ໌, O_RDONLY);
ຖ້າ (fd < 0)
{
fprintf(stderr, "open %s: %s\n", ຊື່ໄຟລ໌, strerror(errno));
ການທ່ອງທ່ຽວ(1)
}
ໃນປັດຈຸບັນພວກເຮົາມີການໂທລະບົບ, ຊື່ໄຟລ໌, ແລະສາຍຄວາມຜິດພາດ. ນີ້ປະກອບດ້ວຍທັງຫມົດ
ຂໍ້ມູນທີ່ ສາຍແຮ່(1) ພິມ. ນັ້ນແມ່ນດີເທົ່າທີ່ມັນໄດ້ຮັບ.
ຫລືມັນແມ່ນບໍ?
ຂໍ້ຈໍາກັດ of ຄວາມຜິດພາດ ແລະ ຄວາມຜິດພາດ
ບັນຫາທີ່ຜູ້ຂຽນເຫັນ, ໃນຊຸມປີ 1980, ແມ່ນວ່າຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດບໍ່ຄົບຖ້ວນ.
"ບໍ່ມີເອກະສານຫຼືໄດເລກະທໍລີດັ່ງກ່າວ" ຫມາຍເຖິງ "ບາງ"ໄດເລກະທໍລີ" ຫຼື "ສິ່ງທີ່” ໄຟລ໌ໃນ
ໄດ້“ບາງ” ໄດເລກະທໍລີ?
ເບິ່ງໄວຢູ່ໃນຫນ້າຜູ້ຊາຍສໍາລັບ ຄວາມຜິດພາດ(3) ກໍາລັງບອກ:
strerror - ກັບຄືນສະຕຣິງທີ່ອະທິບາຍຈໍານວນຂໍ້ຜິດພາດ
ຫມາຍເຫດດີ: ມັນແມ່ນການອະທິບາຍຄວາມຜິດພາດ ຈໍານວນ, ບໍ່ແມ່ນຄວາມຜິດພາດ.
ໃນທາງກົງກັນຂ້າມ, ແກ່ນ ຮູ້ຈັກ ຄວາມຜິດພາດແມ່ນຫຍັງ. ມີຈຸດສະເພາະຢູ່ໃນ
ລະຫັດ kernel, ທີ່ເກີດຈາກເງື່ອນໄຂສະເພາະໃດຫນຶ່ງ, ບ່ອນທີ່ລະຫັດ kernel ແຍກແລະເວົ້າວ່າ "ບໍ່".
ໂຄງການພື້ນທີ່ຜູ້ໃຊ້ສາມາດຊອກຫາເງື່ອນໄຂສະເພາະແລະຂຽນຂໍ້ຜິດພາດທີ່ດີກວ່າ
ຂໍ້ຄວາມ?
ຢ່າງໃດກໍຕາມ, ບັນຫາແມ່ນເລິກລົງ. ຈະເປັນແນວໃດຖ້າຫາກວ່າບັນຫາເກີດຂຶ້ນໃນລະຫວ່າງການ ອ່ານ(2) ລະບົບ
ໂທ, ແທນທີ່ຈະກ່ວາ ເປີດ(2) ໂທ? ມັນງ່າຍດາຍສໍາລັບຂໍ້ຄວາມຄວາມຜິດພາດທີ່ກ່ຽວຂ້ອງກັບ
ເປີດ(2) ເພື່ອປະກອບມີຊື່ໄຟລ໌, ມັນຢູ່ທີ່ນັ້ນ. ແຕ່ເພື່ອໃຫ້ສາມາດປະກອບມີຊື່ໄຟລ໌
ໃນຄວາມຜິດພາດທີ່ກ່ຽວຂ້ອງກັບ ອ່ານ(2) ການໂທລະບົບ, ທ່ານຕ້ອງຜ່ານຊື່ໄຟລ໌ທັງຫມົດ
ວິທີການລົງ stack ການໂທ, ເຊັ່ນດຽວກັນກັບຕົວອະທິບາຍໄຟລ໌.
ແລະນີ້ແມ່ນເລັກນ້ອຍທີ່ grate: kernel ຮູ້ແລ້ວວ່າໄຟລ໌ຊື່ໄຟລ໌ໃດ
ຕົວອະທິບາຍແມ່ນກ່ຽວຂ້ອງກັບ. ເປັນຫຍັງນັກຂຽນໂປລແກລມຕ້ອງຜ່ານຂໍ້ມູນທີ່ຊ້ໍາກັນທັງຫມົດ
ວິທີການລົງ stack ການໂທພຽງແຕ່ເພື່ອປັບປຸງຂໍ້ຄວາມຄວາມຜິດພາດທີ່ອາດຈະບໍ່ໄດ້ຮັບການອອກ? ໃນ
ຄວາມເປັນຈິງ, ນັກຂຽນໂປລແກລມຫຼາຍຄົນບໍ່ເບື່ອຫນ່າຍ, ແລະຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ເກີດຂື້ນແມ່ນຮ້າຍແຮງກວ່າເກົ່າ
ມັນ.
ແຕ່ນັ້ນແມ່ນຊຸມປີ 1980, ໃນ PDP11, ມີຊັບພະຍາກອນທີ່ຈໍາກັດແລະບໍ່ມີຫ້ອງສະຫມຸດຮ່ວມກັນ. ກັບຄືນໄປບ່ອນ
ຫຼັງຈາກນັ້ນ, ບໍ່ມີລົດຊາດຂອງ Unix ລວມ / proc ເຖິງແມ່ນວ່າໃນຮູບແບບພື້ນຖານ, ແລະ lsof(1) ໂຄງການ
ຫ່າງໄກຫຼາຍກວ່າທົດສະວັດ. ສະນັ້ນ ຄວາມຄິດດັ່ງກ່າວຈຶ່ງຖືກຫຼົງເຫຼືອໄວ້ເປັນສິ່ງທີ່ບໍ່ມີປະໂຫຍດ.
ລະດັບ Infinity ສະຫນັບສະຫນູນ
ຈິນຕະນາການວ່າທ່ານເປັນຜູ້ສະຫນັບສະຫນູນລະດັບ infinity. ລາຍລະອຽດວຽກຂອງເຈົ້າບອກວ່າເຈົ້າບໍ່ເຄີຍ
ເຄີຍ ຕ້ອງເວົ້າກັບຜູ້ໃຊ້. ດັ່ງນັ້ນ, ເປັນຫຍັງ, ຍັງມີກະແສຂອງປະຊາຊົນຕ້ອງການຢ່າງຕໍ່ເນື່ອງ
ທ່ານ, guru Unix ທ້ອງຖິ່ນ, ເພື່ອຖອດລະຫັດຂໍ້ຄວາມຂໍ້ຜິດພາດອື່ນບໍ?
ແປກ, 25 ປີຕໍ່ມາ, ເຖິງວ່າຈະມີລະບົບການອະນຸຍາດທີ່ງ່າຍດາຍ, ປະຕິບັດຢ່າງສົມບູນ
ຄວາມສອດຄ່ອງ, ຜູ້ໃຊ້ Unix ສ່ວນໃຫຍ່ຍັງບໍ່ມີຄວາມຄິດທີ່ຈະຖອດລະຫັດ "ບໍ່ມີໄຟລ໌ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ",
ຫຼືຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ເປັນລະຫັດລັບອື່ນໆທີ່ພວກເຂົາເຫັນທຸກໆມື້. ຫຼື, ຢ່າງຫນ້ອຍ, cryptic ກັບ
ໃຫ້ເຂົາເຈົ້າ.
ມັນຈະບໍ່ດີບໍຖ້າການສະຫນັບສະຫນູນເຕັກໂນໂລຢີລະດັບທໍາອິດບໍ່ຈໍາເປັນຕ້ອງມີຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ຖືກຖອດລະຫັດ?
ມັນບໍ່ດີບໍທີ່ຈະມີຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ຜູ້ໃຊ້ສາມາດເຂົ້າໃຈໄດ້ໂດຍບໍ່ຕ້ອງໂທຫາ
ສະຫນັບສະຫນູນເຕັກໂນໂລຊີ?
ມື້ນີ້ / proc ໃນ Linux ແມ່ນຫຼາຍກ່ວາສາມາດສະຫນອງຂໍ້ມູນທີ່ຈໍາເປັນເພື່ອຖອດລະຫັດ
ສ່ວນໃຫຍ່ຂອງຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ, ແລະຊີ້ຜູ້ໃຊ້ໄປຫາສາເຫດໃກ້ຄຽງຂອງພວກມັນ
ບັນຫາ. ໃນລະບົບທີ່ມີຈໍາກັດ / proc ການປະຕິບັດ, ໄດ້ lsof(1) ຄໍາສັ່ງສາມາດຕື່ມຂໍ້ມູນໃສ່ໃນ
ຊ່ອງຫວ່າງຫຼາຍ.
ໃນປີ 2008, ກະແສການຮ້ອງຂໍການແປພາສາເກີດຂຶ້ນກັບຜູ້ຂຽນເລື້ອຍໆເກີນໄປ. ມັນແມ່ນ
ເວລາທີ່ຈະທົບທວນຄືນຄວາມຄິດທີ່ມີອາຍຸ 25 ປີ, ແລະ libexplain ແມ່ນຜົນໄດ້ຮັບ.
ການ ນຳ ໃຊ້ ການ ຫໍສະຫມຸດ
ການໂຕ້ຕອບກັບຫ້ອງສະຫມຸດພະຍາຍາມທີ່ຈະສອດຄ່ອງ, ບ່ອນທີ່ເປັນໄປໄດ້. ໃຫ້ເລີ່ມຕົ້ນດ້ວຍ
ຕົວຢ່າງການນໍາໃຊ້ ຄວາມຜິດພາດ(3):
ຖ້າ (ປ່ຽນຊື່(old_path, new_path) < 0)
{
fprintf(stderr, "ປ່ຽນຊື່ %s %s: %s\n", old_path, new_path,
strerror(errno));
ການທ່ອງທ່ຽວ(1)
}
ແນວຄວາມຄິດທີ່ຢູ່ເບື້ອງຫລັງ libexplain ແມ່ນເພື່ອສະຫນອງ a ຄວາມຜິດພາດ(3) ທຽບເທົ່າສໍາລັບ ແຕ່ລະຄົນ ໂທລະບົບ,
ປັບແຕ່ງສະເພາະກັບການໂທລະບົບນັ້ນ, ເພື່ອໃຫ້ມັນສາມາດສະຫນອງຄວາມຜິດພາດທີ່ລະອຽດກວ່າ
ຂໍ້ຄວາມ, ປະກອບດ້ວຍຂໍ້ມູນຫຼາຍຢ່າງທີ່ເຈົ້າເຫັນພາຍໃຕ້ຫົວຂໍ້ “Error” ຂອງພາກສ່ວນ
2 ແລະ 3 ຜູ້ຊາຍ ຫນ້າ, ເສີມດ້ວຍຂໍ້ມູນກ່ຽວກັບເງື່ອນໄຂຕົວຈິງ, ການໂຕ້ຖຽງຕົວຈິງ
ຄ່າ, ແລະຂໍ້ຈໍາກັດຂອງລະບົບ.
ໄດ້ ງ່າຍດາຍ ກໍລະນີ
ໄດ້ ຄວາມຜິດພາດ(3) ການທົດແທນ:
ຖ້າ (ປ່ຽນຊື່(old_path, new_path) < 0)
{
fprintf(stderr, "%s\n", explain_rename(old_path, new_path));
ການທ່ອງທ່ຽວ(1)
}
ໄດ້ ເອີໂຣ ກໍລະນີ
ມັນເປັນໄປໄດ້ທີ່ຈະຜ່ານຢ່າງຈະແຈ້ງ ຜິດພາດ(3) ມູນຄ່າ, ຖ້າຫາກວ່າທ່ານທໍາອິດຕ້ອງເຮັດບາງ
ການປະມວນຜົນທີ່ຈະລົບກວນ ຜິດພາດ, ເຊັ່ນວ່າການຟື້ນຕົວຄວາມຜິດພາດ:
ຖ້າ (ປ່ຽນຊື່(old_path, new_path < 0))
{
int old_errno = errno;
...ລະຫັດ ທີ່ ລົບກວນ ຜິດພາດ...
fprintf(stderr, "%s\n", ອະທິບາຍ_errno_rename(old_errno,
old_path, new_path));
ການທ່ອງທ່ຽວ(1)
}
ໄດ້ ຫຼາຍກະທູ້ ກໍລະນີ
ບາງແອັບພລິເຄຊັນແມ່ນມີຫຼາຍກະທູ້, ແລະດັ່ງນັ້ນຈຶ່ງບໍ່ສາມາດແບ່ງປັນ libexplain ພາຍໃນໄດ້
ບັຟເຟີ. ທ່ານສາມາດສະຫນອງ buffer ຂອງທ່ານເອງໂດຍໃຊ້
ຖ້າ (ຖອນການເຊື່ອມຕໍ່(ຊື່ເສັ້ນທາງ))
{
char message[3000];
explain_message_unlink(ຂໍ້ຄວາມ, ຂະຫນາດຂອງ(ຂໍ້ຄວາມ), ຊື່ເສັ້ນທາງ);
error_dialog(ຂໍ້ຄວາມ);
ກັບຄືນ -1;
}
ແລະສໍາລັບຄວາມສົມບູນ, ທັງສອງ ຜິດພາດ(3) ແລະປອດໄພກະທູ້:
ssize_t nbytes = read(fd, data, sizeof(data));
ຖ້າ (nbytes < 0)
{
char message[3000];
int old_errno = errno;
...ຄວາມຜິດພາດ ການຟື້ນຟູ...
explain_message_errno_read(ຂໍ້ຄວາມ, ຂະຫນາດຂອງ(ຂໍ້ຄວາມ),
old_errno, fd, data, sizeof(data));
error_dialog(ຂໍ້ຄວາມ);
ກັບຄືນ -1;
}
ເຫຼົ່ານີ້ແມ່ນການທົດແທນສໍາລັບການ strerror_r(3), ກ່ຽວກັບລະບົບທີ່ມີມັນ.
ການໂຕ້ຕອບ ້ໍາຕານ
ຊຸດຂອງຫນ້າທີ່ເພີ່ມເປັນຫນ້າທີ່ສະດວກ, ເພື່ອ woo programmer ທີ່ຈະນໍາໃຊ້
libexplain ຫໍສະຫມຸດ, ກາຍເປັນຫນ້າທີ່ libexplain ທີ່ໃຊ້ທົ່ວໄປທີ່ສຸດຂອງຜູ້ຂຽນໃນ
ໂຄງການເສັ້ນຄໍາສັ່ງ:
int fd = ອະທິບາຍ_creat_or_die(ຊື່ໄຟລ໌, 0666);
ຟັງຊັນນີ້ພະຍາຍາມສ້າງໄຟລ໌ໃຫມ່. ຖ້າຫາກວ່າມັນບໍ່ສາມາດ, ມັນພິມຂໍ້ຄວາມຜິດພາດແລະ
ອອກໄປດ້ວຍ EXIT_FAILURE. ຖ້າບໍ່ມີຂໍ້ຜິດພາດ, ມັນຈະສົ່ງຄືນຕົວອະທິບາຍໄຟລ໌ໃຫມ່.
ຫນ້າທີ່ທີ່ກ່ຽວຂ້ອງ:
int fd = ອະທິບາຍ_creat_on_error(ຊື່ໄຟລ໌, 0666);
ຈະພິມຂໍ້ຄວາມຄວາມຜິດພາດກ່ຽວກັບຄວາມລົ້ມເຫຼວ, ແຕ່ຍັງສົ່ງຄືນຜົນໄດ້ຮັບຄວາມຜິດພາດຕົ້ນສະບັບ, ແລະ
ຜິດພາດ(3) ແມ່ນ unmolested, ເຊັ່ນດຽວກັນ.
ທັງຫມົດ ໄດ້ ອື່ນໆ ລະບົບ ໂທ
ໂດຍທົ່ວໄປ, ທຸກໆການໂທລະບົບມີໄຟລ໌ຂອງຕົນເອງ
#ລວມທັງຊື່.h>
ທີ່ກໍານົດ prototypes ຫນ້າທີ່ສໍາລັບຫົກຫນ້າທີ່:
·ອະທິບາຍ_ຊື່,
·ອະທິບາຍ_errno_ຊື່,
·ອະທິບາຍ_ຂໍ້ຄວາມ_ຊື່,
·ອະທິບາຍ_ຂໍ້ຄວາມ_errno_ຊື່,
·ອະທິບາຍ_ຊື່_or_die ແລະ
·ອະທິບາຍ_ຊື່_on_error.
ທຸກໆຕົ້ນແບບຟັງຊັນມີເອກະສານ Doxygen, ແລະເອກະສານນີ້ is ບໍ່ ປິດ
ເມື່ອໄຟລ໌ລວມຖືກຕິດຕັ້ງ.
ໄດ້ ລໍຖ້າ(2) ການໂທຫາລະບົບ (ແລະຫມູ່ເພື່ອນ) ມີບາງຕົວແປເພີ່ມເຕີມທີ່ຕີຄວາມລົ້ມເຫຼວ
ເພື່ອເປັນສະຖານະທາງອອກທີ່ບໍ່ແມ່ນ EXIT_SUCCESS. ນີ້ໃຊ້ກັບ ລະບົບ(3) ແລະ ປິດ(3) ເປັນ
ດີ.
ການຄຸ້ມຄອງປະກອບມີ 221 ການໂທຫາລະບົບແລະການຮ້ອງຂໍ 547 ioctl. ມີຫຼາຍລະບົບຫຼາຍ
ການຮຽກຮ້ອງຍັງບໍ່ທັນປະຕິບັດ. ລະບົບການໂທທີ່ບໍ່ເຄີຍກັບຄືນມາ, ເຊັ່ນ: ການທ່ອງທ່ຽວ(2), ບໍ່ມີ
ໃນຫ້ອງສະຫມຸດ, ແລະຈະບໍ່ເປັນ. ໄດ້ exec ຄອບຄົວຂອງການໂທລະບົບ ມີ ສະຫນັບສະຫນູນ, ເນື່ອງຈາກວ່າ
ພວກເຂົາເຈົ້າກັບຄືນເມື່ອມີຄວາມຜິດພາດ.
ແມວ
ນີ້ແມ່ນສິ່ງທີ່ໂຄງການ "cat" ສົມມຸດຕິຖານສາມາດເບິ່ງຄືວ່າ, ດ້ວຍການລາຍງານຄວາມຜິດພາດຢ່າງເຕັມທີ່,
ໃຊ້ libexplain.
#ລວມທັງ
# ປະກອບ
#ລວມທັງ
ມີຫນຶ່ງປະກອບມີສໍາລັບ libexplain, ບວກກັບຜູ້ຕ້ອງສົງໄສປົກກະຕິ. (ຖ້າຫາກວ່າທ່ານຕ້ອງການທີ່ຈະຫຼຸດຜ່ອນການ
ການໂຫຼດ preprocessor, ທ່ານສາມາດນໍາໃຊ້ສະເພາະຊື່.h> ປະກອບມີ.)
void static
ຂະບວນການ (FILE *fp)
{
ສໍາລັບ (;;)
{
char buffer[4096];
size_t n = ອະທິບາຍ_fread_or_die(buffer, 1, sizeof(buffer), fp);
ຖ້າ (!n)
ທໍາລາຍ;
explain_fwrite_or_die(buffer, 1, n, stdout);
}
}
ໄດ້ ຂະບວນການ ຟັງຊັນຄັດລອກກະແສໄຟລ໌ໄປຫາຜົນຜະລິດມາດຕະຖານ. ຄວນມີຂໍ້ຜິດພາດເກີດຂຶ້ນ
ສໍາລັບການອ່ານຫຼືຂຽນ, ມັນຖືກລາຍງານ (ແລະຊື່ເສັ້ນທາງຈະຖືກລວມຢູ່ໃນ
error) ແລະຄໍາສັ່ງອອກດ້ວຍ EXIT_FAILURE. ພວກເຮົາບໍ່ກັງວົນກ່ຽວກັບການຕິດຕາມ
pathnames, ຫຼືຖ່າຍທອດໃຫ້ເຂົາເຈົ້າລົງ stack ການໂທ.
int
main(int argc, char **argv)
{
ສໍາລັບ (;;)
{
int c = getopt(argc, argv, "o:");
ຖ້າ (c == EOF)
ທໍາລາຍ;
ສະຫຼັບ (c)
{
ກໍລະນີ 'o':
ອະທິບາຍ_freopen_or_die(optarg, "w", stdout);
ທໍາລາຍ;
ພາກສ່ວນທີ່ມ່ວນຂອງລະຫັດນີ້ແມ່ນວ່າ libexplain ສາມາດລາຍງານຂໍ້ຜິດພາດ ລວມທັງ ໄດ້ ຊື່ເສັ້ນທາງ ເຖິງແມ່ນວ່າ
ຖ້າເຈົ້າ ບໍ່ໄດ້ ເປີດ stdout ຄືນໃໝ່ຢ່າງຈະແຈ້ງຕາມທີ່ເຮັດຢູ່ນີ້. ພວກເຮົາບໍ່ເປັນຫ່ວງກ່ຽວກັບ
ຕິດຕາມຊື່ໄຟລ໌.
default:
fprintf(stderr, "ການນຳໃຊ້: %ss [ -o ] ...\n",
argv[0]);
ກັບຄືນ EXIT_FAILURE;
}
}
ຖ້າ (optind == argc)
ຂະບວນການ(stdin);
ອື່ນ
{
ໃນຂະນະທີ່ (ເລືອກ < argc)
{
FILE *fp = explain_fopen_or_die(argv[optind]++, "r");
ຂະບວນການ(fp);
ອະທິບາຍ_fclose_or_die(fp);
}
}
ຜົນຜະລິດມາດຕະຖານຈະຖືກປິດຢ່າງບໍ່ຊັດເຈນ, ແຕ່ຊ້າເກີນໄປສໍາລັບການລາຍງານຄວາມຜິດພາດ
ອອກມາ, ດັ່ງນັ້ນພວກເຮົາເຮັດມັນຢູ່ທີ່ນີ້, ພຽງແຕ່ໃນກໍລະນີທີ່ I/O buffed ຍັງບໍ່ໄດ້ຂຽນຫຍັງເທື່ອ, ແລະ
ມີຄວາມຜິດພາດ ENOSPC ຫຼືບາງສິ່ງບາງຢ່າງ.
ອະທິບາຍ_fflush_or_die(stdout);
ກັບຄືນ EXIT_SUCCESS;
}
ຫມົດເທົ່ານີ້. ລາຍງານຂໍ້ຜິດພາດເຕັມ, ລະຫັດຊັດເຈນ.
ຂອງ Rusty ຂະຫນາດ of ການໂຕ້ຕອບ ຄວາມດີ
ສໍາລັບຜູ້ທີ່ບໍ່ຄຸ້ນເຄີຍກັບມັນ, Rusty Russel ຂອງ "ຂ້ອຍຈະເຮັດໃຫ້ມັນຍາກທີ່ຈະໃຊ້ໃນທາງທີ່ຜິດ?"
ຫນ້າແມ່ນຕ້ອງອ່ານສໍາລັບຜູ້ອອກແບບ API.
http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html
10. ມັນເປັນ ເປັນໄປບໍ່ໄດ້ to ໄດ້ຮັບ ຜິດ
ເປົ້າໝາຍຕ້ອງຕັ້ງໃຫ້ສູງ, ມີຄວາມທະເຍີທະຍານສູງ, ຢ້ານວ່າເຈົ້າຈະເຮັດສຳເລັດ ແລະຄິດວ່າເຈົ້າເປັນເຈົ້າ
ສໍາເລັດໃນເວລາທີ່ທ່ານບໍ່ໄດ້.
ຫ້ອງສະຫມຸດ libexplain ກວດພົບຕົວຊີ້ປອມແລະຕົວກໍານົດການໂທຫາລະບົບປອມຈໍານວນຫຼາຍ,
ແລະໂດຍທົ່ວໄປແລ້ວພະຍາຍາມຫຼີກລ້ຽງຄວາມຜິດໃນກໍລະນີທີ່ພະຍາຍາມທີ່ສຸດ.
ຫ້ອງສະໝຸດ libexplain ຖືກອອກແບບມາໃຫ້ມີຄວາມປອດໄພຂອງກະທູ້. ມີແນວໂນ້ມທີ່ຈະໃຊ້ໃນໂລກຕົວຈິງຫຼາຍຂຶ້ນ
ເປີດເຜີຍສະຖານທີ່ນີ້ສາມາດປັບປຸງໄດ້.
ບັນຫາໃຫຍ່ທີ່ສຸດແມ່ນກັບຊື່ຫນ້າທີ່ຕົວຈິງຂອງຕົນເອງ. ເນື່ອງຈາກວ່າ C ບໍ່ມີ
name-spaces, ຫ້ອງສະຫມຸດ libexplain ໃຊ້ຄໍານໍາຫນ້າຊື່ອະທິບາຍ. ນີ້ແມ່ນ
ວິທີການແບບດັ້ງເດີມຂອງການສ້າງ pseudo-name-space ເພື່ອຫຼີກເວັ້ນການຂັດແຍ້ງຂອງສັນຍາລັກ.
ຢ່າງໃດກໍຕາມ, ມັນສົ່ງຜົນໃຫ້ບາງຊື່ສຽງທີ່ຜິດທໍາມະຊາດ.
9. ໄດ້ ນັກຂຽນ or linker ຈະບໍ່ ໃຫ້ ທ່ານ ໄດ້ຮັບ it ຜິດ
ຄວາມຜິດພາດທົ່ວໄປແມ່ນການໃຊ້ description_open ບ່ອນທີ່ອະທິບາຍ_open_or_die ມີຈຸດປະສົງ.
ໂຊກດີ, compiler ມັກຈະອອກຂໍ້ຜິດພາດປະເພດຢູ່ໃນຈຸດນີ້ (ຕົວຢ່າງ: ບໍ່ສາມາດມອບໝາຍໄດ້
const char * rvalue ເປັນ int lvalue).
8. ໄດ້ ນັກຂຽນ ຈະ ເຕືອນ if ທ່ານ ໄດ້ຮັບ it ຜິດ
ຖ້າexplan_rename ຖືກໃຊ້ເມື່ອexplain_rename_or_die ມີຈຸດປະສົງ, ອັນນີ້ອາດເຮັດໃຫ້ເກີດອັນອື່ນ
ບັນຫາ. GCC ມີຄຸນສົມບັດຫນ້າທີ່ warn_unused_result ທີ່ເປັນປະໂຫຍດ, ແລະ libexplain
ຫ້ອງສະຫມຸດຄັດຕິດມັນກັບຄໍາອະທິບາຍທັງຫມົດຊື່ ຟັງຊັນໂທເພື່ອຜະລິດຄໍາເຕືອນໃນເວລາທີ່ທ່ານ
ເຮັດຜິດພາດນີ້. ສົມທົບການນີ້ກັບ gcc - ຄວາມຜິດພາດ ເພື່ອສົ່ງເສີມອັນນີ້ເຖິງລະດັບ 9 ຄວາມດີ.
7. ໄດ້ ເຫັນໄດ້ຊັດເຈນ ການນໍາໃຊ້ is (ອາດຈະເປັນ) ໄດ້ ທີ່ຖືກຕ້ອງ ຫນຶ່ງ.
ຊື່ຟັງຊັນໄດ້ຖືກເລືອກເພື່ອສະແດງຄວາມຫມາຍຂອງມັນ, ແຕ່ນີ້ບໍ່ແມ່ນສະເຫມີໄປ
ສໍາເລັດ. ໃນຂະນະທີ່ອະທິບາຍ_ຊື່_or_die ແລະອະທິບາຍ_ຊື່_on_error ມີການອະທິບາຍພໍສົມຄວນ,
ຕົວແປທີ່ປອດໄພຂອງກະທູ້ທີ່ໃຊ້ໜ້ອຍແມ່ນຍາກທີ່ຈະຖອດລະຫັດໄດ້. prototypes ຫນ້າທີ່ຊ່ວຍໃຫ້
compiler ໄປສູ່ຄວາມເຂົ້າໃຈ, ແລະຄໍາເຫັນ Doxygen ໃນໄຟລ໌ header ຊ່ວຍໃຫ້ຜູ້ໃຊ້
ໄປສູ່ຄວາມເຂົ້າໃຈ.
6. ໄດ້ ຊື່ ບອກວ່າ ທ່ານ ວິທີການ to ການນໍາໃຊ້ ມັນ.
ມັນເປັນສິ່ງສໍາຄັນທີ່ຈະອ່ານອະທິບາຍ_ຊື່_or_die ເປັນ “ອະທິບາຍ (ຊື່ ຫຼືຕາຍ)”.
ການນໍາໃຊ້ຄໍານໍາຫນ້າຊື່ອະທິບາຍທີ່ສອດຄ້ອງກັນມີບາງຜົນກະທົບຂ້າງຄຽງທີ່ໂຊກດີໃນ
ພະແນກຄວາມຊັດເຈນ, ເຊັ່ນດຽວກັນ.
ຄໍາສັ່ງຂອງຄໍາສັບຕ່າງໆໃນຊື່ຍັງຊີ້ໃຫ້ເຫັນຄໍາສັ່ງຂອງການໂຕ້ຖຽງ. ການໂຕ້ຖຽງ
ລາຍຊື່ສະເຫມີ ໃນຕອນທ້າຍ ມີການໂຕ້ຖຽງດຽວກັນກັບການໂທຜ່ານລະບົບ; ທັງຫມົດ of ໃຫ້ເຂົາເຈົ້າທີ່ຢູ່ ຖ້າຫາກວ່າ
_errno_ ປາກົດຢູ່ໃນຊື່, ການໂຕ້ຖຽງຂອງມັນຢູ່ກ່ອນການໂຕ້ຖຽງການໂທລະບົບ. ຖ້າ
_message_ ປາກົດຢູ່ໃນຊື່, ສອງຂໍ້ໂຕ້ແຍ້ງຂອງມັນມາກ່ອນ.
5. Do it ສິດ or it ຈະ ພັກຜ່ອນ at ເວລາແລ່ນ.
ຫ້ອງສະຫມຸດ libexplain ກວດພົບຕົວຊີ້ປອມແລະຕົວກໍານົດການໂທຫາລະບົບປອມຈໍານວນຫຼາຍ,
ແລະໂດຍທົ່ວໄປແລ້ວພະຍາຍາມຫຼີກລ້ຽງຄວາມຜິດໃນກໍລະນີທີ່ພະຍາຍາມທີ່ສຸດ. ມັນຄວນ
ບໍ່ເຄີຍແຕກຫັກໃນເວລາແລ່ນ, ແຕ່ການນໍາໃຊ້ໃນໂລກທີ່ແທ້ຈິງຫຼາຍຈະປັບປຸງສິ່ງນີ້ຢ່າງແນ່ນອນ.
ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດບາງຢ່າງແມ່ນແນໃສ່ນັກພັດທະນາແລະຜູ້ຮັກສາຫຼາຍກວ່າຜູ້ໃຊ້ສຸດທ້າຍ, ຍ້ອນວ່ານີ້
ສາມາດຊ່ວຍແກ້ໄຂຂໍ້ຜິດພາດໄດ້. ບໍ່ຫຼາຍປານໃດ "ພັກຜ່ອນໃນເວລາແລ່ນ" ເປັນ "ໃຫ້ຂໍ້ມູນຢູ່
runtime” (ຫຼັງຈາກລະບົບການໂທ barfs).
4. ປະຕິບັດຕາມ ທົ່ວໄປ ສົນທິສັນຍາ ແລະ ເຈົ້າຈະ ໄດ້ຮັບ it right
ເນື່ອງຈາກວ່າ C ບໍ່ມີຊ່ອງຫວ່າງຊື່, ຫ້ອງສະຫມຸດ libexplain ໃຊ້ຊື່ອະທິບາຍສະເຫມີ
ຄຳນຳໜ້າ. ນີ້ແມ່ນວິທີການພື້ນເມືອງຂອງການສ້າງ pseudo-name-space ເພື່ອຫຼີກເວັ້ນການ
ສັນຍາລັກຂັດກັນ.
ການໂຕ້ຖຽງຕໍ່ທ້າຍຂອງການໂທ libexplain ທັງຫມົດແມ່ນຄືກັນກັບລະບົບໂທຫາພວກເຂົາ
ກໍາລັງອະທິບາຍ. ນີ້ແມ່ນຈຸດປະສົງເພື່ອສະຫນອງສົນທິສັນຍາທີ່ສອດຄ່ອງກັນກັບ
ລະບົບເອີ້ນຕົວເອງ.
3. ອ່ານ ໄດ້ ເອກະສານ ແລະ ເຈົ້າຈະ ໄດ້ຮັບ it right
ຫ້ອງສະຫມຸດ libexplain ມີຈຸດປະສົງເພື່ອໃຫ້ມີເອກະສານ Doxygen ຄົບຖ້ວນສໍາລັບແຕ່ລະຄົນ
ການໂທ API ສາທາລະນະ (ແລະພາຍໃນເຊັ່ນດຽວກັນ).
ຂໍ້ຄວາມ ເນື້ອໃນ
ການເຮັດວຽກກ່ຽວກັບ libexplain ແມ່ນຄ້າຍຄືກັບເບິ່ງດ້ານລຸ່ມຂອງລົດຂອງເຈົ້າເມື່ອມັນຂຶ້ນ
hoist ຢູ່ກົນຈັກ. ມີສິ່ງທີ່ໜ້າກຽດບາງຢ່າງຢູ່ໃຕ້ບ່ອນນັ້ນ, ບວກກັບຂີ້ຕົມ ແລະຂີ້ຕົມ, ແລະ
ຜູ້ໃຊ້ບໍ່ຄ່ອຍເຫັນມັນ. ຂໍ້ຄວາມຜິດພາດທີ່ດີຈໍາເປັນຕ້ອງໃຫ້ຂໍ້ມູນ, ເຖິງແມ່ນວ່າສໍາລັບຜູ້ໃຊ້ທີ່
ໂຊກດີພໍທີ່ຈະບໍ່ຕ້ອງເບິ່ງຂ້າງລຸ່ມເລື້ອຍໆ, ແລະເຊັ່ນກັນ
ຂໍ້ມູນສໍາລັບກົນໄກການຟັງຄໍາອະທິບາຍຂອງຜູ້ໃຊ້ຜ່ານໂທລະສັບ. ນີ້ແມ່ນ
ບໍ່ມີວຽກງານງ່າຍດາຍ.
ກວດເບິ່ງຕົວຢ່າງທໍາອິດຂອງພວກເຮົາ, ລະຫັດຕ້ອງການນີ້ຖ້າມັນໃຊ້ libexplain:
int fd = explain_open_or_die("ບາງອັນ", O_RDONLY, 0);
ຈະລົ້ມເຫລວກັບຂໍ້ຄວາມຜິດພາດເຊັ່ນນີ້
open(pathname = "some/file", flags = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ ຫຼື directory
(2, ENOENT) ເພາະວ່າບໍ່ມີລາຍການ "ບາງ" ໃນໄດເລກະທໍລີປະຈຸບັນ
ນີ້ແບ່ງອອກເປັນສາມຕ່ອນ
ໂທລະບົບ ລົ້ມເຫລວ, ຄວາມຜິດພາດລະບົບ ເນື່ອງຈາກວ່າ
ຄໍາອະທິບາຍ
ກ່ອນທີ່ຈະ ເນື່ອງຈາກວ່າ
ມັນເປັນໄປໄດ້ທີ່ຈະເຫັນສ່ວນຂອງຂໍ້ຄວາມກ່ອນ "ເພາະວ່າ" ເປັນເຕັກນິກຫຼາຍເກີນໄປທີ່ຈະບໍ່ແມ່ນ.
ຜູ້ໃຊ້ດ້ານວິຊາການ, ສ່ວນໃຫຍ່ແມ່ນເປັນຜົນມາຈາກການພິມຢ່າງຖືກຕ້ອງລະບົບໂທຫາຕົວມັນເອງຢູ່ທີ່
ການເລີ່ມຕົ້ນຂອງຂໍ້ຄວາມຜິດພາດ. ແລະເບິ່ງຄືວ່າ ສາຍແຮ່(1) ຜົນຜະລິດ, ສໍາລັບ geek ໂບນັດ
ຈຸດ.
open(pathname = "some/file", flags = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ ຫຼື directory
(2, ENOENT)
ສ່ວນຫນຶ່ງຂອງຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດນີ້ເປັນສິ່ງຈໍາເປັນສໍາລັບນັກພັດທະນາໃນເວລາທີ່ລາວກໍາລັງຂຽນລະຫັດ,
ແລະມີຄວາມສໍາຄັນເທົ່າທຽມກັນກັບຜູ້ຮັກສາທີ່ຕ້ອງອ່ານບົດລາຍງານ bug ແລະແກ້ໄຂຂໍ້ບົກພ່ອງໃນ
ລະຫັດ. ມັນບອກວ່າສິ່ງທີ່ລົ້ມເຫລວ.
ຖ້າຂໍ້ຄວາມນີ້ບໍ່ໄດ້ຖືກນໍາສະເຫນີຕໍ່ຜູ້ໃຊ້, ຜູ້ໃຊ້ບໍ່ສາມາດຄັດລອກແລະວາງມັນເຂົ້າໄປໃນ a
ລາຍງານ bug, ແລະຖ້າຫາກວ່າມັນບໍ່ໄດ້ຢູ່ໃນບົດລາຍງານ bug ຜູ້ຮັກສາບໍ່ສາມາດຮູ້ວ່າສິ່ງທີ່ເປັນໄປ.
ຜິດ
ເລື້ອຍໆພະນັກງານເຕັກໂນໂລຢີຈະໃຊ້ ສາຍແຮ່(1) ຫຼື ມັດ(1) ເພື່ອໃຫ້ໄດ້ຮັບຂໍ້ມູນທີ່ແນ່ນອນນີ້, ແຕ່
ເສັ້ນທາງນີ້ບໍ່ເປີດໃນເວລາອ່ານລາຍງານຂໍ້ຜິດພາດ. ລະບົບນັກຂ່າວ bug ແມ່ນຢູ່ໄກ
ໄປ, ແລະ, ໃນປັດຈຸບັນ, ຢູ່ໃນສະພາບທີ່ແຕກຕ່າງກັນໄກ. ດັ່ງນັ້ນ, ຂໍ້ມູນນີ້ຈໍາເປັນຕ້ອງຢູ່ໃນ
ລາຍງານຂໍ້ຜິດພາດ, ຊຶ່ງຫມາຍຄວາມວ່າມັນຕ້ອງຢູ່ໃນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ.
ການເປັນຕົວແທນການໂທລະບົບຍັງໃຫ້ບໍລິບົດກັບສ່ວນທີ່ເຫຼືອຂອງຂໍ້ຄວາມ. ຖ້າຕ້ອງການ
ເກີດຂຶ້ນ, ການໂຕ້ຖຽງການໂທລະບົບ offending ອາດຈະຖືກກ່າວເຖິງໂດຍຊື່ໃນຄໍາອະທິບາຍ
ຫຼັງຈາກ "ເພາະວ່າ". ນອກຈາກນັ້ນ, strings ທັງຫມົດໄດ້ຖືກອ້າງອີງຢ່າງເຕັມສ່ວນແລະຫນີ C strings, ດັ່ງນັ້ນ
ແຖວໃໝ່ທີ່ຝັງໄວ້ ແລະຕົວອັກສອນທີ່ບໍ່ໄດ້ພິມຈະບໍ່ເຮັດໃຫ້ເຄື່ອງຂອງຜູ້ໃຊ້ໄປ
ເສັ້ນໄຍ.
ໄດ້ ຄວາມຜິດພາດລະບົບ ແມ່ນສິ່ງທີ່ອອກມາຈາກ ຄວາມຜິດພາດ(2), ບວກກັບສັນຍາລັກຄວາມຜິດພາດ. ອົດທົນ ແລະ
sysadmins ຜູ້ຊ່ຽວຊານສາມາດຢຸດການອ່ານຢູ່ໃນຈຸດນີ້, ແຕ່ປະສົບການຂອງຜູ້ຂຽນຈົນເຖິງປະຈຸບັນແມ່ນ
ການອ່ານຕໍ່ໄປແມ່ນໃຫ້ລາງວັນ. (ຖ້າມັນບໍ່ແມ່ນລາງວັນ, ມັນອາດຈະເປັນພື້ນທີ່ຂອງ
libexplain ທີ່ສາມາດປັບປຸງໄດ້. ການປະກອບສ່ວນລະຫັດແມ່ນຍິນດີຕ້ອນຮັບ, ແນ່ນອນ.)
ຫຼັງຈາກ ເນື່ອງຈາກວ່າ
ນີ້ແມ່ນສ່ວນຂອງຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດທີ່ແນໃສ່ຜູ້ໃຊ້ທີ່ບໍ່ແມ່ນວິຊາການ. ມັນເບິ່ງເກີນກວ່າ
ການໂຕ້ຖຽງການໂທລະບົບທີ່ງ່າຍດາຍ, ແລະຊອກຫາສິ່ງທີ່ສະເພາະຫຼາຍ.
ບໍ່ມີໄດເລກະທໍລີ "ບາງ" ໃນໄດເລກະທໍລີປະຈຸບັນ
ສ່ວນນີ້ພະຍາຍາມອະທິບາຍສາເຫດໃກ້ຄຽງຂອງຄວາມຜິດພາດໃນພາສາທໍາມະດາ, ແລະມັນ
ຢູ່ທີ່ນີ້, ຄວາມເປັນສາກົນແມ່ນມີຄວາມຈຳເປັນ.
ໂດຍທົ່ວໄປ, ນະໂຍບາຍແມ່ນເພື່ອປະກອບມີຂໍ້ມູນຫຼາຍເທົ່າທີ່ເປັນໄປໄດ້, ເພື່ອໃຫ້ຜູ້ໃຊ້
ບໍ່ຈໍາເປັນຕ້ອງໄປຊອກຫາມັນ (ແລະບໍ່ໄດ້ປ່ອຍໃຫ້ມັນອອກຈາກບົດລາຍງານ bug).
Internationalization
ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດສ່ວນໃຫຍ່ໃນຫ້ອງສະຫມຸດ libexplain ໄດ້ຖືກປັບປຸງເປັນສາກົນ. ຢູ່ທີ່ນັ້ນ
ຍັງບໍ່ມີການທ້ອງຖິ່ນເທື່ອ, ສະນັ້ນຖ້າທ່ານຕ້ອງການຄໍາອະທິບາຍເປັນພາສາກໍາເນີດຂອງທ່ານ,
ກະລຸນາປະກອບສ່ວນ.
ຄຸນສົມບັດ "ຫຼາຍທີ່ສຸດ", ຂ້າງເທິງ, ກ່ຽວຂ້ອງກັບຄວາມຈິງທີ່ວ່າຫຼັກຖານສະແດງແນວຄວາມຄິດ
ການຈັດຕັ້ງປະຕິບັດບໍ່ໄດ້ລວມເອົາການສະໜັບສະໜູນສາກົນ. ພື້ນຖານລະຫັດແມ່ນເປັນ
ປັບປຸງແກ້ໄຂເທື່ອລະກ້າວ, ປົກກະຕິແລ້ວເປັນຜົນມາຈາກການ refactoring ຂໍ້ຄວາມເພື່ອໃຫ້ແຕ່ລະຂໍ້ຜິດພາດ
ຂໍ້ຄວາມສະຕຣິງປາກົດຢູ່ໃນລະຫັດແນ່ນອນຫນຶ່ງຄັ້ງ.
ການຈັດສັນໄດ້ຖືກສ້າງຂຶ້ນສໍາລັບພາສາທີ່ຈໍາເປັນຕ້ອງໄດ້ປະກອບສ່ວນຂອງ
ໂທລະບົບ ລົ້ມເຫລວ, ຄວາມຜິດພາດລະບົບ ເນື່ອງຈາກວ່າ ຄໍາອະທິບາຍ
ໃນຄໍາສັ່ງທີ່ແຕກຕ່າງກັນສໍາລັບໄວຍະກອນທີ່ຖືກຕ້ອງໃນຂໍ້ຄວາມຄວາມຜິດພາດໃນທ້ອງຖິ່ນ.
ໄປສະນີ mortem
ມີເວລາທີ່ໂຄງການຍັງບໍ່ທັນໃຊ້ libexplain, ແລະທ່ານບໍ່ສາມາດໃຊ້ໄດ້ ສາຍແຮ່(1)
ບໍ່ວ່າຈະ. ມີ ອະທິບາຍ(1) ຄໍາສັ່ງລວມກັບ libexplain ທີ່ສາມາດຖືກນໍາໃຊ້ເພື່ອ
ຖອດລະຫັດຂໍ້ຄວາມຜິດພາດ, ຖ້າສະຖານະຂອງລະບົບພື້ນຖານບໍ່ໄດ້ປ່ຽນແປງຫຼາຍເກີນໄປ.
$ ອະທິບາຍ ປ່ຽນຊື່ ຟູ /tmp/bar/baz -e ENOENT
rename(oldpath = "foo", newpath = "/tmp/bar/baz") ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ.
(2, ENOENT) ເນື່ອງຈາກວ່າບໍ່ມີ "bar" directory ໃນ newpath "./ tmp"ໄດເລກະທໍລີ
$
ໃຫ້ສັງເກດວິທີການແກ້ໄຂຄວາມບໍ່ຊັດເຈນຂອງເສັ້ນທາງໂດຍການໃຊ້ຊື່ argument ການເອີ້ນລະບົບ. ຂອງ
ແນ່ນອນ, ທ່ານຕ້ອງຮູ້ຂໍ້ຜິດພາດແລະລະບົບໂທຫາ ອະທິບາຍ(1) ເປັນປະໂຫຍດ. ເປັນ
ຫລີກໄປທາງຫນຶ່ງ, ນີ້ແມ່ນວິທີຫນຶ່ງທີ່ໃຊ້ໂດຍຊຸດທົດສອບອັດຕະໂນມັດ libexplain ເພື່ອກວດສອບວ່າ
libexplain ເຮັດວຽກ.
ປັດຊະຍາ
"ບອກຂ້ອຍທຸກຢ່າງ, ລວມທັງສິ່ງທີ່ຂ້ອຍບໍ່ຮູ້ວ່າຈະຊອກຫາ."
ຫ້ອງສະຫມຸດໄດ້ຖືກປະຕິບັດໃນລັກສະນະທີ່ເມື່ອເຊື່ອມຕໍ່ແບບຄົງທີ່, ພຽງແຕ່ລະຫັດທ່ານ
ການນໍາໃຊ້ຕົວຈິງຈະຖືກເຊື່ອມຕໍ່. ນີ້ແມ່ນບັນລຸໄດ້ໂດຍການມີຫນຶ່ງຟັງຊັນຕໍ່ໄຟລ໌ແຫຼ່ງ,
ທຸກຄັ້ງທີ່ເປັນໄປໄດ້.
ເມື່ອມັນເປັນໄປໄດ້ທີ່ຈະສະຫນອງຂໍ້ມູນເພີ່ມເຕີມ, libexplain ຈະເຮັດແນວນັ້ນ. ຜູ້ໃຊ້ຫນ້ອຍລົງ
ມີການຕິດຕາມລົງສໍາລັບຕົນເອງ, ທີ່ດີກວ່າ. ນີ້ຫມາຍຄວາມວ່າ UIDs ແມ່ນມາພ້ອມກັບ
ຊື່ຜູ້ໃຊ້, GIDs ແມ່ນມາພ້ອມກັບຊື່ກຸ່ມ, PIDs ແມ່ນມາພ້ອມກັບຂະບວນການ.
ຊື່, ຕົວອະທິບາຍໄຟລ໌ ແລະກະແສແມ່ນມາພ້ອມກັບຊື່ເສັ້ນທາງ, ແລະອື່ນໆ.
ເມື່ອແກ້ໄຂເສັ້ນທາງ, ຖ້າອົງປະກອບຂອງເສັ້ນທາງບໍ່ມີ, libexplain ຈະຊອກຫາທີ່ຄ້າຍຄືກັນ
ຊື່, ເພື່ອແນະນໍາທາງເລືອກສໍາລັບຄວາມຜິດພາດ typographical.
ຫ້ອງສະໝຸດ libexplain ພະຍາຍາມໃຊ້ heap ໜ້ອຍທີ່ສຸດເທົ່າທີ່ເປັນໄປໄດ້, ແລະປົກກະຕິແລ້ວບໍ່ມີ. ນີ້ແມ່ນ
ເພື່ອຫຼີກເວັ້ນການລົບກວນສະຖານະຂະບວນການ, ເທົ່າທີ່ເປັນໄປໄດ້, ເຖິງແມ່ນວ່າບາງຄັ້ງມັນກໍ່ເປັນ
ຫຼີກລ່ຽງບໍ່ໄດ້.
ຫ້ອງສະຫມຸດ libexplain ພະຍາຍາມທີ່ຈະປອດໄພ, ໂດຍການຫຼີກເວັ້ນຕົວແປທົ່ວໂລກ, ການຮັກສາ
ລັດໃນ stack ໄດ້ຫຼາຍເທົ່າທີ່ເປັນໄປໄດ້. ມີ buffer ຂໍ້ຄວາມທົ່ວໄປດຽວ, ແລະ
ຟັງຊັນທີ່ໃຊ້ມັນຖືກບັນທຶກໄວ້ວ່າບໍ່ປອດໄພ.
ຫ້ອງສະໝຸດ libexplain ບໍ່ລົບກວນຕົວຈັດການສັນຍານຂອງຂະບວນການ. ນີ້ເຮັດໃຫ້
ການກໍານົດວ່າຕົວຊີ້ຈະກໍານົດຄວາມຜິດຂອງສິ່ງທ້າທາຍ, ແຕ່ບໍ່ແມ່ນເປັນໄປບໍ່ໄດ້.
ເມື່ອຂໍ້ມູນມີໃຫ້ຜ່ານລະບົບການໂທເຊັ່ນດຽວກັນກັບມີຢູ່ຜ່ານ ກ / proc
ເຂົ້າ, ໂທລະບົບແມ່ນມັກ. ນີ້ແມ່ນເພື່ອຫຼີກເວັ້ນການລົບກວນສະຖານະຂອງຂະບວນການ.
ຍັງມີເວລາທີ່ບໍ່ມີຕົວອະທິບາຍໄຟລ໌ທີ່ມີຢູ່.
ຫ້ອງສະຫມຸດ libexplain ໄດ້ຖືກລວບລວມດ້ວຍການສະຫນັບສະຫນູນໄຟລ໌ຂະຫນາດໃຫຍ່. ບໍ່ມີຂະໜາດໃຫຍ່/ນ້ອຍ
ໂຣກຈິດ. ບ່ອນທີ່ນີ້ມີຜົນກະທົບຕໍ່ປະເພດການໂຕ້ຖຽງໃນ API, ແລະຂໍ້ຜິດພາດຈະຖືກອອກ
ຖ້າໄຟລ໌ຂະຫນາດໃຫຍ່ທີ່ຈໍາເປັນກໍານົດແມ່ນບໍ່ມີ.
FIXME: ຈໍາເປັນຕ້ອງເຮັດວຽກເພື່ອໃຫ້ແນ່ໃຈວ່າໂຄຕ້າລະບົບໄຟລ໌ຖືກຈັດການຢູ່ໃນລະຫັດ. ນີ້
ໃຊ້ໄດ້ກັບບາງຄົນ ຈຳກັດ(2) ຂອບເຂດ, ເຊັ່ນດຽວກັນ.
ມີກໍລະນີທີ່ເສັ້ນທາງຍາດພີ່ນ້ອງແມ່ນບໍ່ມີຂໍ້ມູນ. ຕົວຢ່າງ: ລະບົບ daemon,
ເຊີບເວີ ແລະຂະບວນການໃນພື້ນຫຼັງ. ໃນກໍລະນີເຫຼົ່ານີ້, ເສັ້ນທາງຢ່າງແທ້ຈິງຖືກນໍາໃຊ້ໃນຄວາມຜິດພາດ
ຄໍາອະທິບາຍ.
PATH ການແກ້ໄຂ
ສະບັບສັ້ນ: ເບິ່ງ ການແກ້ໄຂເສັ້ນທາງ(7).
ຮຸ່ນຍາວ: ຜູ້ໃຊ້ສ່ວນໃຫຍ່ບໍ່ເຄີຍໄດ້ຍິນ ການແກ້ໄຂເສັ້ນທາງ(7), ແລະຜູ້ໃຊ້ຂັ້ນສູງຈໍານວນຫຼາຍ
ບໍ່ເຄີຍອ່ານມັນ. ນີ້ແມ່ນສະບັບຫຍໍ້:
ຂັ້ນຕອນ 1: ເລີ່ມຕົ້ນ of ໄດ້ ການແກ້ໄຂ ຂະບວນການ
ຖ້າຊື່ເສັ້ນທາງເລີ່ມຕົ້ນດ້ວຍຕົວຫຍໍ້ (“/”), ໄດເລກະທໍລີຄົ້ນຫາເລີ່ມຕົ້ນແມ່ນ
ໄດເລກະທໍລີຮາກຂອງຂະບວນການໂທ.
ຖ້າຊື່ເສັ້ນທາງບໍ່ເລີ່ມຕົ້ນດ້ວຍຕົວຫຍໍ້ (“/”), ການຊອກຫາເລີ່ມຕົ້ນ
ໄດເລກະທໍລີຂອງຂະບວນການແກ້ໄຂແມ່ນໄດເລກະທໍລີທີ່ເຮັດວຽກໃນປະຈຸບັນຂອງຂະບວນການ.
ຂັ້ນຕອນ 2: ຍ່າງ ພ້ອມ ໄດ້ ເສັ້ນທາງ
ກໍານົດໄດເລກະທໍລີການຊອກຫາປະຈຸບັນເປັນໄດເລກະທໍລີການຄົ້ນຫາເລີ່ມຕົ້ນ. ໃນປັດຈຸບັນ, ສໍາລັບແຕ່ລະຄົນທີ່ບໍ່ແມ່ນ
ອົງປະກອບສຸດທ້າຍຂອງຊື່ເສັ້ນທາງ, ບ່ອນທີ່ອົງປະກອບເປັນ substring delimited ໂດຍ slash (“/”)
ຕົວອັກສອນ, ອົງປະກອບນີ້ຖືກຊອກຫາຢູ່ໃນໄດເລກະທໍລີການຊອກຫາໃນປະຈຸບັນ.
ຖ້າຂະບວນການບໍ່ມີການອະນຸຍາດຄົ້ນຫາຢູ່ໃນໄດເລກະທໍລີການຊອກຫາໃນປະຈຸບັນ, EACCES
ຂໍ້ຜິດພາດຖືກສົ່ງຄືນ ("ການອະນຸຍາດຖືກປະຕິເສດ").
open(pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) ລົ້ມເຫລວ,
ການອະນຸຍາດຖືກປະຕິເສດ (13, EACCES) ເພາະວ່າຂະບວນການດັ່ງກ່າວບໍ່ມີການອະນຸຍາດຄົ້ນຫາ
ໄປຫາຊື່ເສັ້ນທາງ "/home/archives/.ssh", ຂະບວນການທີ່ມີປະສິດທິພາບ GID 1000
"pmiller" ບໍ່ກົງກັບເຈົ້າຂອງໄດເລກະທໍລີ 1001 "archives" ດັ່ງນັ້ນເຈົ້າຂອງ
ຮູບແບບການອະນຸຍາດ "rwx" ແມ່ນຖືກລະເລີຍ, ຮູບແບບການອະນຸຍາດອື່ນໆແມ່ນ "--", ແລະ
ຂະບວນການບໍ່ໄດ້ຮັບສິດທິພິເສດ (ບໍ່ມີຄວາມສາມາດ DAC_READ_SEARCH)
ຖ້າອົງປະກອບບໍ່ພົບ, ຂໍ້ຜິດພາດ ENOENT ຈະຖືກສົ່ງຄືນ ("ບໍ່ມີໄຟລ໌ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ").
unlink(pathname = "/home/microsoft/rubbish") ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ (2,
ENOENT) ເນື່ອງຈາກວ່າບໍ່ມີໄດເລກະທໍລີ "microsoft" ໃນຊື່ເສັ້ນທາງ "/ ເຮືອນ"ໄດເລກະທໍລີ
ນອກຈາກນີ້ຍັງມີການສະຫນັບສະຫນູນບາງຢ່າງສໍາລັບຜູ້ໃຊ້ໃນເວລາທີ່ພວກເຂົາພິມຊື່ເສັ້ນທາງຜິດ, ເຮັດໃຫ້ຄໍາແນະນໍາໃນເວລາທີ່
ENOENT ຖືກສົ່ງຄືນ:
open(pathname = "/user/include/fcntl.h", flags = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ດັ່ງກ່າວ ຫຼື
ໄດເລກະທໍລີ (2, ENOENT) ເພາະວ່າບໍ່ມີໄດເລກະທໍລີ "ຜູ້ໃຊ້" ໃນຊື່ເສັ້ນທາງ "/"
ໄດເລກະທໍລີ, ເຈົ້າຫມາຍເຖິງໄດເລກະທໍລີ "usr" ແທນບໍ?
ຖ້າອົງປະກອບຖືກພົບເຫັນ, ແຕ່ບໍ່ແມ່ນໄດເລກະທໍລີຫຼືການເຊື່ອມຕໍ່ສັນຍາລັກ, ENOTDIR
ຂໍ້ຜິດພາດຖືກສົ່ງຄືນ ("ບໍ່ແມ່ນໄດເລກະທໍລີ").
open(pathname = "/home/pmiller/.netrc/lca", ທຸງ = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ແມ່ນ
directory (20, ENOTDIR) ເນື່ອງຈາກວ່າໄຟລ໌ປົກກະຕິ ".netrc" ໃນຊື່ເສັ້ນທາງ
ໄດເລກະທໍລີ "/home/pmiller" ຖືກໃຊ້ເປັນໄດເລກະທໍລີໃນເວລາທີ່ມັນບໍ່ແມ່ນ
ຖ້າອົງປະກອບຖືກພົບເຫັນແລະເປັນໄດເລກະທໍລີ, ພວກເຮົາກໍານົດໄດເລກະທໍລີການຊອກຫາໃນປະຈຸບັນເປັນສິ່ງນັ້ນ
ໄດເລກະທໍລີ, ແລະໄປທີ່ອົງປະກອບຕໍ່ໄປ.
ຖ້າອົງປະກອບຖືກພົບເຫັນແລະເປັນການເຊື່ອມໂຍງສັນຍາລັກ (symlink), ພວກເຮົາທໍາອິດແກ້ໄຂສັນຍາລັກນີ້
ເຊື່ອມຕໍ່ (ກັບໄດເລກະທໍລີຄົ້ນຫາປະຈຸບັນເປັນໄດເລກະທໍລີການຄົ້ນຫາເລີ່ມຕົ້ນ). ເມື່ອຜິດພາດ, ວ່າ
ຂໍ້ຜິດພາດຖືກສົ່ງຄືນ. ຖ້າຜົນໄດ້ຮັບບໍ່ແມ່ນໄດເລກະທໍລີ, ຂໍ້ຜິດພາດ ENOTDIR ຈະຖືກສົ່ງຄືນ.
unlink(pathname = "/tmp/dangling/rubbish") ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ ຫຼືໄດເລກະທໍລີດັ່ງກ່າວ (2,
ENOENT) ເນື່ອງຈາກວ່າການເຊື່ອມຕໍ່ສັນຍາລັກ "dangling" ໃນຊື່ເສັ້ນທາງ "/ tmp"ໄດເລກະທໍລີ
ຫມາຍເຖິງ "ບໍ່ມີບ່ອນໃດ" ທີ່ບໍ່ມີຢູ່
ຖ້າການແກ້ໄຂຂອງ symlink ປະສົບຜົນສໍາເລັດແລະສົ່ງຄືນໄດເລກະທໍລີ, ພວກເຮົາກໍານົດປະຈຸບັນ
ຊອກຫາລາຍການໄປຫາໄດເລກະທໍລີນັ້ນ, ແລະໄປທີ່ອົງປະກອບຕໍ່ໄປ. ໃຫ້ສັງເກດວ່າ
ຂະບວນການແກ້ໄຂຢູ່ທີ່ນີ້ກ່ຽວຂ້ອງກັບການເອີ້ນຄືນ. ເພື່ອປົກປ້ອງແກ່ນຈາກ stack
overflow, ແລະຍັງເພື່ອປ້ອງກັນການປະຕິເສດການບໍລິການ, ມີຂອບເຂດຈໍາກັດສູງສຸດ
ຄວາມເລິກ recursion, ແລະກ່ຽວກັບຈໍານວນສູງສຸດຂອງການເຊື່ອມຕໍ່ສັນຍາລັກປະຕິບັດຕາມ. ຄວາມຜິດພາດ ELOOP ແມ່ນ
ກັບຄືນມາເມື່ອສູງສຸດແມ່ນເກີນ ("ລະດັບການເຊື່ອມໂຍງສັນຍາລັກຫຼາຍເກີນໄປ").
open(pathname = "/tmp/dangling", ທຸງ = O_RDONLY) ລົ້ມເຫລວ, ມີລະດັບຫຼາຍເກີນໄປ.
ການເຊື່ອມຕໍ່ສັນຍາລັກ (40, ELOOP) ເນື່ອງຈາກວ່າ loop ເຊື່ອມຕໍ່ສັນຍາລັກໄດ້ພົບໃນ
ຊື່ເສັ້ນທາງ, ເລີ່ມຕົ້ນທີ່ "/tmp/dangling"
ມັນເປັນໄປໄດ້ທີ່ຈະໄດ້ຮັບຄວາມຜິດພາດ ELOOP ຫຼື EMLINK ຖ້າມີ symlinks ຫຼາຍເກີນໄປ, ແຕ່ບໍ່ມີ.
ກວດພົບ loop.
open(pathname = "/tmp/rabbit-hole", ທຸງ = O_RDONLY) ລົ້ມເຫລວ, ມີລະດັບຫຼາຍເກີນໄປ.
ການເຊື່ອມໂຍງສັນຍາລັກ (40, ELOOP) ເນື່ອງຈາກວ່າການເຊື່ອມຕໍ່ສັນຍາລັກຫຼາຍເກີນໄປໄດ້ຖືກພົບໃນ
ຊື່ເສັ້ນທາງ (8)
ສັງເກດເຫັນວິທີການຈໍາກັດຕົວຈິງແມ່ນພິມອອກ.
ຂັ້ນຕອນ 3: ຄົ້ນຫາ ໄດ້ ສຸດທ້າຍ entry
ການຊອກຫາອົງປະກອບສຸດທ້າຍຂອງຊື່ເສັ້ນທາງໄປຄືກັນກັບສິ່ງອື່ນໆທັງໝົດ
ອົງປະກອບ, ດັ່ງທີ່ໄດ້ອະທິບາຍໄວ້ໃນຂັ້ນຕອນທີ່ຜ່ານມາ, ມີສອງຄວາມແຕກຕ່າງ:
(i) ອົງປະກອບສຸດທ້າຍບໍ່ຈໍາເປັນຕ້ອງເປັນໄດເລກະທໍລີ (ຢ່າງຫນ້ອຍເທົ່າກັບການແກ້ໄຂເສັ້ນທາງ
ຂະບວນການແມ່ນເປັນຫ່ວງ. ມັນອາດຈະຕ້ອງເປັນໄດເລກະທໍລີ, ຫຼືບໍ່ແມ່ນໄດເລກະທໍລີ, ເພາະວ່າ
ຂໍ້ກໍານົດຂອງການໂທລະບົບສະເພາະ).
(ii)
ມັນບໍ່ຈໍາເປັນຕ້ອງມີຄວາມຜິດພາດຖ້າອົງປະກອບສຸດທ້າຍບໍ່ພົບ; ບາງທີພວກເຮົາພຽງແຕ່
ການສ້າງມັນ. ລາຍລະອຽດກ່ຽວກັບການປິ່ນປົວຂອງການເຂົ້າສຸດທ້າຍແມ່ນໄດ້ອະທິບາຍຢູ່ໃນ
ຫນ້າຄູ່ມືຂອງການໂທລະບົບສະເພາະ.
(iii)
ມັນຍັງເປັນໄປໄດ້ທີ່ຈະມີບັນຫາກັບອົງປະກອບສຸດທ້າຍຖ້າມັນເປັນການເຊື່ອມຕໍ່ສັນຍາລັກ
ແລະມັນບໍ່ຄວນປະຕິບັດຕາມ. ສໍາລັບຕົວຢ່າງ, ການນໍາໃຊ້ ເປີດ(2) ທຸງ O_NOFOLLOW:
open(pathname = "a-symlink", flags = O_RDONLY | O_NOFOLLOW) ລົ້ມເຫລວ, ມີລະດັບຫຼາຍເກີນໄປ.
ການເຊື່ອມຕໍ່ສັນຍາລັກ (ELOOP) ເນື່ອງຈາກວ່າ O_NOFOLLOW ຖືກລະບຸໄວ້ແຕ່ຊື່ເສັ້ນທາງຫມາຍເຖິງ a
ການເຊື່ອມຕໍ່ສັນຍາລັກ
(iv)
ມັນເປັນເລື່ອງທໍາມະດາສໍາລັບຜູ້ໃຊ້ທີ່ຈະເຮັດຜິດພາດໃນເວລາທີ່ພິມຊື່ເສັ້ນທາງ. ຫ້ອງສະຫມຸດ libexplain
ພະຍາຍາມໃຫ້ຄຳແນະນຳເມື່ອ ENOENT ຖືກສົ່ງຄືນ, ຕົວຢ່າງ:
open(pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ດັ່ງກ່າວ ຫຼື
directory (2, ENOENT) ເນື່ອງຈາກວ່າບໍ່ມີ "filecontrl.h" ໄຟລ໌ປົກກະຕິໃນຊື່ເສັ້ນທາງ
"/ usr / ປະກອບມີ" directory, ເຈົ້າຫມາຍຄວາມວ່າ "fcntl.h" ໄຟລ໌ປົກກະຕິແທນບໍ?
(v) ມັນເປັນໄປໄດ້ວ່າອົງປະກອບສຸດທ້າຍແມ່ນຕ້ອງການເປັນສິ່ງອື່ນນອກຈາກ a
ໄຟລ໌ປົກກະຕິ:
readlink(pathname = "just-a-file", data = 0x7F930A50, data_size = 4097) ລົ້ມເຫລວ,
ການໂຕ້ຖຽງບໍ່ຖືກຕ້ອງ (22, EINVAL) ເພາະວ່າຊື່ເສັ້ນທາງເປັນໄຟລ໌ປົກກະຕິ, ບໍ່ແມ່ນການເຊື່ອມຕໍ່ສັນຍາລັກ
(vi)
FIXME: ການຈັດການບິດ "t".
ຈໍາກັດ
ມີຈໍານວນຈໍາກັດກ່ຽວກັບຊື່ເສັ້ນທາງແລະຊື່ໄຟລ໌.
ຂີດຈຳກັດຄວາມຍາວຂອງຊື່
ມີຄວາມຍາວສູງສຸດສໍາລັບຊື່ເສັ້ນທາງ. ຖ້າຊື່ເສັ້ນທາງ (ຫຼືບາງລະດັບປານກາງ
ຊື່ເສັ້ນທາງທີ່ໄດ້ຮັບໃນຂະນະທີ່ການແກ້ໄຂການເຊື່ອມຕໍ່ສັນຍາລັກ) ຍາວເກີນໄປ, ເປັນ ENAMETOOLONG
ຂໍ້ຜິດພາດຖືກສົ່ງຄືນ ("ຊື່ໄຟລ໌ຍາວເກີນໄປ"). ສັງເກດເຫັນວິທີການຈໍາກັດລະບົບລວມ
ໃນຂໍ້ຄວາມຜິດພາດ.
ເປີດ(ຊື່ເສັ້ນທາງ = "ຫຼາຍ...ຍາວ", flags = O_RDONLY) ລົ້ມເຫລວ, ຊື່ໄຟລ໌ຍາວເກີນໄປ (36,
ENAMETOOLONG) ເພາະວ່າຊື່ເສັ້ນທາງເກີນຄວາມຍາວສູງສຸດຂອງລະບົບ (4096)
ຈຳກັດຄວາມຍາວຂອງຊື່ໄຟລ໌
ບາງຕົວແປຂອງ Unix ມີຂອບເຂດຈໍາກັດກ່ຽວກັບຈໍານວນ bytes ໃນແຕ່ລະອົງປະກອບເສັ້ນທາງ.
ບາງຄົນຈັດການກັບເລື່ອງນີ້ຢ່າງງຽບໆ, ແລະບາງຄົນກໍ່ໃຫ້ ENAMETOOLONG; lib ອະທິບາຍ
ການນໍາໃຊ້ຫ້ອງສະຫມຸດ pathconf(3) _PC_NO_TRUNC ບອກອັນໃດ. ຖ້າຫາກວ່າຄວາມຜິດພາດນີ້ເກີດຂຶ້ນ, ໄດ້
ຫ້ອງສະຫມຸດ libexplain ຈະລະບຸຂອບເຂດຈໍາກັດໃນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ, ຂອບເຂດຈໍາກັດແມ່ນ
ໄດ້ມາຈາກ pathconf(3) _PC_NAME_MAX. ສັງເກດເຫັນວິທີການຈໍາກັດລະບົບລວມ
ໃນຂໍ້ຄວາມຜິດພາດ.
ເປີດ(ຊື່ເສັ້ນທາງ = "system7/only-had-14-ຕົວອັກສອນ", flags = O_RDONLY) ລົ້ມເຫລວ, ໄຟລ໌
ຊື່ຍາວເກີນໄປ (36, ENAMETOOLONG) ເນື່ອງຈາກວ່າອົງປະກອບ "ພຽງແຕ່-had-14-ຕົວອັກສອນ" ແມ່ນ
ຍາວເກີນຂອບເຂດຈໍາກັດ (14)
ຊື່ເສັ້ນທາງຫວ່າງເປົ່າ
ໃນ Unix ຕົ້ນສະບັບ, ຊື່ເສັ້ນທາງເປົ່າຫມາຍເຖິງໄດເລກະທໍລີປະຈຸບັນ.
ໃນປັດຈຸບັນ POSIX ດຳລັດວ່າຊື່ເສັ້ນທາງເປົ່າຕ້ອງບໍ່ໄດ້ຮັບການແກ້ໄຂຢ່າງສໍາເລັດຜົນ.
open(pathname = "", flags = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ມີໄຟລ໌ ຫຼື directory ດັ່ງກ່າວ (2,
ENOENT) ເພາະວ່າ POSIX ດຳລັດວ່າຊື່ເສັ້ນທາງເປົ່າຕ້ອງບໍ່ໄດ້ຮັບການແກ້ໄຂ
ສົບຜົນສໍາເລັດ
Permissions
bits ການອະນຸຍາດຂອງໄຟລ໌ປະກອບດ້ວຍສາມກຸ່ມຂອງສາມ bits. ກຸ່ມທໍາອິດຂອງ
ສາມຖືກນໍາໃຊ້ໃນເວລາທີ່ ID ຜູ້ໃຊ້ທີ່ມີປະສິດທິພາບຂອງຂະບວນການໂທຫາເທົ່າກັບ ID ເຈົ້າຂອງ
ໄຟລ໌. ກຸ່ມທີສອງຂອງສາມແມ່ນໃຊ້ເມື່ອ ID ກຸ່ມຂອງໄຟລ໌ທັງສອງເທົ່າກັບ
ID ກຸ່ມທີ່ມີປະສິດທິພາບຂອງຂະບວນການໂທ, ຫຼືເປັນຫນຶ່ງໃນ ID ກຸ່ມເສີມຂອງ
ຂະບວນການໂທ. ໃນເວລາທີ່ທັງສອງບໍ່ຖື, ກຸ່ມທີສາມຖືກນໍາໃຊ້.
ເປີດ(ຊື່ເສັ້ນທາງ = "/ etc / passwd", flags = O_WRONLY) ລົ້ມເຫລວ, ການອະນຸຍາດຖືກປະຕິເສດ (13,
EACCES) ເນື່ອງຈາກວ່າຂະບວນການບໍ່ມີການອະນຸຍາດໃຫ້ຂຽນ "passwd" ປົກກະຕິ
ໄຟລ໌ໃນຊື່ເສັ້ນທາງ "/ ແລະອື່ນໆ"ໄດເລກະທໍລີ, ຂະບວນການທີ່ມີປະສິດທິພາບ UID 1000 "pmiller"
ບໍ່ກົງກັບເຈົ້າຂອງໄຟລ໌ປົກກະຕິ 0 "ຮາກ" ດັ່ງນັ້ນຮູບແບບການອະນຸຍາດເຈົ້າຂອງ "rw-"
ຖືກລະເລີຍ, ຮູບແບບການອະນຸຍາດອື່ນໆແມ່ນ "r--", ແລະຂະບວນການບໍ່ໄດ້ຮັບສິດທິພິເສດ
(ບໍ່ມີຄວາມສາມາດ DAC_OVERRIDE)
ບາງພື້ນທີ່ຫຼາຍແມ່ນໃຫ້ຄໍາອະທິບາຍນີ້, ຍ້ອນວ່າຜູ້ໃຊ້ສ່ວນໃຫຍ່ບໍ່ຮູ້ວ່ານີ້
ແມ່ນວິທີທີ່ລະບົບການອະນຸຍາດເຮັດວຽກ. ໂດຍສະເພາະ: ເຈົ້າຂອງ, ກຸ່ມແລະອື່ນໆ
ການອະນຸຍາດແມ່ນສະເພາະ, ພວກເຂົາເຈົ້າບໍ່ "ຫຼື"ed ຮ່ວມກັນ.
ແຂງແຮງ ແລະ ການສົນທະນາ SYSTEM ທີ່ເອີ້ນ
ຂະບວນການຂຽນຕົວຈັດການຂໍ້ຜິດພາດສະເພາະສໍາລັບການເອີ້ນລະບົບແຕ່ລະຄັ້ງມັກຈະເປີດເຜີຍ
quirks ທີ່ຫນ້າສົນໃຈແລະເງື່ອນໄຂຂອງເຂດແດນ, ຫຼືບໍ່ເຫັນແຈ້ງ ຜິດພາດ(3) ຄ່າ.
ENOMEDIUM, No ຂະຫນາດກາງ ພົບເຫັນ
ການກະທໍາຂອງການຄັດລອກແຜ່ນຊີດີແມ່ນແຫຼ່ງຂອງຫົວຂໍ້ສໍາລັບເອກະສານນີ້.
$ dd ຖ້າ =/dev/cdrom of=fubar.iso
dd: ເປີດ “/dev/cdrom”: ບໍ່ພົບສື່
$
ຜູ້ຂຽນສົງໄສວ່າເປັນຫຍັງຄອມພິວເຕີຂອງລາວຈຶ່ງບອກລາວວ່າບໍ່ມີສິ່ງດັ່ງກ່າວເປັນ psychic
ກາງ. ນອກ ເໜືອ ຈາກຄວາມຈິງທີ່ວ່າຜູ້ເວົ້າພາສາອັງກິດພື້ນເມືອງ ຈຳ ນວນຫຼວງຫຼາຍບໍ່ແມ່ນ
ເຖິງແມ່ນວ່າຮູ້ວ່າ "ສື່ມວນຊົນ" ແມ່ນຫຼາຍພາສາ, ປ່ອຍໃຫ້ຢູ່ຄົນດຽວວ່າ "ຂະຫນາດກາງ" ແມ່ນຄໍານາມ, ສະຕິງ.
ກັບຄືນໂດຍ ຄວາມຜິດພາດ(3) ສໍາລັບ ENOMEDIUM ແມ່ນ terse ເປັນທີ່ຈະເກືອບຫມົດຂອງ
ເນື້ອໃນ.
ເມື່ອໃດ ເປີດ(2) ກັບຄືນ ENOMEDIUM ມັນຈະດີຖ້າຫ້ອງສະຫມຸດ libexplain ສາມາດຂະຫຍາຍ a
ພຽງເລັກນ້ອຍກ່ຽວກັບເລື່ອງນີ້, ອີງຕາມປະເພດຂອງການຂັບມັນແມ່ນ. ຍົກຕົວຢ່າງ:
... ເນື່ອງຈາກວ່າບໍ່ມີແຜ່ນຢູ່ໃນ floppy drive
... ເນື່ອງຈາກວ່າບໍ່ມີແຜ່ນໃນ CD-ROM drive
... ເພາະວ່າບໍ່ມີເທບໃນໄດເທບ
... ເນື່ອງຈາກວ່າບໍ່ມີ memory stick ໃນເຄື່ອງອ່ານກາດ
ແລະສະນັ້ນມັນໄດ້ບັງເກີດຂຶ້ນ ...
open(pathname = "/dev/cdrom", ທຸງ = O_RDONLY) ລົ້ມເຫລວ, ບໍ່ພົບສື່ກາງ (123,
ENOMEDIUM) ເພາະວ່າບໍ່ປະກົດວ່າມີແຜ່ນຢູ່ໃນແຜ່ນ CD-ROM
ເຄັດລັບ, ທີ່ຜູ້ຂຽນບໍ່ຮູ້ມາກ່ອນ, ແມ່ນການເປີດອຸປະກອນໂດຍໃຊ້
ທຸງ O_NONBLOCK, ເຊິ່ງຈະເຮັດໃຫ້ທ່ານສາມາດເປີດໄດຣຟ໌ທີ່ບໍ່ມີສື່ກາງຢູ່ໃນນັ້ນ. ແລ້ວເຈົ້າ
ອອກອຸປະກອນສະເພາະ ioctls(2) ຮ້ອງຂໍຈົນກວ່າທ່ານຈະຄິດອອກວ່າ heck ມັນແມ່ນຫຍັງ. (ບໍ່
ໃຫ້ແນ່ໃຈວ່ານີ້ແມ່ນ POSIX, ແຕ່ວ່າມັນຍັງເບິ່ງຄືວ່າຈະເຮັດວຽກແບບນັ້ນໃນ BSD ແລະ Solaris, ອີງຕາມ
ໄດ້ ວອມ(1) ແຫຼ່ງຂໍ້ມູນ.
ໃຫ້ສັງເກດວ່າການນໍາໃຊ້ທີ່ແຕກຕ່າງກັນຂອງ "ແຜ່ນ" ແລະ "ແຜ່ນ" ໃນສະພາບການ. ມາດຕະຖານ CD ມາຈາກ
ໃນປະເທດຝຣັ່ງ, ແຕ່ທຸກສິ່ງທຸກຢ່າງມີ "k".
ບໍ່ໄດ້ຜົນ, ບໍ່ດີ ທີ່ຢູ່
ການໂທລະບົບໃດນຶ່ງທີ່ໃຊ້ການໂຕ້ຖຽງຕົວຊີ້ສາມາດສົ່ງຄືນ EFAULT. ຫ້ອງສະຫມຸດ libexplain
ສາມາດຄິດອອກວ່າການໂຕ້ຖຽງແມ່ນຜິດພາດ, ແລະມັນເຮັດໄດ້ໂດຍບໍ່ມີການລົບກວນຂະບວນການ
(ຫຼື thread) ການຈັດການສັນຍານ.
ໃນເວລາທີ່ມີ, ໄດ້ ຄະແນນຕ່ຳ(2) ການໂທລະບົບຖືກນໍາໃຊ້, ເພື່ອຖາມວ່າພາກພື້ນຫນ່ວຍຄວາມຈໍາຖືກຕ້ອງ.
ມັນສາມາດສົ່ງຄືນຜົນໄດ້ຮັບສາມຢ່າງ: ແຜນທີ່ແຕ່ບໍ່ແມ່ນຢູ່ໃນຄວາມຊົງຈໍາທາງດ້ານຮ່າງກາຍ, ແຜນທີ່ແລະທາງດ້ານຮ່າງກາຍ
ຄວາມຊົງຈໍາ, ແລະບໍ່ໄດ້ເຮັດແຜນທີ່. ເມື່ອທົດສອບຄວາມຖືກຕ້ອງຂອງຕົວຊີ້, ສອງອັນທໍາອິດແມ່ນ "ແມ່ນ"
ແລະອັນສຸດທ້າຍແມ່ນ "ບໍ່".
ການກວດສອບສາຍ C ແມ່ນຍາກກວ່າ, ເພາະວ່າແທນທີ່ຈະເປັນຕົວຊີ້ແລະຂະຫນາດ, ພວກເຮົາພຽງແຕ່
ມີຕົວຊີ້. ເພື່ອກໍານົດຂະຫນາດທີ່ພວກເຮົາຈະຕ້ອງຊອກຫາ NUL, ແລະມັນສາມາດເຮັດໄດ້
segfault, catch-22.
ເພື່ອເຮັດວຽກນີ້, ຫ້ອງສະຫມຸດ libexplain ໃຊ້ ສະຖິຕິ(2) sysem call (ມີທີ່ຮູ້ຈັກ
ການໂຕ້ຖຽງທີສອງທີ່ດີ) ເພື່ອທົດສອບ C strings ສໍາລັບຄວາມຖືກຕ້ອງ. ກັບຄືນຄວາມລົ້ມເຫຼວ && errno == EFAULT
ແມ່ນ "ບໍ່", ແລະອັນອື່ນແມ່ນ "ແມ່ນ". ອັນນີ້, ແນ່ນອນຈໍາກັດສະຕຣິງໃຫ້ PATH_MAX
ຕົວອັກສອນ, ແຕ່ປົກກະຕິແລ້ວນັ້ນບໍ່ແມ່ນບັນຫາສໍາລັບຫ້ອງສະຫມຸດ libexplain, ເພາະວ່ານັ້ນແມ່ນ
ເກືອບສະເໝີເປັນສາຍທີ່ຍາວທີ່ສຸດທີ່ມັນສົນໃຈ.
ໄຟລ໌ອີເມລ໌, ເກີນໄປ ຈໍານວນຫຼາຍ ເປີດ ໄຟ
ຄວາມຜິດພາດນີ້ເກີດຂຶ້ນເມື່ອຂະບວນການມີຈໍານວນຕົວອະທິບາຍໄຟລ໌ສູງສຸດແລ້ວເປີດ.
ຖ້າຂອບເຂດຈໍາກັດຕົວຈິງຈະຖືກພິມ, ແລະຫ້ອງສະຫມຸດ libexplain ພະຍາຍາມ, ທ່ານບໍ່ສາມາດເປີດໄດ້
ໄຟລ໌ໃນ / proc ເພື່ອອ່ານວ່າມັນແມ່ນຫຍັງ.
open_max = sysconf(_SC_OPEN_MAX);
ອັນນີ້ບໍ່ຍາກຫຼາຍ, ມີ sysconf(3) ວິທີການໄດ້ຮັບຂອບເຂດຈໍາກັດ.
ENFILE, ເກີນໄປ ຈໍານວນຫຼາຍ ເປີດ ໄຟ in ລະບົບ
ຄວາມຜິດພາດນີ້ເກີດຂຶ້ນເມື່ອລະບົບຈໍາກັດຈໍານວນໄຟລ໌ເປີດທັງຫມົດ
ຮອດ. ໃນກໍລະນີດັ່ງກ່າວນີ້, ບໍ່ມີມື sysconf(3) ວິທີການໄດ້ຮັບຂອບເຂດຈໍາກັດ.
ການຂຸດຂຸມເລິກ, ຫນຶ່ງອາດຈະຄົ້ນພົບວ່າຢູ່ໃນ Linux ມີ / proc ເຂົ້າທີ່ພວກເຮົາສາມາດອ່ານໄດ້
ໄດ້ຮັບຄ່ານີ້. Catch-22: ພວກເຮົາບໍ່ມີຕົວອະທິບາຍໄຟລ໌, ດັ່ງນັ້ນພວກເຮົາບໍ່ສາມາດເປີດໄຟລ໌ໄປຫາ
ອ່ານຂອບເຂດຈໍາກັດ.
ໃນ Linux ມີການໂທຫາລະບົບເພື່ອໃຫ້ໄດ້ມັນ, ແຕ່ມັນບໍ່ມີ [e] glibc wrapper function, ດັ່ງນັ້ນ.
ທ່ານມີທັງຫມົດມັນລະມັດລະວັງຫຼາຍ:
ຍາວ
explain_maxfile(void)
{
#ifdef __linux__
struct __sysctl_args args;
int32_t maxfile;
size_t maxfile_size = ຂະຫນາດຂອງ(maxfile);
int name[] = { CTL_FS, FS_MAXFILE };
memset(&args, 0, sizeof(struct __sysctl_args));
args.name = ຊື່;
args.nlen = 2;
args.oldval = &maxfile;
args.oldlenp = &maxfile_size;
ຖ້າ (syscall(SYS__sysctl, &args) >= 0)
ສົ່ງຄືນ maxfile;
#ສຸດທ້າຍ
ກັບຄືນ -1;
}
ນີ້ອະນຸຍາດໃຫ້ຈໍາກັດການລວມຢູ່ໃນຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດ, ເມື່ອມີ.
EINVAL “ບໍ່ຖືກຕ້ອງ ການໂຕ້ຖຽງ” vs ENOSYS “ຟັງຊັນ ບໍ່ ປະຕິບັດ”
ການກະທຳທີ່ບໍ່ຮອງຮັບ (ເຊັ່ນ: symlink(2) ໃນລະບົບໄຟລ໌ FAT) ບໍ່ໄດ້ຖືກລາຍງານ
ຢ່າງຕໍ່ເນື່ອງຈາກການໂທລະບົບຫນຶ່ງໄປຫາຕໍ່ໄປ. ມັນເປັນໄປໄດ້ທີ່ຈະມີທັງ EINVAL ຫຼື
ENOSYS ກັບຄືນມາ.
ດັ່ງນັ້ນ, ຕ້ອງເອົາໃຈໃສ່ກັບກໍລະນີຄວາມຜິດພາດເຫຼົ່ານີ້ເພື່ອໃຫ້ຖືກຕ້ອງ, ໂດຍສະເພາະ
ເນື່ອງຈາກວ່າ EINVAL ຍັງສາມາດອ້າງອີງເຖິງບັນຫາທີ່ມີຫນຶ່ງຫຼືຫຼາຍການໂຕ້ຖຽງການໂທລະບົບ.
ຫມາຍເຫດ ທີ່ ຜິດພາດ(3) is ບໍ່ ສະເຫມີໄປ ທີ່ກໍານົດໄວ້
ມີບາງຄັ້ງທີ່ມັນຈໍາເປັນຕ້ອງອ່ານແຫຼ່ງ [e]glibc ເພື່ອກໍານົດວິທີການແລະ
ເມື່ອຂໍ້ຜິດພາດຖືກສົ່ງຄືນສໍາລັບບາງການໂທລະບົບ.
feof(3) fileno(3)
ມັນມັກຈະສົມມຸດວ່າຫນ້າທີ່ເຫຼົ່ານີ້ບໍ່ສາມາດສົ່ງຄືນຂໍ້ຜິດພາດໄດ້. ນີ້ແມ່ນພຽງແຕ່ຖ້າຫາກວ່າ
ໄດ້ ນ້ໍາ argument ແມ່ນຖືກຕ້ອງ, ຢ່າງໃດກໍຕາມ, ພວກເຂົາເຈົ້າສາມາດກວດພົບບໍ່ຖືກຕ້ອງ
ຕົວຊີ້.
fpathconf(3) pathconf(3)
ມູນຄ່າກັບຄືນຂອງ fpathconf(2) ແລະ pathconf(2) ສາມາດເປັນ -1 ຢ່າງຖືກຕ້ອງ, ດັ່ງນັ້ນມັນແມ່ນ
ມີຄວາມຈໍາເປັນເພື່ອເບິ່ງວ່າ ຜິດພາດ(3) ໄດ້ຖືກກໍານົດຢ່າງຈະແຈ້ງ.
ioctls(2)
ມູນຄ່າກັບຄືນຂອງ ioctls(2) ສາມາດເປັນ -1 ຢ່າງຖືກຕ້ອງ, ສະນັ້ນມັນຈໍາເປັນຕ້ອງເບິ່ງວ່າ
ຜິດພາດ(3) ໄດ້ຖືກກໍານົດຢ່າງຈະແຈ້ງ.
ອ່ານ(3)
ມູນຄ່າກັບຄືນຂອງ ອ່ານ(3) ແມ່ນ NULL ສໍາລັບທັງສອງຂໍ້ຜິດພາດ ແລະໄຟລ໌ສິ້ນສຸດ. ມັນແມ່ນ
ມີຄວາມຈໍາເປັນເພື່ອເບິ່ງວ່າ ຜິດພາດ(3) ໄດ້ຖືກກໍານົດຢ່າງຈະແຈ້ງ.
setbuf(3) setbuffer(3) setlinebuf(3) setvbuf(3)
ທັງໝົດແຕ່ສຸດທ້າຍຂອງໜ້າທີ່ເຫຼົ່ານີ້ກັບຄືນມາເປັນໂມຄະ. ແລະ setvbuf(3) ເປັນເອກະສານພຽງແຕ່ເປັນ
ກັບຄືນ "ບໍ່ແມ່ນສູນ" ດ້ວຍຄວາມຜິດພາດ. ມັນເປັນສິ່ງຈໍາເປັນເພື່ອເບິ່ງວ່າ ຜິດພາດ(3) ໄດ້ຢ່າງຈະແຈ້ງ
ຕັ້ງ.
strtod(3) Strtol(3) strtold(3) sttoll(3) strtoul(3) strtoull(3)
ຟັງຊັນເຫຼົ່ານີ້ສົ່ງຄືນຄ່າ 0 ດ້ວຍຄວາມຜິດພາດ, ແຕ່ນັ້ນກໍ່ແມ່ນຄ່າຕອບແທນທີ່ຖືກຕ້ອງຕາມກົດໝາຍ. ມັນແມ່ນ
ມີຄວາມຈໍາເປັນເພື່ອເບິ່ງວ່າ ຜິດພາດ(3) ໄດ້ຖືກກໍານົດຢ່າງຈະແຈ້ງ.
unget ອື່ນໆ(3)
ໃນຂະນະທີ່ພຽງແຕ່ລັກສະນະດຽວຂອງການສໍາຮອງຂໍ້ມູນໄດ້ຖືກບັງຄັບໂດຍມາດຕະຖານ ANSI C, ມັນປ່ຽນໄປ
ອອກມາວ່າ [e]glibc ອະນຸຍາດໃຫ້ຫຼາຍກວ່າ ... ແຕ່ນັ້ນຫມາຍຄວາມວ່າມັນສາມາດລົ້ມເຫລວກັບ ENOMEM. ມັນສາມາດ
ຍັງລົ້ມເຫລວກັບ EBADF ຖ້າ fp ແມ່ນປອມ. ຄວາມຫຍຸ້ງຍາກທີ່ສຸດ, ຖ້າທ່ານຜ່ານ EOF ຜິດພາດ
ການກັບຄືນເກີດຂື້ນ, ແຕ່ errno ບໍ່ໄດ້ຖືກກໍານົດ.
ຫ້ອງສະຫມຸດ libexplain ກວດພົບຂໍ້ຜິດພາດເຫຼົ່ານີ້ຢ່າງຖືກຕ້ອງ, ເຖິງແມ່ນວ່າໃນກໍລະນີທີ່ມີ
ຄ່າຄວາມຜິດພາດແມ່ນບັນທຶກບໍ່ດີ, ຖ້າຢູ່ໃນທັງຫມົດ.
ENOSPC, No ຊ່ອງ ໄວ້ on ອຸປະກອນ
ເມື່ອຂໍ້ຜິດພາດນີ້ຫມາຍເຖິງໄຟລ໌ໃນລະບົບໄຟລ໌, ຫ້ອງສະຫມຸດ libexplain ຈະພິມຕົວເຊື່ອມຕໍ່
ຈຸດຂອງລະບົບໄຟລ໌ທີ່ມີບັນຫາ. ນີ້ສາມາດເຮັດໃຫ້ແຫຼ່ງຂອງຄວາມຜິດພາດຫຼາຍ
ຈະແຈ້ງກວ່າ.
write(fildes = 1 "ຕົວຢ່າງ", data = 0xbfff2340, data_size = 5) ລົ້ມເຫລວ, ບໍ່ມີຊ່ອງຫວ່າງ
ຢູ່ໃນອຸປະກອນ (28, ENOSPC) ເພາະວ່າລະບົບໄຟລ໌ທີ່ບັນຈຸໄຟລ໌ ("/ ເຮືອນ") ບໍ່ມີ
ພື້ນທີ່ເພີ່ມເຕີມສໍາລັບຂໍ້ມູນ
ເນື່ອງຈາກການຮອງຮັບອຸປະກອນພິເສດຫຼາຍຂຶ້ນ, ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດຄາດວ່າຈະລວມເອົາອຸປະກອນ
ຊື່ແລະຂະຫນາດຕົວຈິງຂອງອຸປະກອນ.
EROFS, ອ່ານຢ່າງດຽວ ເອກະສານ ລະບົບ
ເມື່ອຂໍ້ຜິດພາດນີ້ຫມາຍເຖິງໄຟລ໌ໃນລະບົບໄຟລ໌, ຫ້ອງສະຫມຸດ libexplain ຈະພິມຕົວເຊື່ອມຕໍ່
ຈຸດຂອງລະບົບໄຟລ໌ທີ່ມີບັນຫາ. ນີ້ສາມາດເຮັດໃຫ້ແຫຼ່ງຂອງຄວາມຜິດພາດຫຼາຍ
ຈະແຈ້ງກວ່າ.
ເນື່ອງຈາກການຮອງຮັບອຸປະກອນພິເສດຫຼາຍຂຶ້ນ, ຂໍ້ຄວາມສະແດງຂໍ້ຜິດພາດຄາດວ່າຈະລວມເອົາອຸປະກອນ
ຊື່ແລະປະເພດ.
open(pathname = "/dev/fd0", O_RDWR, 0666) ລົ້ມເຫລວ, ລະບົບໄຟລ໌ອ່ານເທົ່ານັ້ນ (30, EROFS)
ເນື່ອງຈາກວ່າແຜ່ນ floppy disk ມີແຖບປ້ອງກັນການຂຽນ
...ເພາະ CD-ROM ບໍ່ສາມາດຂຽນໄດ້
...ເນື່ອງຈາກວ່າແຜ່ນຄວາມຊົງຈໍາທີ່ມີແຖບປົກປັກຮັກສາ write ໄດ້ຕັ້ງໄວ້
...ເພາະວ່າເທບແມ່ເຫຼັກ ½ ນິ້ວບໍ່ມີແຫວນຂຽນ
ປ່ຽນຊື່
ໄດ້ ປ່ຽນຊື່(2) ການໂທລະບົບຖືກນໍາໃຊ້ເພື່ອປ່ຽນສະຖານທີ່ຫຼືຊື່ຂອງໄຟລ໌, ຍ້າຍມັນ
ລະຫວ່າງໄດເລກະທໍລີຖ້າຕ້ອງການ. ຖ້າຊື່ເສັ້ນທາງປາຍທາງມີຢູ່ແລ້ວ ມັນຈະເປັນ
ທົດແທນດ້ວຍປະລໍາມະນູ, ດັ່ງນັ້ນບໍ່ມີຈຸດໃດທີ່ຂະບວນການອື່ນພະຍາຍາມ
ເຂົ້າເຖິງມັນຈະພົບວ່າມັນຂາດຫາຍໄປ.
ຢ່າງໃດກໍຕາມ, ມີຂໍ້ຈໍາກັດ: ທ່ານພຽງແຕ່ສາມາດປ່ຽນຊື່ໄດເລກະທໍລີຢູ່ເທິງຂອງອື່ນ
ໄດເລກະທໍລີຖ້າໄດເລກະທໍລີປາຍທາງບໍ່ຫວ່າງເປົ່າ.
rename(oldpath = "foo", newpath = "bar") ລົ້ມເຫລວ, Directory ບໍ່ຫວ່າງເປົ່າ (39,
ENOTEMPTY) ເນື່ອງຈາກວ່າ newpath ບໍ່ແມ່ນ directory ຫວ່າງເປົ່າ; ນັ້ນແມ່ນ, ມັນປະກອບດ້ວຍລາຍການ
ນອກຈາກ "." ແລະ ".."
ທ່ານບໍ່ສາມາດປ່ຽນຊື່ໄດເລກະທໍລີຢູ່ເທິງສຸດຂອງລາຍການທີ່ບໍ່ແມ່ນໄດເລກະທໍລີ, ຄືກັນ.
rename(oldpath = "foo", newpath = "bar") ລົ້ມເຫລວ, ບໍ່ແມ່ນ directory (20, ENOTDIR)
ເນື່ອງຈາກວ່າ oldpath ແມ່ນໄດເລກະທໍລີ, ແຕ່ newpath ແມ່ນໄຟລ໌ປົກກະຕິ, ບໍ່ແມ່ນໄດເລກະທໍລີ
ທັງບໍ່ແມ່ນການປີ້ນກັບກັນໄດ້ອະນຸຍາດໃຫ້
rename(oldpath = "foo", newpath = "bar") ລົ້ມເຫລວ, ເປັນໄດເລກະທໍລີ (21, EISDIR)
ເນື່ອງຈາກວ່າ newpath ແມ່ນໄດເລກະທໍລີ, ແຕ່ oldpath ແມ່ນໄຟລ໌ປົກກະຕິ, ບໍ່ແມ່ນໄດເລກະທໍລີ
ນີ້, ແນ່ນອນ, ເຮັດໃຫ້ວຽກຂອງຫ້ອງສະຫມຸດ libexplain ສັບສົນຫຼາຍ, ເພາະວ່າ
ຍົກເລີກການເຊື່ອມຕໍ່(2) ຫຼື ແມ່ນ rm(2) ການໂທລະບົບແມ່ນເອີ້ນວ່າ implicitly ໂດຍ ປ່ຽນຊື່(2), ແລະອື່ນໆທັງຫມົດຂອງ
ຍົກເລີກການເຊື່ອມຕໍ່(2) ຫຼື ແມ່ນ rm(2) ຄວາມຜິດພາດຕ້ອງໄດ້ຮັບການກວດພົບແລະຈັດການ, ເຊັ່ນດຽວກັນ.
dup2
ໄດ້ dup2(2) ການໂທລະບົບແມ່ນໃຊ້ເພື່ອສ້າງຕົວອະທິບາຍໄຟລ໌ທີສອງທີ່ອ້າງອີງເຖິງ
ວັດຖຸດຽວກັນກັບຕົວອະທິບາຍໄຟລ໌ທໍາອິດ. ໂດຍປົກກະຕິແລ້ວ ອັນນີ້ຖືກໃຊ້ເພື່ອປະຕິບັດການປ້ອນຂໍ້ມູນຂອງແກະ
ແລະການປ່ຽນເສັ້ນທາງຜົນຜະລິດ.
ສິ່ງທີ່ມ່ວນແມ່ນວ່າ, ຄືກັນກັບ ປ່ຽນຊື່(2) ປະລໍາມະນູສາມາດປ່ຽນຊື່ໄຟລ໌ຢູ່ເທິງຂອງການ
ໄຟລ໌ທີ່ມີຢູ່ແລ້ວແລະເອົາໄຟລ໌ເກົ່າອອກ, dup2(2) ສາມາດເຮັດສິ່ງນີ້ໃສ່ໄຟລ໌ທີ່ເປີດແລ້ວ
ຕົວອະທິບາຍ.
ອີກເທື່ອຫນຶ່ງ, ນີ້ເຮັດໃຫ້ວຽກຂອງຫ້ອງສະຫມຸດ libexplain ສັບສົນຫຼາຍ, ເພາະວ່າ ໃກ້(2)
ການໂທລະບົບແມ່ນເອີ້ນວ່າ implicitly ໂດຍ dup2(2), ແລະອື່ນໆທັງຫມົດຂອງ ໃກ້(2) ຄວາມຜິດພາດຂອງຈະຕ້ອງເປັນ
ກວດພົບແລະຈັດການ, ເຊັ່ນດຽວກັນ.
ເລື່ອງຮາວທີ່ແປງ IN IOCTL ສະຫນັບສະຫນູນ
ໄດ້ ioctls(2) ການໂທຫາລະບົບໃຫ້ຜູ້ຂຽນໄດເວີອຸປະກອນທີ່ມີວິທີການຕິດຕໍ່ສື່ສານກັບ
user-space ທີ່ບໍ່ເຫມາະພາຍໃນ kernel API ທີ່ມີຢູ່ແລ້ວ. ເບິ່ງ ioctl_list(2).
ການຖອດລະຫັດ ການຮ້ອງຂໍ ຈໍານວນ
ຈາກການເບິ່ງ cursory ຢູ່ ioctls(2) ການໂຕ້ຕອບ, ມີຈະປະກົດວ່າມີຂະຫນາດໃຫຍ່ແຕ່ຈໍາກັດ
ຈໍານວນທີ່ເປັນໄປໄດ້ ioctls(2) ຄໍາຮ້ອງຂໍ. ແຕ່ລະຄົນແຕກຕ່າງກັນ ioctls(2) ການຮ້ອງຂໍແມ່ນມີປະສິດຕິຜົນ
ການໂທຫາລະບົບອື່ນ, ແຕ່ບໍ່ມີປະເພດຄວາມປອດໄພໃດໆ - compiler ບໍ່ສາມາດຊ່ວຍໄດ້
programmer ໄດ້ຮັບສິດທິເຫຼົ່ານີ້. ນີ້ອາດຈະເປັນແຮງຈູງໃຈທີ່ຢູ່ເບື້ອງຫຼັງ tcflush(3) ແລະ
ຫມູ່ເພື່ອນ.
ຄວາມປະທັບໃຈເບື້ອງຕົ້ນແມ່ນທ່ານສາມາດຖອດລະຫັດໄດ້ ioctls(2) ການຮ້ອງຂໍການນໍາໃຊ້ສະຫຼັບຂະຫນາດໃຫຍ່
ຖະແຫຼງການ. ອັນນີ້ກາຍເປັນສິ່ງທີ່ເປັນໄປບໍ່ໄດ້ ເພາະວ່າຜູ້ໜຶ່ງຄົ້ນພົບຢ່າງໄວວາວ່າມັນແມ່ນ
ເປັນໄປບໍ່ໄດ້ທີ່ຈະລວມເອົາຫົວຂອງລະບົບທີ່ຈໍາເປັນທັງໝົດເພື່ອກໍານົດສິ່ງຕ່າງໆ ioctls(2)
ການຮ້ອງຂໍ, ເພາະວ່າພວກເຂົາມີຄວາມຫຍຸ້ງຍາກໃນການຫຼີ້ນທີ່ດີກັບກັນແລະກັນ.
ການເບິ່ງທີ່ເລິກເຊິ່ງສະແດງໃຫ້ເຫັນວ່າມີຈໍານວນການຮ້ອງຂໍ "ສ່ວນຕົວ", ແລະອຸປະກອນ
ຜູ້ຂຽນຄົນຂັບໄດ້ຖືກຊຸກຍູ້ໃຫ້ໃຊ້ພວກມັນ. ນີ້ຫມາຍຄວາມວ່າມີຂະຫນາດໃຫຍ່ກວ່າທີ່ເປັນໄປໄດ້
ຊຸດຂອງຄໍາຮ້ອງຂໍ, ທີ່ມີຕົວເລກການຮ້ອງຂໍທີ່ບໍ່ຊັດເຈນ, ກ່ວາຈະປາກົດຂື້ນໃນທັນທີ. ນອກຈາກນີ້,
ຍັງມີບາງຄວາມບໍ່ແນ່ນອນທາງປະຫວັດສາດເຊັ່ນກັນ.
ພວກເຮົາຮູ້ແລ້ວວ່າການສະຫຼັບແມ່ນ impractical, ແຕ່ໃນປັດຈຸບັນພວກເຮົາຮູ້ວ່າຈະເລືອກເອົາ
ຊື່ຄໍາຮ້ອງຂໍທີ່ເຫມາະສົມແລະຄໍາອະທິບາຍພວກເຮົາຕ້ອງພິຈາລະນາບໍ່ພຽງແຕ່ຈໍານວນຄໍາຮ້ອງຂໍແຕ່
ຕົວອະທິບາຍໄຟລ໌.
ການປະຕິບັດຂອງ ioctls(2) ສະຫນັບສະຫນູນພາຍໃນຫ້ອງສະຫມຸດ libexplain ແມ່ນການມີຕາຕະລາງຂອງ
ຊີ້ໄປ ioctls(2) ຮ້ອງຂໍໃຫ້ຜູ້ອະທິບາຍ. ແຕ່ລະຕົວອະທິບາຍເຫຼົ່ານີ້ປະກອບມີທາງເລືອກ
ຊີ້ໄປຫາຟັງຊັນ disambiguation.
ແຕ່ລະຄໍາຮ້ອງຂໍແມ່ນປະຕິບັດຕົວຈິງໃນໄຟລ໌ແຫຼ່ງແຍກຕ່າງຫາກ, ດັ່ງນັ້ນມີຄວາມຈໍາເປັນ
ປະກອບມີໄຟລ໌ໄດ້ຖືກປົດປ່ອຍພັນທະທີ່ຈະຫຼິ້ນງາມກັບຄົນອື່ນ.
ການເປັນຕົວແທນ
ປັດຊະຍາທີ່ຢູ່ເບື້ອງຫລັງຫ້ອງສະຫມຸດ libexplain ແມ່ນເພື່ອສະຫນອງຂໍ້ມູນຫຼາຍເທົ່າທີ່
ເປັນໄປໄດ້, ລວມທັງການເປັນຕົວແທນທີ່ຖືກຕ້ອງຂອງການໂທລະບົບ. ໃນກໍລະນີຂອງ
ioctls(2) ນີ້ຫມາຍຄວາມວ່າການພິມຈໍານວນຄໍາຮ້ອງຂໍທີ່ຖືກຕ້ອງ (ໂດຍຊື່) ແລະຍັງຖືກຕ້ອງ (ຫຼື
ຢ່າງຫນ້ອຍທີ່ເປັນປະໂຫຍດ) ການເປັນຕົວແທນຂອງການໂຕ້ຖຽງທີສາມ.
ໄດ້ ioctls(2) ຕົ້ນແບບມີລັກສະນະດັ່ງນີ້:
int ioctl(int fildes, int request, ...);
ເຊິ່ງຄວນຈະມີສັນຍານເຕືອນຄວາມປອດໄພປະເພດຂອງເຈົ້າຈະປິດ. ພາຍໃນກັບ [e]glibc, ອັນນີ້ແມ່ນຫັນ
ໃນຫຼາຍຮູບແບບ:
int __ioctl(int fildes, int request, long arg);
int __ioctl(int fildes, int request, void *arg);
ແລະການໂຕ້ຕອບ syscall kernel Linux ຄາດວ່າຈະ
asmlinkage long sys_ioctl(unsigned int fildes, unsigned int request, unsigned long
arg);
ການປ່ຽນແປງທີ່ຮຸນແຮງຂອງການໂຕ້ຖຽງທີສາມແມ່ນສິ່ງທ້າທາຍ, ໃນເວລາທີ່ຫ້ອງສະຫມຸດ libexplain
ພະຍາຍາມພິມຕົວແທນຂອງການໂຕ້ຖຽງທີສາມນັ້ນ. ຢ່າງໃດກໍຕາມ, ເມື່ອຈໍານວນການຮ້ອງຂໍ
ໄດ້ຖືກ disambiguated, ແຕ່ລະລາຍການໃນຕາຕະລາງ ioctl ຂອງຫ້ອງສະຫມຸດ libexplain ມີ a
ຟັງຊັນ print_data ແບບກຳນົດເອງ (OO ເຮັດດ້ວຍຕົນເອງ).
ຄໍາອະທິບາຍ
ມີບັນຫາຫນ້ອຍໃນການກໍານົດຄໍາອະທິບາຍທີ່ຈະນໍາໃຊ້. ເມື່ອຈໍານວນການຮ້ອງຂໍ
ໄດ້ຖືກ disambiguated, ແຕ່ລະລາຍການໃນຕາຕະລາງ ioctl ຂອງຫ້ອງສະຫມຸດ libexplain ມີ custom
ຟັງຊັນ print_explanation (ອີກເທື່ອຫນຶ່ງ, OO ເຮັດດ້ວຍຕົນເອງ).
ບໍ່ຄືກັບພາກ 2 ແລະພາກ 3 ການໂທລະບົບ, ຫຼາຍທີ່ສຸດ ioctls(2) ຄໍາຮ້ອງຂໍບໍ່ມີຂໍ້ຜິດພາດ
ເອກະສານ. ນີ້ຫມາຍຄວາມວ່າ, ເພື່ອໃຫ້ຄໍາອະທິບາຍຄວາມຜິດພາດທີ່ດີ, ມັນຈໍາເປັນຕ້ອງອ່ານ kernel
ແຫຼ່ງຂໍ້ມູນທີ່ຈະຄົ້ນພົບ
· ແມ່ນຫຍັງ ຜິດພາດ(3) ຄ່າອາດຈະຖືກສົ່ງຄືນ, ແລະ
·ສາເຫດຂອງຄວາມຜິດພາດແຕ່ລະຄົນ.
ເນື່ອງຈາກວ່າລັກສະນະຂອງ OO ຂອງການສົ່ງການໂທຫາຫນ້າທີ່ກັບແກ່ນ, ທ່ານຈໍາເປັນຕ້ອງອ່ານ
ທັງຫມົດ ແຫຼ່ງຂໍ້ມູນທີ່ປະຕິບັດນັ້ນ ioctls(2) ການຮ້ອງຂໍ, ບໍ່ພຽງແຕ່ການປະຕິບັດທົ່ວໄປ. ມັນ
ຄາດວ່າຈະມີ kernels ທີ່ແຕກຕ່າງກັນຈະມີຕົວເລກຄວາມຜິດພາດທີ່ແຕກຕ່າງກັນແລະ subtly
ສາເຫດຂອງຄວາມຜິດພາດທີ່ແຕກຕ່າງກັນ.
EINVAL vs ENTOTTY
ສະຖານະການແມ່ນຮ້າຍແຮງກວ່າເກົ່າສໍາລັບ ioctls(2) ການຮ້ອງຂໍຫຼາຍກ່ວາສໍາລັບການໂທຫາລະບົບ, ກັບ EINVAL ແລະ
ENTOTTY ທັງສອງຖືກໃຊ້ເພື່ອຊີ້ບອກວ່າ an ioctls(2) ຄໍາຮ້ອງຂໍແມ່ນບໍ່ເຫມາະສົມໃນນັ້ນ
ສະພາບການ, ແລະເປັນບາງໂອກາດ ENOSYS, ENOTSUP ແລະ EOPNOTSUPP (ຫມາຍຄວາມວ່າຈະຖືກນໍາໃຊ້ສໍາລັບ sockets) ເປັນ
ດີ. ມີຄວາມຄິດເຫັນໃນແຫຼ່ງ Linux kernel ທີ່ເບິ່ງຄືວ່າຊີ້ໃຫ້ເຫັນເຖິງຄວາມກ້າວຫນ້າ
ການອະນາໄມກຳລັງດຳເນີນຢູ່. ສໍາລັບຄວາມວຸ່ນວາຍພິເສດ, BSD ເພີ່ມ ENIOOCTL ກັບຄວາມສັບສົນ.
ດັ່ງນັ້ນ, ຕ້ອງເອົາໃຈໃສ່ກັບກໍລະນີຄວາມຜິດພາດເຫຼົ່ານີ້ເພື່ອໃຫ້ຖືກຕ້ອງ, ໂດຍສະເພາະ
ເນື່ອງຈາກວ່າ EINVAL ຍັງສາມາດອ້າງອີງເຖິງບັນຫາທີ່ມີຫນຶ່ງຫຼືຫຼາຍການໂຕ້ຖຽງການໂທລະບົບ.
intptr_t
ມາດຕະຖານ C99 ກໍານົດປະເພດຈໍານວນເຕັມທີ່ຮັບປະກັນວ່າສາມາດຖືຕົວຊີ້ໃດໆ
ໂດຍບໍ່ມີການສູນເສຍຕົວແທນ.
ຕົ້ນແບບ syscall ຟັງຊັນຂ້າງເທິງຈະຖືກຂຽນດີກວ່າ
long sys_ioctl(unsigned int fildes, unsigned int request, intptr_t arg);
ບັນຫາແມ່ນຄວາມບໍ່ສອດຄ່ອງທາງດ້ານສະຕິປັນຍາທີ່ເກີດຈາກອຸປະກອນສະເພາະ ຫຼືລະບົບໄຟລ໌ສະເພາະ.
ioctls(2) ການປະຕິບັດເຊັ່ນ:
vfs_ioctl ຍາວ(ໄຟລ໌ໂຄງສ້າງ *filp, unsigned int cmd, unsigned long arg);
ສ່ວນໃຫຍ່ຂອງ ioctls(2) ການຮ້ອງຂໍຕົວຈິງມີ int *arg ການໂຕ້ຖຽງທີສາມ. ແຕ່ມີມັນ
ປະກາດຍາວເຮັດໃຫ້ລະຫັດການປິ່ນປົວນີ້ຍາວ * arg. ອັນນີ້ບໍ່ເປັນອັນຕະລາຍໃນ 32-bits
(sizeof(long) == sizeof(int)) ແຕ່ບໍ່ພໍໃຈໃນ 64-bits (sizeof(long) != sizeof(int)).
ຂຶ້ນຢູ່ກັບ endian-ness, ເຈົ້າເຮັດຫຼືບໍ່ໄດ້ຮັບຄ່າທີ່ທ່ານຄາດຫວັງ, ແຕ່ວ່າທ່ານ ສະເຫມີໄປ ໄດ້ຮັບ
scribble ຄວາມຊົງຈໍາຫຼື stack scribble ເຊັ່ນດຽວກັນ.
ຂຽນທັງຫມົດເຫຼົ່ານີ້ເປັນ
int ioctl(int fildes, int request, ...);
int __ioctl(int fildes, int request, intptr_t arg);
long sys_ioctl(unsigned int fildes, unsigned int request, intptr_t arg);
vfs_ioctl ຍາວ(ໄຟລ໌ໂຄງສ້າງ *filp, unsigned int cmd, intptr_t arg);
ເນັ້ນຫນັກວ່າຈໍານວນຈໍານວນແມ່ນພຽງແຕ່ຈໍານວນເຕັມທີ່ຈະເປັນຕົວແທນຂອງປະລິມານທີ່ເກືອບ
ສະເຫມີເປັນປະເພດຕົວຊີ້ທີ່ບໍ່ກ່ຽວຂ້ອງ.
ສະຫຼຸບ
ໃຊ້ libexplain, ຜູ້ໃຊ້ຂອງທ່ານຈະມັກມັນ.
COPYRIGHT
libexplain ເວີຊັ່ນ 1.4
ສະຫງວນລິຂະສິດ (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Peter Miller
ໃຊ້ description_lca2010 ອອນລາຍໂດຍໃຊ້ບໍລິການ onworks.net