Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ทำความเข้าใจกับข้อยกเว้น Errno แปลก ๆ ของ Rubys

หากคุณเคยดูลำดับชั้นข้อยกเว้นของ 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