Computer >> Máy Tính >  >> Lập trình >> Ruby

Hiểu các ngoại lệ Errno kỳ lạ của Rubys

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ó 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.