Nếu bạn đã từng xem qua hệ thống phân cấp ngoại lệ của Ruby, bạn có thể nhận thấy điều gì đó kỳ lạ. Ngoài tất cả các ngoại lệ bình thường như RuntimeError và NoMethodError, có một tham chiếu kỳ lạ đến Errno::*
.
Exception
StandardError
...
SystemCallError
Errno::*
...
Nếu bạn đã từng gặp may mắn khi ghi vào đĩa khi đĩa đầy hoặc cố gắng thực hiện lệnh gọi API qua mạng bị lỗi thì có thể bạn đã thấy loại lỗi này đang hoạt động. Bạn có thể kích hoạt một tệp ngay bây giờ bằng cách cố gắng mở một tệp không tồn tại.
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>'
Nhưng chính xác thì những trường hợp ngoại lệ Errono là gì? Và tại sao họ lại được đối xử khác biệt, cảm ơn các loại ngoại lệ khác?
Thích ứng Ruby với hệ điều hành
Các ngoại lệ Errno về cơ bản là một bộ điều hợp. Chúng kết nối các lỗi của hệ điều hành với hệ thống ngoại lệ của Ruby. Hệ điều hành xử lý lỗi theo một cách khác với Ruby, vì vậy bạn có để có một số loại bộ điều hợp.
Trong ruby, lỗi có xu hướng được báo cáo là ngoại lệ. Nhưng lỗi của hệ điều hành thường chỉ là số nguyên. Vì vậy, ruby xác định một lớp ngoại lệ cho mỗi lỗi hệ điều hành có thể xảy ra. Sau đó, nó gắn tất cả các ngoại lệ này vào một mô-đun được gọi là Errno.
Chúng tôi có thể sử dụng IRB để xem tất cả các ngoại lệ trong mô-đun này. Và cậu bé, có rất nhiều!
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]
Nhưng tại sao chúng lại được đặt tên khó hiểu như vậy? Ý tôi là, làm sao tôi có thể đoán được rằng ENOINT có nghĩa là "Không tìm thấy tệp?"
... Thực ra có một câu trả lời rất đơn giản.
Bán buôn được sao chép từ libc
Bất cứ ai lần đầu tiên xây dựng mô-đun Errno chỉ cần sao chép trực tiếp các tên lỗi từ libc. Vì vậy, ENOINT, trong C, là tên của macro chứa mã lỗi số nguyên mà Hệ điều hành trả về khi không thể tìm thấy tệp.
Vì vậy, để thực sự tìm hiểu xem mỗi thứ này có tác dụng gì, mẹo là hãy xem tài liệu cho thư viện tiêu chuẩn C. Bạn có thể tìm thấy một danh sách lớn về chúng ở đây. Tôi đã trích dẫn một vài trong số những cái có liên quan hơn bên dưới:
EPERM | Hoạt động không được phép; bạn không thể truy cập tệp trừ khi bạn có quyền. |
ENOENT | Không tìm thấy tệp hoặc thư mục. |
EIO | Lỗi đầu vào / đầu ra; thường được sử dụng cho các lỗi đọc hoặc ghi vật lý. |
EBADF | Bộ mô tả tệp không hợp lệ. Ví dụ:bạn sẽ gặp lỗi này nếu bạn cố gắng ghi vào một tệp bạn đã mở chỉ để đọc. |
ECHILD | Bạn đã cố gắng thao tác một quy trình con, nhưng không có bất kỳ quy trình con nào. |
ENOMEM | Bạn đã hết RAM và không thể cấp thêm bất kỳ bộ nhớ ảo nào nữa. |
MẶT BẰNG | Quyền bị từ chối; quyền đối với tệp không cho phép hoạt động đã cố gắng. |
ENOTBLK | Bạn đã cố gắng gắn một tệp thông thường dưới dạng một thiết bị, chẳng hạn như ổ cứng. |
EBUSY | Tài nguyên bận; tài nguyên hệ thống không thể chia sẻ đã được sử dụng. Ví dụ:nếu bạn cố gắng xóa một tệp là gốc của hệ thống tệp hiện được gắn kết, bạn sẽ gặp lỗi này. |
EEXIST | Tệp tồn tại; một tệp hiện có đã được chỉ định trong ngữ cảnh mà việc chỉ định một tệp mới chỉ có ý nghĩa. |
MÔI GIỚI | Một tệp không phải là thư mục đã được chỉ định khi cần có thư mục. |
EISDIR | Tệp là một thư mục; bạn không thể mở một thư mục để viết hoặc tạo hoặc xóa các liên kết cứng đến nó. |
EINVAL | Đối số không hợp lệ. Điều này được sử dụng để chỉ ra nhiều loại vấn đề khác nhau khi chuyển đối số sai vào một hàm thư viện. |
EMFILE | Quy trình hiện tại có quá nhiều tệp đang mở và không thể mở thêm được nữa. Các bộ mô tả trùng lặp được tính vào giới hạn này. |
EFBIG | Tệp quá lớn; kích thước của tệp sẽ lớn hơn hệ thống cho phép. |
ENOSPC | Không còn dung lượng trên thiết bị; thao tác ghi trên tệp không thành công vì đĩa đã đầy. |
ESPIPE | Thao tác tìm kiếm không hợp lệ (chẳng hạn như trên đường ống). |
EROFS | Đã cố gắng sửa đổi một số thứ trên hệ thống tệp chỉ đọc. |
EPIPE | Đường ống bị hỏng; không có quá trình đọc từ đầu kia của đường ống |
ENOTSOCK | Một tệp không phải là ổ cắm được chỉ định khi cần có ổ cắm. |
ENETUNREACH | Thao tác ổ cắm không thành công do không thể truy cập mạng con chứa máy chủ từ xa. |
ENETRESET | Kết nối mạng đã được đặt lại do máy chủ từ xa bị lỗi. |
ECONNABORTED | Kết nối mạng đã bị ngắt cục bộ. |
ECONNRESET | Kết nối mạng đã bị đóng vì các lý do nằm ngoài sự kiểm soát của máy chủ cục bộ, chẳng hạn như do máy khởi động lại từ xa hoặc vi phạm giao thức không thể khôi phục. |
ENOBUFS | Các bộ đệm của hạt nhân cho các hoạt động I / O đều đang được sử dụng. Trong GNU, lỗi này luôn đồng nghĩa với ENOMEM; bạn có thể nhận được cái này hoặc cái khác từ hoạt động mạng. |
EISCONN | Bạn đã cố kết nối một ổ cắm đã được kết nối. Xem Kết nối. |
ENOTCONN | Ổ cắm không được kết nối với bất kỳ thứ gì. Bạn gặp lỗi này khi cố gắng truyền dữ liệu qua ổ cắm mà trước tiên không chỉ định đích cho dữ liệu. |
EDESTADDRREQ | Không có địa chỉ đích mặc định nào được đặt cho ổ cắm. Bạn gặp lỗi này khi cố gắng truyền dữ liệu qua ổ cắm không kết nối mà trước tiên không chỉ định đích cho dữ liệu có kết nối. |
ESHUTDOWN | Ổ cắm đã tắt. |
ETIMEDOUT | Hoạt động socket với thời gian chờ được chỉ định không nhận được phản hồi trong khoảng thời gian chờ. |
TINH TẾ | Máy chủ từ xa từ chối cho phép kết nối mạng (thường là do nó không chạy dịch vụ được yêu cầu). |
EHOSTDOWN | Máy chủ từ xa cho kết nối mạng được yêu cầu bị lỗi. |
EHOSTUNREACH | Không thể truy cập máy chủ từ xa cho kết nối mạng được yêu cầu. |
THƯỞNG THỨC | Thư mục không trống, nơi mong đợi một thư mục trống. Thông thường, lỗi này xảy ra khi bạn đang cố gắng xóa một thư mục. |
EPROCLIM | Điều này có nghĩa là giới hạn cho mỗi người dùng trên quy trình mới sẽ bị vượt quá bởi một lần phân nhánh đã cố gắng. Xem Giới hạn về tài nguyên, để biết chi tiết về giới hạn RLIMIT_NPROC. |