หากคุณเคยดูลำดับชั้นข้อยกเว้นของ Ruby คุณอาจสังเกตเห็นบางอย่างแปลก ๆ นอกจากข้อยกเว้นทั่วไปทั้งหมด เช่น RuntimeError และ NoMethodError แล้ว ยังมีการอ้างอิงถึง Errno::*
.
Exception
StandardError
...
SystemCallError
Errno::*
...
หากคุณเคยโชคร้ายที่จะเขียนลงดิสก์เมื่อดิสก์เต็ม หรือพยายามเรียก API ผ่านเครือข่ายที่ล้มเหลว คุณอาจเคยเห็นข้อผิดพลาดประเภทนี้ในการดำเนินการ คุณสามารถทริกเกอร์ไฟล์ได้ทันทีโดยพยายามเปิดไฟล์ที่ไม่มีอยู่
irb> File.open("badfilename.txt")
Errno::ENOENT: No such file or directory @ rb_sysopen - badfilename.txt
from (irb):9:in `initialize'
from (irb):9:in `open'
from (irb):9
from /Users/snhorne/.rbenv/versions/2.1.0/bin/irb:11:in `<main>'
แต่อะไรคือข้อยกเว้นของ Errono? และทำไมพวกเขาถึงได้รับการปฏิบัติต่างกันด้วยข้อยกเว้นประเภทอื่นๆ
การปรับ Ruby ให้เข้ากับระบบปฏิบัติการ
ข้อยกเว้นของ Errno นั้นเป็นอะแดปเตอร์เป็นหลัก พวกเขาเชื่อมโยงข้อผิดพลาดของระบบปฏิบัติการกับระบบข้อยกเว้นของ Ruby ระบบปฏิบัติการจัดการข้อผิดพลาดในลักษณะที่แตกต่างจาก Ruby ดังนั้นคุณจึงมี มีอะแดปเตอร์บางชนิด
ในทับทิม ข้อผิดพลาดมักจะถูกรายงานเป็นข้อยกเว้น แต่ข้อผิดพลาดของระบบปฏิบัติการมักเป็นเพียงจำนวนเต็ม ดังนั้น ruby จึงกำหนดคลาสข้อยกเว้นหนึ่งคลาสสำหรับแต่ละข้อผิดพลาดของระบบปฏิบัติการที่เป็นไปได้ จากนั้นจึงรวมข้อยกเว้นทั้งหมดไว้ใน โมดูล เรียกว่า Errno
เราสามารถใช้ IRB เพื่อดูข้อยกเว้นทั้งหมดในโมดูลนี้ แล้วไอ้หนู มีเยอะ!
irb> Errno.constants
=> [:NOERROR, :EPERM, :ENOENT, :ESRCH, :EINTR, :EIO, :ENXIO, :E2BIG, :ENOEXEC, :EBADF, :ECHILD, :EAGAIN, :ENOMEM, :EACCES, :EFAULT, :ENOTBLK, :EBUSY, :EEXIST, :EXDEV, :ENODEV, :ENOTDIR, :EISDIR, :EINVAL, :ENFILE, :EMFILE, :ENOTTY, :ETXTBSY, :EFBIG, :ENOSPC, :ESPIPE, :EROFS, :EMLINK, :EPIPE, :EDOM, :ERANGE, :EDEADLK, :ENAMETOOLONG, :ENOLCK, :ENOSYS, :ENOTEMPTY, :ELOOP, :EWOULDBLOCK, :ENOMSG, :EIDRM, :ECHRNG, :EL2NSYNC, :EL3HLT, :EL3RST, :ELNRNG, :EUNATCH, :ENOCSI, :EL2HLT, :EBADE, :EBADR, :EXFULL, :ENOANO, :EBADRQC, :EBADSLT, :EDEADLOCK, :EBFONT, :ENOSTR, :ENODATA, :ETIME, :ENOSR, :ENONET, :ENOPKG, :EREMOTE, :ENOLINK, :EADV, :ESRMNT, :ECOMM, :EPROTO, :EMULTIHOP, :EDOTDOT, :EBADMSG, :EOVERFLOW, :ENOTUNIQ, :EBADFD, :EREMCHG, :ELIBACC, :ELIBBAD, :ELIBSCN, :ELIBMAX, :ELIBEXEC, :EILSEQ, :ERESTART, :ESTRPIPE, :EUSERS, :ENOTSOCK, :EDESTADDRREQ, :EMSGSIZE, :EPROTOTYPE, :ENOPROTOOPT, :EPROTONOSUPPORT, :ESOCKTNOSUPPORT, :EOPNOTSUPP, :EPFNOSUPPORT, :EAFNOSUPPORT, :EADDRINUSE, :EADDRNOTAVAIL, :ENETDOWN, :ENETUNREACH, :ENETRESET, :ECONNABORTED, :ECONNRESET, :ENOBUFS, :EISCONN, :ENOTCONN, :ESHUTDOWN, :ETOOMANYREFS, :ETIMEDOUT, :ECONNREFUSED, :EHOSTDOWN, :EHOSTUNREACH, :EALREADY, :EINPROGRESS, :ESTALE, :EUCLEAN, :ENOTNAM, :ENAVAIL, :EISNAM, :EREMOTEIO, :EDQUOT, :ECANCELED, :EKEYEXPIRED, :EKEYREJECTED, :EKEYREVOKED, :EMEDIUMTYPE, :ENOKEY, :ENOMEDIUM, :ENOTRECOVERABLE, :EOWNERDEAD, :ERFKILL, :EAUTH, :EBADRPC, :EDOOFUS, :EFTYPE, :ENEEDAUTH, :ENOATTR, :ENOTSUP, :EPROCLIM, :EPROCUNAVAIL, :EPROGMISMATCH, :EPROGUNAVAIL, :ERPCMISMATCH, :EIPSEC]
แต่ทำไมพวกเขาถึงตั้งชื่ออย่างลึกลับ? ฉันหมายความว่าฉันจะเดาได้อย่างไรว่า ENOINT หมายถึง "ไม่พบไฟล์"
...มีคำตอบที่ง่ายมาก
คัดลอกขายส่งจาก libc
ใครก็ตามที่สร้างโมดูล Errno ขึ้นมาก่อน ก็แค่คัดลอกชื่อข้อผิดพลาดโดยตรงจาก libc ดังนั้น ENOINT ใน C จึงเป็นชื่อของมาโครที่มีรหัสข้อผิดพลาดของจำนวนเต็มซึ่งระบบปฏิบัติการส่งคืนเมื่อไม่พบไฟล์
ดังนั้น หากต้องการทราบจริงๆ ว่าสิ่งเหล่านี้มีเคล็ดลับอะไรบ้าง ให้ดูที่เอกสารประกอบสำหรับไลบรารีมาตรฐาน C คุณสามารถค้นหารายการใหญ่ได้ที่นี่ ฉันได้ตัดตอนบางส่วนที่เกี่ยวข้องมากกว่าด้านล่าง:
EPERM | ไม่อนุญาตให้ดำเนินการ คุณไม่สามารถเข้าถึงไฟล์ได้เว้นแต่คุณจะได้รับอนุญาต |
ENOENT | ไม่พบไฟล์หรือไดเรกทอรี |
EIO | อินพุต/เอาต์พุตผิดพลาด; มักใช้สำหรับข้อผิดพลาดในการอ่านหรือเขียนจริง |
EBADF | ตัวอธิบายไฟล์ไม่ถูกต้อง คุณจะได้รับข้อผิดพลาดนี้หากคุณพยายามเขียนไปยังไฟล์ที่คุณเปิดเพื่ออ่านเท่านั้น เป็นต้น |
อีชิลด์ | คุณพยายามจัดการโปรเซสลูก แต่ไม่มีโปรเซสลูก |
ENOMEM | หน่วยความจำของคุณหมด และไม่สามารถจัดสรรหน่วยความจำเสมือนได้อีก |
EACCES | การอนุญาตถูกปฏิเสธ; สิทธิ์ของไฟล์ไม่อนุญาตให้มีการดำเนินการที่พยายาม |
ENOTBLK | คุณพยายามเมานต์ไฟล์ธรรมดาเป็นอุปกรณ์ เช่น HDD |
อีบูซี่ | ทรัพยากรไม่ว่าง; มีการใช้ทรัพยากรระบบที่ไม่สามารถแชร์ได้อยู่แล้ว ตัวอย่างเช่น หากคุณพยายามลบไฟล์ที่เป็นรูทของระบบไฟล์ที่ติดตั้งอยู่ในปัจจุบัน คุณจะได้รับข้อผิดพลาดนี้ |
มีอยู่ | ไฟล์มีอยู่; ไฟล์ที่มีอยู่ถูกระบุในบริบทที่เหมาะสมที่จะระบุไฟล์ใหม่เท่านั้น |
ENOTDIR | ไฟล์ที่ไม่ใช่ไดเร็กทอรีถูกระบุเมื่อจำเป็นต้องใช้ไดเร็กทอรี |
EISDIR | ไฟล์เป็นไดเร็กทอรี; คุณไม่สามารถเปิดไดเร็กทอรีเพื่อเขียน หรือสร้างหรือลบฮาร์ดลิงก์ไปยังไดเร็กทอรี |
EINVAL | อาร์กิวเมนต์ไม่ถูกต้อง ใช้เพื่อระบุปัญหาประเภทต่างๆ ในการส่งอาร์กิวเมนต์ที่ไม่ถูกต้องไปยังฟังก์ชันไลบรารี |
EMFILE | กระบวนการปัจจุบันมีไฟล์เปิดมากเกินไปและไม่สามารถเปิดได้อีก ตัวอธิบายที่ซ้ำกันจะนับรวมในขีดจำกัดนี้ |
EFBIG | ไฟล์ใหญ่เกินไป ขนาดของไฟล์จะใหญ่กว่าที่ระบบอนุญาต |
ENOSPC | ไม่มีพื้นที่เหลือบนอุปกรณ์; การเขียนไฟล์ล้มเหลวเนื่องจากดิสก์เต็ม |
ESPIPE | การดำเนินการค้นหาไม่ถูกต้อง (เช่น บนท่อ) |
EROFS | มีการพยายามแก้ไขบางอย่างในระบบไฟล์แบบอ่านอย่างเดียว |
EPIPE | ท่อแตก; ไม่มีกระบวนการอ่านจากปลายอีกด้านของไพพ์ |
ENOTSOCK | มีการระบุไฟล์ที่ไม่ใช่ซ็อกเก็ตเมื่อจำเป็นต้องใช้ซ็อกเก็ต |
ENETUNREACH | การดำเนินการซ็อกเก็ตล้มเหลวเนื่องจากไม่สามารถเข้าถึงซับเน็ตที่มีโฮสต์ระยะไกลได้ |
ENETRESET | มีการรีเซ็ตการเชื่อมต่อเครือข่ายเนื่องจากโฮสต์ระยะไกลขัดข้อง |
ประหยัดแล้ว | การเชื่อมต่อเครือข่ายถูกยกเลิกภายในเครื่อง |
ECONNRESET | การเชื่อมต่อเครือข่ายถูกปิดด้วยเหตุผลที่อยู่นอกเหนือการควบคุมของโฮสต์ในพื้นที่ เช่น โดยการรีบูตเครื่องจากระยะไกลหรือการละเมิดโปรโตคอลที่กู้คืนไม่ได้ |
ENOBUFS | มีการใช้บัฟเฟอร์ของเคอร์เนลสำหรับการดำเนินการ I/O ทั้งหมด ใน GNU ข้อผิดพลาดนี้มีความหมายเหมือนกันกับ ENOMEM เสมอ คุณอาจได้รับอย่างใดอย่างหนึ่งจากการทำงานของเครือข่าย |
ไอสคอนน์ | คุณพยายามเชื่อมต่อซ็อกเก็ตที่เชื่อมต่อแล้ว ดูการเชื่อมต่อ |
ENOTCONN | ซ็อกเก็ตไม่ได้เชื่อมต่อกับสิ่งใด คุณได้รับข้อผิดพลาดนี้เมื่อคุณพยายามส่งข้อมูลผ่านซ็อกเก็ต โดยไม่ระบุปลายทางสำหรับข้อมูลก่อน |
EDESTADDRREQ | ไม่มีการตั้งค่าที่อยู่ปลายทางเริ่มต้นสำหรับซ็อกเก็ต คุณได้รับข้อผิดพลาดนี้เมื่อคุณพยายามส่งข้อมูลผ่านซ็อกเก็ตที่ไม่มีการเชื่อมต่อ โดยไม่ระบุปลายทางสำหรับข้อมูลด้วยการเชื่อมต่อก่อน |
ESHUTDOWN | ซ็อกเก็ตถูกปิดไปแล้ว |
ETIMEDOUT | การทำงานของซ็อกเก็ตที่มีการหมดเวลาที่ระบุไม่ได้รับการตอบกลับในช่วงระยะเวลาหมดเวลา |
ประหยัดแล้ว | รีโมตโฮสต์ปฏิเสธที่จะอนุญาตการเชื่อมต่อเครือข่าย (โดยทั่วไปเนื่องจากไม่ได้เรียกใช้บริการที่ร้องขอ) |
EHOSTDOWN | รีโมตโฮสต์สำหรับการเชื่อมต่อเครือข่ายที่ร้องขอไม่ทำงาน |
EHOSTUNREACH | โฮสต์ระยะไกลสำหรับการเชื่อมต่อเครือข่ายที่ร้องขอไม่สามารถเข้าถึงได้ |
ENOTEMPTY | ไดเร็กทอรีไม่ว่างเปล่า โดยคาดว่าไดเร็กทอรีว่าง โดยปกติ ข้อผิดพลาดนี้จะเกิดขึ้นเมื่อคุณพยายามลบไดเร็กทอรี |
EPROCLIM | ซึ่งหมายความว่าขีดจำกัดต่อผู้ใช้สำหรับกระบวนการใหม่จะเกินขีดจำกัดด้วยการพยายามส้อม ดูข้อจำกัดของทรัพยากร สำหรับรายละเอียดเกี่ยวกับขีดจำกัด RLIMIT_NPROC |