Tiếng AnhTiếng PhápTiếng Tây Ban Nha

Ad


Biểu tượng yêu thích OnWorks

giải thích_lca2010 - Trực tuyến trên đám mây

Chạy giải thích_lca2010 trong nhà cung cấp dịch vụ lưu trữ miễn phí OnWorks trên Ubuntu Online, Fedora Online, trình giả lập trực tuyến Windows hoặc trình mô phỏng trực tuyến MAC OS

Đây là lệnh giải thích_lca2010 có thể chạy trong nhà cung cấp dịch vụ lưu trữ miễn phí OnWorks bằng cách sử dụng một trong nhiều máy trạm trực tuyến miễn phí của chúng tôi, chẳng hạn như Ubuntu Online, Fedora Online, trình giả lập trực tuyến Windows hoặc trình mô phỏng trực tuyến MAC OS

CHƯƠNG TRÌNH:

TÊN


giải thích_lca2010 - Không tìm thấy phương tiện nào: đã đến lúc ngừng cố gắng đọc kinh hoàng(3) của
lí trí.

Động lực


Ý tưởng về libexplain nảy ra với tôi vào đầu những năm 1980. Bất cứ khi nào hệ thống gọi
trả về một lỗi, hạt nhân biết chính xác điều gì đã xảy ra ... và nén nó thành
ít hơn 8 bit của sai. Không gian người dùng có quyền truy cập vào cùng một dữ liệu với hạt nhân, nó
không gian người dùng sẽ có thể tìm ra chính xác điều gì đã xảy ra để gây ra lỗi
quay lại và sử dụng nó để viết các thông báo lỗi tốt.

nó đơn giản đến thế ư?

lỗi tin nhắn as sự khéo léo
Các thông báo lỗi tốt thường là những tác vụ "một phần trăm" bị rớt khi lên lịch
áp lực bóp chết dự án của bạn. Tuy nhiên, một thông báo lỗi tốt có thể khiến
cải tiến không cân xứng đối với trải nghiệm người dùng, khi người dùng lạc vào cảnh sát
lãnh thổ không xác định thường không gặp phải. Đây là nhiệm vụ không dễ dàng.

Là một lập trình viên ấu trùng, tác giả không thấy vấn đề với lỗi (hoàn toàn chính xác)
những tin nhắn như thế này:
ngoại lệ nổi (lõi được kết xuất)
cho đến khi cách giải thích không phải lập trình viên thay thế được chỉ ra. Nhưng đó không phải là
chỉ có điều sai với thông báo lỗi Unix. Tần suất bạn thấy các thông báo lỗi như:
$ ./dốt nát
không thể mở tệp
$
Có hai tùy chọn cho một nhà phát triển tại thời điểm này:

1.
bạn có thể chạy trình gỡ lỗi, chẳng hạn như gdb(1), hoặc

2.
bạn có thể dùng đi lạc(1) hoặc bó lại thành bó(1) để nhìn vào bên trong.

· Hãy nhớ rằng người dùng của bạn thậm chí có thể không có quyền truy cập vào các công cụ này, chưa nói đến khả năng
để sử dụng chúng. (Đã rất lâu kể từ khi Unix mới bắt đầu có nghĩa là “chỉ có văn bản một
trình điều khiển thiết bị ”.)

Tuy nhiên, trong ví dụ này, sử dụng đi lạc(1) tiết lộ
$ đi lạc -e dấu vết = mở ./dốt nát
open ("some / file", O_RDONLY) = -1 ENOENT (Không có tệp hoặc thư mục như vậy)
không thể mở tệp
$
Đây là thông tin nhiều hơn đáng kể so với thông báo lỗi cung cấp. Thông thường,
mã nguồn ngu ngốc trông như thế này
int fd = open ("thứ gì đó", O_RDONLY);
nếu (fd <0)
{
fprintf (stderr, "không thể mở tệp \ n");
ra(1);
}
Người dùng không được nói cái nào và cũng không cho người dùng biết cái nào lỗi. Là tập tin
thậm chí ở đó? Có vấn đề về quyền không? Nó cho bạn biết nó đang cố gắng mở một
nhưng đó có thể là do tình cờ.

Lấy thanh manh mối của bạn và đi đánh bại các lập trình viên ấu trùng với nó. Nói với anh ấy về kẻ gian tà(3).
Lần tiếp theo khi sử dụng chương trình, bạn sẽ thấy một thông báo lỗi khác:
$ ./dốt nát
mở: Không có tệp hoặc thư mục như vậy
$
Tiến bộ, nhưng không phải những gì chúng tôi mong đợi. Người dùng có thể khắc phục sự cố bằng cách nào nếu thông báo lỗi
không cho anh ta biết vấn đề là gì? Nhìn vào nguồn, chúng ta thấy
int fd = open ("thứ gì đó", O_RDONLY);
nếu (fd <0)
{
perror ("mở");
ra(1);
}
Thời gian cho lần chạy khác với thanh manh mối. Lần này, thông báo lỗi có một bước
tiến và lùi một bước:
$ ./dốt nát
thứ gì đó: Không có tập tin hoặc thư mục
$
Bây giờ chúng tôi biết tệp mà nó đang cố gắng mở, nhưng không còn được thông báo rằng nó đã mở(2)
mà không thành công. Trong trường hợp này, nó có thể không đáng kể, nhưng nó có thể quan trọng đối với
các cuộc gọi hệ thống khác. Nó có thể đã được người tạo(2) thay vào đó, một phép toán ngụ ý rằng
các quyền khác nhau là cần thiết.
const char * filename = "thứ gì đó";
int fd = open (tên tệp, O_RDONLY);
nếu (fd <0)
{
perror (tên tệp);
ra(1);
}
Rất tiếc, đoạn mã ví dụ trên cũng rất điển hình đối với các lập trình viên không phải là ấu trùng. Thời gian
để nói với người học padawan của chúng tôi về kinh hoàng(3) cuộc gọi hệ thống.
$ ./dốt nát
mở thứ gì đó: Không có tập tin hoặc thư mục
$
Điều này tối đa hóa thông tin có thể được trình bày cho người dùng. Mã trông giống như
điều này:
const char * filename = "thứ gì đó";
int fd = open (tên tệp, O_RDONLY);
nếu (fd <0)
{
fprintf (stderr, "open% s:% s \ n", filename, strerror (errno));
ra(1);
}
Bây giờ chúng ta có lệnh gọi hệ thống, tên tệp và chuỗi lỗi. Điều này chứa tất cả
thông tin đó đi lạc(1) được in. Điều đó tốt như nó nhận được.

Hoặc là nó?

Hạn chế of kẻ gian tà kinh hoàng
Vấn đề mà tác giả gặp phải, vào những năm 1980, là thông báo lỗi không đầy đủ.
“Không có tệp hoặc thư mục như vậy” có liên quan đến “một số”Hoặc đến thư mục“điều" trong tập tin
các "một số" danh mục?

Xem nhanh trang người đàn ông cho kinh hoàng(3) đang nói:
strerror - trả về chuỗi mô tả số lỗi
Lưu ý tốt: nó đang mô tả lỗi con số, không phải lỗi.

Mặt khác, nhân biết lỗi là gì. Có một điểm cụ thể trong
mã hạt nhân, gây ra bởi một điều kiện cụ thể, trong đó mã hạt nhân phân nhánh và nói “không”.
Chương trình không gian người dùng có thể tìm ra điều kiện cụ thể và viết lỗi tốt hơn không
thông điệp?

Tuy nhiên, vấn đề đi sâu hơn. Điều gì sẽ xảy ra nếu sự cố xảy ra trong đọc(2) hệ thống
cuộc gọi, thay vì mở(2) cuộc gọi? Nó đơn giản cho thông báo lỗi liên quan đến
mở(2) để bao gồm tên tệp, nó ở ngay đó. Nhưng để có thể bao gồm tên tệp
trong lỗi liên quan đến đọc(2) lệnh gọi hệ thống, bạn phải chuyển tất cả tên tệp
đường xuống ngăn xếp cuộc gọi, cũng như trình mô tả tệp.

Và đây là điểm đáng quan tâm: hạt nhân đã biết tệp đặt tên tệp là gì
bộ mô tả được liên kết với. Tại sao một lập trình viên phải chuyển tất cả dữ liệu thừa
cách xuống ngăn xếp cuộc gọi chỉ để cải thiện một thông báo lỗi có thể không bao giờ được đưa ra? Trong
thực tế, nhiều lập trình viên không bận tâm và kết quả là các thông báo lỗi càng tồi tệ hơn đối với
nó.

Nhưng đó là những năm 1980, trên PDP11, với nguồn tài nguyên hạn chế và không có thư viện dùng chung. Trở lại
sau đó, không có hương vị của Unix bao gồm / proc ngay cả ở dạng thô sơ, và lsof.(1) chương trình
đã hơn một thập kỷ trôi qua. Vì vậy, ý tưởng đã bị xếp vào hàng không thực tế.

Cấp Vô cực HỖ TRỢ
Hãy tưởng tượng rằng bạn đang hỗ trợ cấp độ vô cực. Mô tả công việc của bạn nói rằng bạn không bao giờ
bao giờ phải nói chuyện với người dùng. Vậy tại sao vẫn có một lượng người không ngừng mong muốn
bạn, chuyên gia Unix địa phương, để giải mã một thông báo lỗi nào khác?

Thật kỳ lạ, 25 năm sau, mặc dù có một hệ thống quyền đơn giản, được triển khai với
nhất quán, hầu hết người dùng Unix vẫn không biết cách giải mã "Không có tệp hoặc thư mục như vậy",
hoặc bất kỳ thông báo lỗi khó hiểu nào khác mà họ thấy hàng ngày. Hoặc, ít nhất, khó hiểu với
Chúng.

Sẽ thật tuyệt nếu hỗ trợ công nghệ cấp độ đầu tiên không cần thông báo lỗi được giải mã?
Thật tuyệt khi có thông báo lỗi mà người dùng có thể hiểu được mà không cần gọi điện
hô trợ ky thuật?

Những ngày này / proc trên Linux không chỉ có khả năng cung cấp thông tin cần thiết để giải mã
phần lớn các thông báo lỗi và hướng người dùng đến nguyên nhân gần giống của
vấn đề. Trên các hệ thống có giới hạn / proc thực hiện, lsof.(1) lệnh có thể điền vào
nhiều khoảng trống.

Trong năm 2008, các luồng yêu cầu dịch thuật đã xảy ra với tác giả một cách quá thường xuyên. Nó đã
thời gian để kiểm tra lại ý tưởng 25 năm tuổi đó, và libexplain là kết quả.

SỬ DỤNG CÁC THƯ VIỆN


Giao diện của thư viện cố gắng nhất quán, nếu có thể. Hãy bắt đầu với một
ví dụ sử dụng kinh hoàng(3):
if (rename (old_path, new_path) <0)
{
fprintf (stderr, "đổi tên% s% s:% s \ n", old_path, new_path,
strerror (errno));
ra(1);
}
Ý tưởng đằng sau libexplain là cung cấp một kinh hoàng(3) tương đương cho mỗi cuộc gọi hệ thống,
được điều chỉnh cụ thể cho lệnh gọi hệ thống đó, để nó có thể cung cấp một lỗi chi tiết hơn
, chứa nhiều thông tin bạn thấy trong tiêu đề "LỖI" của phần
2 và 3 người đàn ông trang, bổ sung thông tin về điều kiện thực tế, lập luận thực tế
giá trị và giới hạn hệ thống.

Sản phẩm Đơn giản Khay
Sản phẩm kinh hoàng(3) thay thế:
if (rename (old_path, new_path) <0)
{
fprintf (stderr, "% s \ n", giải_thích tên_cách (đường dẫn cũ, đường dẫn_mới));
ra(1);
}

Sản phẩm sai Khay
Nó cũng có thể vượt qua một sai(3) giá trị, nếu trước tiên bạn phải làm một số
xử lý sẽ làm phiền sai, chẳng hạn như khôi phục lỗi:
if (rename (old_path, new_path <0))
{
int old_errno = errno;
hữu ích. Cảm ơn ! việc này làm phiền saihữu ích. Cảm ơn !
fprintf (stderr, "% s \ n", giải thích_errno_rename (old_errno,
old_path, new_path));
ra(1);
}

Sản phẩm Nhiều chủ đề Các Trường Hợp
Một số ứng dụng đa luồng và do đó không thể chia sẻ nội bộ của libexplain
đệm. Bạn có thể cung cấp bộ đệm của riêng mình bằng cách sử dụng
if (hủy liên kết (tên đường dẫn))
{
tin nhắn char [3000];
giải thích_message_unlink (tin nhắn, kích thước(tin nhắn), tên đường dẫn);
hộp thoại lỗi(nhắn);
trả về -1;
}
Và để hoàn thiện, cả hai sai(3) và luồng ‐ an toàn:
ssize_t nbytes = read (fd, data, sizeof (data));
nếu (nbyte <0)
{
tin nhắn char [3000];
int old_errno = errno;
hữu ích. Cảm ơn !lôi phục hồihữu ích. Cảm ơn !
giải thích_message_errno_read (tin nhắn, kích thước(thông điệp),
old_errno, fd, data, sizeof (data));
hộp thoại lỗi(nhắn);
trả về -1;
}

Đây là những thay thế cho strerror_r(3), trên các hệ thống có nó.

Giao thức Sugar
Một tập hợp các chức năng được thêm vào dưới dạng các chức năng tiện lợi, để thu hút các lập trình viên sử dụng
thư viện libexplain, hóa ra là các hàm libexplain được sử dụng phổ biến nhất của tác giả trong
các chương trình dòng lệnh:
int fd = description_creat_or_die (tên tập tin, 0666);
Hàm này cố gắng tạo một tệp mới. Nếu không thể, nó sẽ in một thông báo lỗi và
thoát với EXIT_FAILURE. Nếu không có lỗi, nó sẽ trả về bộ mô tả tệp mới.

Một chức năng liên quan:
int fd = giải thích_cách_cử_lỗi (tên tệp, 0666);
sẽ in thông báo lỗi khi bị lỗi, nhưng cũng trả về kết quả lỗi ban đầu và
sai(3) cũng không bị phản đối.

Tất cả các khác hệ thống cuộc gọi
Nói chung, mọi lệnh gọi hệ thống đều có tệp bao gồm riêng của nó
#bao gồmtên.h>
xác định các nguyên mẫu hàm cho sáu hàm:

· giải thích_tên,

· Giải thích_errno_tên,

· Giải thích_message_tên,

· Giải thích_message_errno_tên,

· giải thích_tên_or_die và

· giải thích_tên_on_error.

Mọi nguyên mẫu hàm đều có tài liệu Doxygen và tài liệu này is không tước
khi các tệp bao gồm được cài đặt.

Sản phẩm chờ đợi(2) cuộc gọi hệ thống (và bạn bè) có một số biến thể bổ sung cũng giải thích sự thất bại
là trạng thái thoát không phải là EXIT_SUCCESS. Điều này áp dụng cho hệ thống(3) khăn giấy(3) như
tốt.

Phạm vi bao gồm 221 cuộc gọi hệ thống và 547 yêu cầu ioctl. Còn nhiều hệ thống nữa
các cuộc gọi vẫn chưa được thực hiện. Các lệnh gọi hệ thống không bao giờ trở lại, chẳng hạn như ra(2), không có mặt
trong thư viện, và sẽ không bao giờ có. Các giám đốc điều hành họ các cuộc gọi hệ thống đang được hỗ trợ, bởi vì
họ trả lại khi có lỗi.

Cát
Đây là chương trình “con mèo” giả định có thể trông như thế nào, với đầy đủ báo cáo lỗi,
sử dụng libexplain.
#bao gồm
#include
#bao gồm
Có một bao gồm cho libexplain, cộng với các chất nghi ngờ thông thường. (Nếu bạn muốn giảm
tải trước bộ xử lý, bạn có thể sử dụngtên.h> bao gồm.)
khoảng trống tĩnh
xử lý (FILE * fp)
{
vì (;;)
{
đệm char [4096];
size_t n = description_fread_or_die (đệm, 1, sizeof (đệm), fp);
nếu (! n)
phá vỡ;
giải thích_fwrite_or_die (đệm, 1, n, stdout);
}
}
Sản phẩm quá trình chức năng sao chép một dòng tệp vào đầu ra tiêu chuẩn. Nếu xảy ra lỗi
để đọc hoặc ghi, nó sẽ được báo cáo (và tên đường dẫn sẽ được bao gồm trong
lỗi) và lệnh thoát với EXIT_FAILURE. Chúng tôi thậm chí không lo lắng về việc theo dõi
tên đường dẫn hoặc chuyển chúng xuống ngăn xếp cuộc gọi.
int
main (int argc, char ** argv)
{
vì (;;)
{
int c = getopt (argc, argv, "o:");
nếu (c == EOF)
phá vỡ;
chuyển đổi (c)
{
trường hợp 'o':
giải thích_freopen_or_die (optarg, "w", stdout);
phá vỡ;
Phần thú vị của mã này là libexplain có thể báo lỗi kể cả các tên đường dẫn cũng
nếu bạn không mở lại stdout một cách rõ ràng như được thực hiện ở đây. Chúng tôi thậm chí không lo lắng về
theo dõi tên tệp.
mặc định:
fprintf (stderr, "Mức sử dụng:% ss [-o ] ...\n",
argv [0]);
trả về EXIT_FAILURE;
}
}
nếu (optind == argc)
quy trình (stdin);
khác
{
trong khi (optind <argc)
{
FILE * fp = giải thích_fopen_or_die (argv [optind] ++, "r");
quy trình (fp);
giải thích_fclose_or_die (fp);
}
}
Đầu ra tiêu chuẩn sẽ được đóng ngầm, nhưng quá muộn để có một báo cáo lỗi
đã phát hành, vì vậy chúng tôi làm điều đó ở đây, đề phòng trường hợp I / O được lưu vào bộ đệm chưa viết bất kỳ điều gì và
có một lỗi ENOSPC hoặc một cái gì đó.
giải_ thích_fflush_or_die (stdout);
trả về EXIT_SUCCESS;
}
Đó là tất cả. Báo lỗi đầy đủ, mã rõ ràng.

Rusty's Quy mô of Giao thức Lòng tốt
Đối với những người trong số các bạn chưa quen thuộc với nó, "Làm thế nào để tôi làm cho điều này khó sử dụng sai?"
trang phải đọc đối với các nhà thiết kế API.
http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html

10. Đó là không thể đến được sai rồi.

Các mục tiêu cần được đặt cao, có tham vọng cao, kẻo bạn hoàn thành chúng và nghĩ rằng bạn đang
hoàn thành khi bạn không.

Thư viện libexplain phát hiện các con trỏ không có thật và nhiều tham số lệnh gọi hệ thống không có thật khác,
và thường cố gắng tránh mặc định trong những trường hợp cố gắng nhất.

Thư viện libexplain được thiết kế để an toàn cho luồng. Sẽ có nhiều khả năng sử dụng trong thế giới thực hơn
tiết lộ những nơi điều này có thể được cải thiện.

Vấn đề lớn nhất là với chính các tên chức năng thực tế. Vì C không có
tên ‐ dấu cách, thư viện libexplain luôn sử dụng tiền tố tên giải thích. Đây là
cách truyền thống để tạo khoảng trắng tên giả để tránh xung đột ký hiệu.
Tuy nhiên, nó dẫn đến một số tên nghe không tự nhiên.

9. Sản phẩm trình biên dịch or Liên kết sẽ không cho phép bạn được it sai rồi.

Một sai lầm phổ biến là sử dụng giải thích_open nơi giải thích_open_or_die được dự định.
May mắn thay, trình biên dịch thường sẽ xuất hiện lỗi kiểu vào thời điểm này (ví dụ không thể chỉ định
const char * rvalue thành một int lvalue).

8. Sản phẩm trình biên dịch sẽ cảnh báo if bạn được it sai rồi.

Nếu giải thích_rename được sử dụng khi giải thích_rename_or_die được dự định, điều này có thể gây ra
các vấn đề. GCC có thuộc tính hàm warning_unused_result hữu ích và vùng giải phóng mặt bằng
thư viện đính kèm nó vào tất cả các giải thích_tên hàm gọi để đưa ra cảnh báo khi bạn
mắc lỗi này. Kết hợp cái này với gcc - Lỗi để thăng cấp điều này lên mức độ tốt cấp 9.

7. Sản phẩm Rõ ràng sử dụng is (có lẽ) các sửa chữa một.

Các tên chức năng đã được chọn để truyền đạt ý nghĩa của chúng, nhưng điều này không phải lúc nào cũng
thành công. Trong khi giải thích_tên_or_die và giải thích_tên_on_error khá mô tả,
càng khó giải mã các biến thể an toàn của luồng ít được sử dụng hơn. Các nguyên mẫu hàm giúp
trình biên dịch hướng tới sự hiểu biết và các nhận xét Doxygen trong các tệp tiêu đề giúp người dùng
hướng tới sự hiểu biết.

6. Sản phẩm tên nói bạn làm thế nào đến sử dụng nó.

Điều đặc biệt quan trọng là phải đọc giải thích_tên_or_die as “giải thích (tên hoặc chết)".
Việc sử dụng tiền tố dấu cách giải thích_ tên ‐ nhất quán có một số tác dụng phụ đáng tiếc trong
bộ phận hiển nhiên, là tốt.

Thứ tự của các từ trong tên cũng cho biết thứ tự của các đối số. Lý lẽ
danh sách luôn luôn cuối với các đối số tương tự như được chuyển đến lệnh gọi hệ thống; tất cả các of họ. Nếu
_errno_ xuất hiện trong tên, đối số của nó luôn đứng trước đối số lệnh gọi hệ thống. Nếu như
_message_ xuất hiện trong tên, hai đối số của nó luôn đứng trước.

5. Do it ngay or it sẽ phá vỡ at thời gian chạy.

Thư viện libexplain phát hiện các con trỏ không có thật và nhiều tham số lệnh gọi hệ thống không có thật khác,
và thường cố gắng tránh mặc định trong những trường hợp cố gắng nhất. Nó nên
không bao giờ bị hỏng trong thời gian chạy, nhưng việc sử dụng trong thế giới thực hơn chắc chắn sẽ cải thiện điều này.

Một số thông báo lỗi nhằm vào các nhà phát triển và người bảo trì hơn là người dùng cuối, vì điều này
có thể hỗ trợ giải quyết lỗi. Không quá “ngắt quãng trong thời gian chạy” như “hãy cung cấp thông tin lúc
thời gian chạy ”(sau khi hệ thống gọi barfs).

4. Theo chung hội nghị bạn sẽ được it đúng.

Bởi vì C không có tên ‐ dấu cách, thư viện libexplain luôn sử dụng tên giải thích
tiếp đầu ngữ. Đây là cách truyền thống để tạo khoảng trắng tên giả để tránh
xung đột biểu tượng.

Các đối số theo sau của tất cả lệnh gọi libexplain giống hệt lệnh gọi hệ thống chúng
đang mô tả. Điều này nhằm cung cấp một quy ước nhất quán chung với
hệ thống tự gọi.

3. Đọc các tài liệu hướng dẫn bạn sẽ được it đúng.

Thư viện libexplain nhằm mục đích có đầy đủ tài liệu Doxygen cho mỗi
lệnh gọi API công khai (và cả trong nội bộ).

THÔNG ĐIỆP NỘI DUNG


Làm việc trên libexplain hơi giống như nhìn vào mặt dưới của chiếc xe của bạn khi nó đang khởi động
vận thăng của thợ cơ khí. Có một số thứ xấu xí dưới đó, cùng với bùn và đất vụn, và
người dùng hiếm khi nhìn thấy nó. Một thông báo lỗi tốt cần phải có nhiều thông tin, ngay cả đối với người dùng
đã đủ may mắn để không phải nhìn vào mặt dưới thường xuyên, và
cung cấp thông tin cho người thợ nghe mô tả của người dùng qua điện thoại. Đây là
không có nhiệm vụ dễ dàng.

Xem lại ví dụ đầu tiên của chúng tôi, mã sẽ như thế này nếu nó sử dụng libexplain:
int fd = Liberation_open_or_die ("some / thing", O_RDONLY, 0);
sẽ thất bại với một thông báo lỗi như thế này
mở (pathname = "some / file", flags = O_RDONLY) không thành công, Không có tệp hoặc thư mục nào như vậy
(2, ENOENT) vì không có thư mục "một số" trong thư mục hiện tại
Cái này chia thành ba mảnh
hệ thống ‐ cuộc gọi thất bại, lỗi hệ thống bởi vì
giải thích

Trước Bởi vì
Có thể thấy phần của thông báo trước “bởi vì” là quá kỹ thuật để không
người dùng kỹ thuật, chủ yếu là kết quả của việc in chính xác hệ thống tự gọi
đầu thông báo lỗi. Và nó trông giống như đi lạc(1) đầu ra, cho người đam mê thưởng thức
điểm.
mở (pathname = "some / file", flags = O_RDONLY) không thành công, Không có tệp hoặc thư mục nào như vậy
(2, NỔI BẬT)
Phần thông báo lỗi này rất cần thiết cho nhà phát triển khi anh ta đang viết mã,
và quan trọng không kém đối với người bảo trì, người phải đọc báo cáo lỗi và sửa lỗi trong
mã số. Nó nói chính xác những gì đã thất bại.

Nếu văn bản này không được hiển thị cho người dùng thì người dùng không thể sao chép ‐ và ‐ dán vào
báo cáo lỗi và nếu nó không có trong báo cáo lỗi, người bảo trì không thể biết điều gì đã thực sự xảy ra
sai rồi.

Nhân viên kỹ thuật thường xuyên sẽ sử dụng đi lạc(1) hoặc bó lại thành bó(1) để có được thông tin chính xác này, nhưng
đại lộ này không mở khi đọc báo cáo lỗi. Hệ thống của báo cáo lỗi rất xa
xa, và bây giờ, ở một trạng thái khác xa. Do đó, thông tin này cần phải có trong
báo cáo lỗi, có nghĩa là nó phải nằm trong thông báo lỗi.

Biểu diễn cuộc gọi hệ thống cũng cung cấp ngữ cảnh cho phần còn lại của thông báo. Nếu cần
phát sinh, đối số cuộc gọi hệ thống vi phạm có thể được gọi bằng tên trong phần giải thích
sau “bởi vì”. Ngoài ra, tất cả các chuỗi đều được trích dẫn đầy đủ và chuỗi C thoát, vì vậy
các dòng mới được nhúng và các ký tự không in sẽ không làm cho thiết bị đầu cuối của người dùng hoạt động
cỏ khô.

Sản phẩm lỗi hệ thống là những gì xuất phát từ kinh hoàng(2), cộng với biểu tượng lỗi. Thiếu kiên nhẫn và
chuyên gia sysadmins có thể ngừng đọc vào thời điểm này, nhưng kinh nghiệm của tác giả cho đến nay là
rằng đọc thêm là bổ ích. (Nếu nó không bổ ích, nó có thể là một lĩnh vực
libexplain có thể được cải thiện. Tất nhiên, những đóng góp về mã đều được hoan nghênh.)

Sau Bởi vì
Đây là phần của thông báo lỗi nhằm vào người dùng không phải là kỹ thuật. Nó nhìn xa hơn
đối số lệnh gọi hệ thống đơn giản và tìm kiếm một cái gì đó cụ thể hơn.
không có thư mục "một số" trong thư mục hiện tại
Phần này cố gắng giải thích nguyên nhân gần như của lỗi bằng ngôn ngữ đơn giản và nó
ở đây là quốc tế hóa là điều cần thiết.

Nói chung, chính sách là bao gồm càng nhiều thông tin càng tốt, để người dùng
không cần phải đi tìm nó (và không để nó ra khỏi báo cáo lỗi).

quốc tế hóa
Hầu hết các thông báo lỗi trong thư viện libexplain đã được quốc tế hóa. Ở đó
chưa được bản địa hóa, vì vậy nếu bạn muốn giải thích bằng ngôn ngữ mẹ đẻ của mình,
xin vui lòng đóng góp.

Định nghĩa "hầu hết của", ở trên, liên quan đến thực tế là khái niệm chứng minh ‐ của ‐
việc thực hiện không bao gồm hỗ trợ quốc tế hóa. Cơ sở mã đang được
được sửa đổi dần dần, thường là kết quả của việc cấu trúc lại các thông báo để mỗi lỗi
chuỗi thông báo xuất hiện trong mã đúng một lần.

Điều khoản đã được thực hiện cho các ngôn ngữ cần tập hợp các phần của
hệ thống ‐ cuộc gọi thất bại, lỗi hệ thống bởi vì giải thích
theo các thứ tự khác nhau cho đúng ngữ pháp trong các thông báo lỗi được bản địa hóa.

sau khi chết
Đôi khi một chương trình vẫn chưa sử dụng libexplain và bạn không thể sử dụng đi lạc(1)
một trong hai. Đây là một giải thích(1) lệnh đi kèm với libexplain có thể được sử dụng để
giải mã thông báo lỗi, nếu trạng thái của hệ thống cơ bản không thay đổi quá nhiều.
$ giải thích đổi tên foo / tmp / bar / baz -e NỔI BẬT
đổi tên (oldpath = "foo", newpath = "/ tmp / bar / baz") không thành công, Không có tệp hoặc thư mục như vậy
(2, ENOENT) vì không có thư mục "bar" trong đường dẫn mới "/ Tmp" danh mục
$
Lưu ý cách giải quyết sự không rõ ràng về đường dẫn bằng cách sử dụng tên đối số lệnh gọi hệ thống. Của
tất nhiên, bạn phải biết lỗi và hệ thống yêu cầu giải thích(1) hữu ích. Như một
sang một bên, đây là một trong những cách được sử dụng bởi bộ thử nghiệm tự động libexplain để xác minh rằng
libexplain đang hoạt động.

Triết học
“Hãy kể cho tôi mọi thứ, kể cả những thứ tôi không biết để tìm kiếm.”

Thư viện được triển khai theo cách mà khi được liên kết tĩnh, chỉ mã bạn
thực sự sử dụng sẽ được liên kết. Điều này đạt được bằng cách có một chức năng cho mỗi tệp nguồn,
bất cứ khi nào khả thi.

Khi có thể cung cấp thêm thông tin, libexplain sẽ làm như vậy. Người dùng càng ít
phải tự mình theo dõi thì càng tốt. Điều này có nghĩa là UID đi kèm với
tên người dùng, GID đi kèm với tên nhóm, PID đi kèm với quy trình
tên, bộ mô tả tệp và luồng được đi kèm với tên đường dẫn, vv.

Khi phân giải các đường dẫn, nếu một thành phần đường dẫn không tồn tại, libexplain sẽ tìm kiếm các đường dẫn tương tự
tên, để đề xuất các giải pháp thay thế cho các lỗi đánh máy.

Thư viện libexplain cố gắng sử dụng càng ít heap càng tốt, và thường là không. Đây là
để tránh làm xáo trộn trạng thái quy trình, càng nhiều càng tốt, mặc dù đôi khi nó
không thể tránh khỏi.

Thư viện libexplain cố gắng đảm bảo an toàn cho chuỗi, bằng cách tránh các biến toàn cục, giữ
trạng thái trên ngăn xếp càng nhiều càng tốt. Có một bộ đệm thông báo chung duy nhất và
các chức năng sử dụng nó được ghi nhận là không an toàn cho chuỗi.

Thư viện libexplain không làm phiền các trình xử lý tín hiệu của quy trình. Điều này làm cho
xác định liệu một con trỏ có mặc định là một thách thức hay không, nhưng không phải là không thể.

Khi thông tin có sẵn thông qua cuộc gọi hệ thống cũng như có sẵn thông qua / proc
mục nhập, cuộc gọi hệ thống được ưu tiên. Điều này là để tránh làm xáo trộn trạng thái của quá trình.
Cũng có khi không có bộ mô tả tệp nào khả dụng.

Thư viện libexplain được biên dịch với hỗ trợ tệp lớn. Không có lớn / nhỏ
tâm thần phân liệt. Trường hợp điều này ảnh hưởng đến các loại đối số trong API và lỗi sẽ được đưa ra
nếu không có định nghĩa tệp lớn cần thiết.

Khắc phục: Cần phải làm việc để đảm bảo rằng hạn ngạch hệ thống tệp được xử lý trong mã. Điều này
áp dụng cho một số giới hạn(2) ranh giới, là tốt.

Có những trường hợp đường dẫn họ hàng không thông tin. Ví dụ: daemon hệ thống,
máy chủ và các quy trình nền. Trong những trường hợp này, các đường dẫn tuyệt đối được sử dụng trong lỗi
Giải thích.

PATH GIẢI QUYẾT


Phiên bản ngắn: xem đường dẫn_độ phân giải(7).

Phiên bản dài: Hầu hết người dùng chưa bao giờ nghe nói về đường dẫn_độ phân giải(7) và nhiều người dùng nâng cao
chưa bao giờ đọc nó. Đây là một phiên bản có chú thích:

Bước 1: Bắt đầu of các độ phân giải quá trình
Nếu tên đường dẫn bắt đầu bằng ký tự gạch chéo (“/”), thì thư mục tra cứu bắt đầu là
thư mục gốc của quá trình gọi.

Nếu tên đường dẫn không bắt đầu bằng ký tự dấu gạch chéo (“/”), thì việc tra cứu bắt đầu
thư mục của quá trình giải quyết là thư mục làm việc hiện tại của quá trình.

Bước 2: Đi bộ dọc theo các con đường
Đặt thư mục tra cứu hiện tại thành thư mục tra cứu bắt đầu. Bây giờ, đối với mỗi không
thành phần cuối cùng của tên đường dẫn, trong đó thành phần là một chuỗi con được phân tách bằng dấu gạch chéo (“/”)
ký tự, thành phần này được tra cứu trong thư mục tra cứu hiện tại.

Nếu quy trình không có quyền tìm kiếm trên thư mục tra cứu hiện tại, một EACCES
lỗi được trả về ("Quyền bị từ chối").
mở (pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) không thành công,
Quyền bị từ chối (13, EACCES) vì quy trình không có quyền tìm kiếm
vào thư mục tên đường dẫn "/home/archives/.ssh", quy trình có hiệu lực GID 1000
"pmiller" không khớp với chủ sở hữu thư mục 1001 "archives" nên chủ sở hữu
chế độ quyền "rwx" bị bỏ qua, chế độ quyền khác là "---" và
quy trình không được đặc quyền (không có khả năng DAC_READ_SEARCH)

Nếu không tìm thấy thành phần, sẽ trả về lỗi ENOENT ("Không có tệp hoặc thư mục như vậy").
hủy liên kết (pathname = "/ home / microsoft / rubbish") không thành công, Không có tệp hoặc thư mục như vậy (2,
ENOENT) vì không có thư mục "microsoft" trong tên đường dẫn "/ Home" danh mục

Ngoài ra còn có một số hỗ trợ cho người dùng khi họ nhập sai tên đường dẫn, đưa ra đề xuất khi
ENOENT được trả lại:
mở (pathname = "/user/include/fcntl.h", flags = O_RDONLY) không thành công, Không có tệp như vậy hoặc
thư mục (2, ENOENT) vì không có thư mục "người dùng" trong tên đường dẫn "/"
thư mục, có phải ý bạn là thư mục "usr" không?

Nếu thành phần được tìm thấy, nhưng không phải là một thư mục hoặc một liên kết tượng trưng, ​​một ENOTDIR
được trả về lỗi ("Không phải là thư mục").
mở (pathname = "/home/pmiller/.netrc/lca", flags = O_RDONLY) không thành công, Không phải
thư mục (20, ENOTDIR) vì tệp thông thường ".netrc" trong tên đường dẫn
Thư mục "/ home / pmiller" đang được sử dụng làm thư mục khi nó không phải

Nếu thành phần được tìm thấy và là một thư mục, chúng tôi đặt thư mục tra cứu hiện tại thành
và chuyển đến thành phần tiếp theo.

Nếu thành phần được tìm thấy và là một liên kết tượng trưng (liên kết tượng trưng), trước tiên chúng tôi giải quyết biểu tượng này
liên kết (với thư mục tra cứu hiện tại là thư mục tra cứu bắt đầu). Do lỗi, điều đó
lỗi được trả lại. Nếu kết quả không phải là một thư mục, lỗi ENOTDIR sẽ được trả về.
hủy liên kết (pathname = "/ tmp / dangling / rubbish") không thành công, Không có tệp hoặc thư mục nào như vậy (2,
ENOENT) vì liên kết tượng trưng "treo lơ lửng" trong tên đường dẫn "/ Tmp" danh mục
đề cập đến "hư không" không tồn tại
Nếu quá trình phân giải liên kết biểu tượng thành công và trả về một thư mục, chúng tôi đặt hiện tại
tra cứu thư mục đến thư mục đó và chuyển đến thành phần tiếp theo. Lưu ý rằng
quá trình giải quyết ở đây liên quan đến đệ quy. Để bảo vệ hạt nhân khỏi ngăn xếp
tràn, và cũng để bảo vệ chống lại việc từ chối dịch vụ, có những giới hạn ở mức tối đa
độ sâu đệ quy và trên số lượng tối đa các liên kết tượng trưng theo sau. Lỗi ELOOP là
được trả về khi vượt quá mức tối đa ("Quá nhiều cấp độ liên kết tượng trưng").
mở (pathname = "/ tmp / dangling", flags = O_RDONLY) không thành công, Quá nhiều cấp độ
các liên kết tượng trưng (40, ELOOP) bởi vì một vòng lặp liên kết tượng trưng đã gặp phải trong
tên đường dẫn, bắt đầu bằng "/ tmp / dangling"
Cũng có thể gặp lỗi ELOOP hoặc EMLINK nếu có quá nhiều liên kết tượng trưng, ​​nhưng không
vòng lặp đã được phát hiện.
không mở được (pathname = "/ tmp / Rabbit ‐ hole", flags = O_RDONLY), Quá nhiều cấp độ
các liên kết tượng trưng (40, ELOOP) vì quá nhiều liên kết tượng trưng đã gặp phải trong
tên đường dẫn (8)
Chú ý cách giới hạn thực tế cũng được in.

Bước 3: Tìm kiếm các cuối cùng nhập
Việc tra cứu thành phần cuối cùng của tên đường dẫn cũng giống như các thành phần khác
các thành phần, như được mô tả trong bước trước, với hai điểm khác biệt:

(i) Thành phần cuối cùng không cần phải là một thư mục (ít nhất là theo độ phân giải đường dẫn
quy trình có liên quan. Nó có thể phải là một thư mục hoặc không phải là một thư mục, vì
các yêu cầu của lệnh gọi hệ thống cụ thể).

(Ii)
Nó không nhất thiết là một lỗi nếu thành phần cuối cùng không được tìm thấy; có lẽ chúng ta chỉ là
tạo ra nó. Các chi tiết về xử lý đầu vào cuối cùng được mô tả trong
các trang thủ công của các lệnh gọi hệ thống cụ thể.

(iii)
Cũng có thể có vấn đề với thành phần cuối cùng nếu nó là một liên kết tượng trưng
và nó không nên được tuân theo. Ví dụ, bằng cách sử dụng mở(2) Cờ O_NOFOLLOW:
open (pathname = "a ‐ symlink", flags = O_RDONLY | O_NOFOLLOW) không thành công, Quá nhiều cấp
liên kết tượng trưng (ELOOP) vì O_NOFOLLOW đã được chỉ định nhưng tên đường dẫn tham chiếu đến
liên kết tượng trưng

(iv)
Người dùng thường mắc lỗi khi nhập tên đường dẫn. Thư viện libexplain
cố gắng đưa ra đề xuất khi ENOENT được trả lại, ví dụ:
mở (pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) không thành công, Không có tệp như vậy hoặc
thư mục (2, ENOENT) vì không có tệp thông thường "filecontrl.h" trong tên đường dẫn
"/ usr / bao gồm", ý của bạn là tệp thông thường" fcntl.h "phải không?

(v) Cũng có thể thành phần cuối cùng được yêu cầu phải là một cái gì đó khác với
tệp thông thường:
readlink (pathname = "just ‐ a ‐ file", data = 0x7F930A50, data_size = 4097) không thành công,
Đối số không hợp lệ (22, EINVAL) vì tên đường dẫn là một tệp thông thường, không phải là một liên kết tượng trưng

(vi)
FIXME: xử lý bit "t".

Giới hạn
Có một số giới hạn liên quan đến tên đường dẫn và tên tệp.

Giới hạn độ dài tên đường dẫn
Có độ dài tối đa cho tên đường dẫn. Nếu tên đường dẫn (hoặc một số trung gian
tên đường dẫn có được trong khi giải quyết các liên kết tượng trưng) quá dài, một ENAMETOOLONG
lỗi được trả về ("Tên tệp quá dài"). Lưu ý cách giới hạn hệ thống được bao gồm
trong thông báo lỗi.
mở (tên đường dẫn = "rất dài", flags = O_RDONLY) không thành công, Tên tệp quá dài (36,
ENAMETOOLONG) vì tên đường dẫn vượt quá độ dài đường dẫn tối đa của hệ thống (4096)

Giới hạn độ dài tên tệp
Một số biến thể Unix có giới hạn về số byte trong mỗi thành phần đường dẫn.
Một số trong số họ giải quyết điều này một cách âm thầm, và một số cho ENAMETOOLONG; vùng tự do
sử dụng thư viện đường dẫn(3) _PC_NO_TRUNC để cho biết điều đó. Nếu lỗi này xảy ra,
thư viện libexplain sẽ nêu giới hạn trong thông báo lỗi, giới hạn là
thu được từ đường dẫn(3) _PC_NAME_MAX. Lưu ý cách bao gồm giới hạn hệ thống
trong thông báo lỗi.
mở (tên đường dẫn = "system7 / only-had-14-ký tự", flags = O_RDONLY) không thành công, Tệp
tên quá dài (36, ENAMETOOLONG) vì thành phần "only-had-14-ký tự" là
dài hơn giới hạn hệ thống (14)

Tên đường dẫn trống
Trong Unix ban đầu, tên đường dẫn trống tham chiếu đến thư mục hiện tại.
Ngày nay, POSIX ra lệnh rằng tên đường dẫn trống không được giải quyết thành công.
mở (pathname = "", flags = O_RDONLY) không thành công, Không có tệp hoặc thư mục nào như vậy (2,
ENOENT) vì POSIX quy định rằng tên đường dẫn trống không được giải quyết
thành công

Quyền
Các bit quyền của một tệp bao gồm ba nhóm ba bit. Nhóm đầu tiên của
ba được sử dụng khi ID người dùng hiệu quả của quá trình gọi bằng ID chủ sở hữu của
tập tin. Nhóm thứ hai trong số ba được sử dụng khi ID nhóm của tệp bằng
ID nhóm hiệu quả của quá trình gọi hoặc là một trong những ID nhóm bổ sung của
quá trình gọi điện. Khi cả hai không giữ, nhóm thứ ba được sử dụng.
mở (tên đường dẫn = "/ etc / passwd", flags = O_WRONLY) không thành công, Quyền bị từ chối (13,
EACCES) vì quy trình không có quyền ghi đối với "mật khẩu" thông thường
tệp trong tên đường dẫn "/ Etc"thư mục, quá trình có hiệu lực UID 1000" pmiller "
không khớp với chủ sở hữu tệp thông thường 0 "root" nên chế độ quyền của chủ sở hữu "rw-"
bị bỏ qua, chế độ quyền khác là "r--" và quá trình này không có đặc quyền
(không có khả năng DAC_OVERRIDE)
Một số không gian đáng kể được đưa ra cho lời giải thích này, vì hầu hết người dùng không biết rằng điều này
là cách hệ thống quyền hoạt động. Đặc biệt: chủ sở hữu, nhóm và khác
quyền là độc quyền, chúng không "HOẶC" cùng nhau.

CHIẾN LƯỢC HẤP DẪN WELFARE CUỘC GỌI


Quá trình viết một trình xử lý lỗi cụ thể cho mỗi lệnh gọi hệ thống thường tiết lộ
những điều kỳ quặc thú vị và điều kiện ranh giới, hoặc mù mờ sai(3) giá trị.

EOMEDIUM, Không trung bình tìm thấy
Hành động sao chép đĩa CD là nguồn gốc của tiêu đề cho bài báo này.
$ dd if = / dev / cdrom of = fubar.iso
dd: opens “/ dev / cdrom”: Không tìm thấy phương tiện nào
$
Tác giả tự hỏi tại sao máy tính của anh ấy lại nói với anh ấy rằng không có cái gọi là nhà ngoại cảm
Trung bình. Hoàn toàn khác với thực tế là một số lượng lớn người nói tiếng Anh bản ngữ không
thậm chí biết rằng “media” là số nhiều, hãy để một mình “phương tiện” là số ít, chuỗi
trả lại bởi kinh hoàng(3) đối với ENOMEDIUM ngắn gọn đến mức gần như hoàn toàn không có
nội dung.

Thời Gian mở(2) trả về ENOMEDIUM, thật tuyệt nếu thư viện libexplain có thể mở rộng
một chút về điều này, dựa trên loại ổ đĩa. Ví dụ:
... vì không có đĩa trong ổ mềm
... vì không có đĩa trong ổ CD ‐ ROM
... bởi vì không có băng trong ổ băng
... vì không có thẻ nhớ trong đầu đọc thẻ

Và do đó, nó đã xảy đến...
mở (pathname = "/ dev / cdrom", flags = O_RDONLY) không thành công, Không tìm thấy phương tiện nào (123,
ENOMEDIUM) vì dường như không có đĩa trong ổ CD ‐ ROM
Thủ thuật mà trước đây tác giả không hề hay biết, là mở thiết bị bằng cách sử dụng
Cờ O_NONBLOCK, sẽ cho phép bạn mở ổ đĩa mà không có phương tiện nào trong đó. Sau đó bạn
vấn đề thiết bị cụ thể ioctls(2) yêu cầu cho đến khi bạn tìm ra nó là cái quái gì. (Không
chắc chắn nếu đây là POSIX, nhưng nó dường như cũng hoạt động theo cách đó trong BSD và Solaris, theo
các wodim(1) nguồn.)

Cũng lưu ý cách sử dụng khác nhau của “đĩa” và “đĩa” trong ngữ cảnh. Chuẩn CD có nguồn gốc
ở Pháp, nhưng mọi thứ khác đều có chữ “k”.

LỖI, Bad địa chỉ
Bất kỳ lệnh gọi hệ thống nào nhận đối số con trỏ đều có thể trả về EFAULT. Thư viện libexplain
có thể tìm ra đối số nào bị lỗi và nó thực hiện nó mà không làm ảnh hưởng đến quá trình
(hoặc luồng) xử lý tín hiệu.

Khi có sẵn, nhỏ hơn(2) lệnh gọi hệ thống được sử dụng để hỏi xem vùng bộ nhớ có hợp lệ hay không.
Nó có thể trả về ba kết quả: được ánh xạ nhưng không có trong bộ nhớ vật lý, được ánh xạ và trong vật lý
bộ nhớ và không được ánh xạ. Khi kiểm tra tính hợp lệ của một con trỏ, hai điều đầu tiên là "có"
và câu cuối cùng là "không".

Kiểm tra chuỗi C khó hơn, vì thay vì con trỏ và kích thước, chúng tôi chỉ
có một con trỏ. Để xác định kích thước, chúng tôi sẽ phải tìm NUL, và điều đó có thể
segfault, bắt ‐ 22.

Để giải quyết vấn đề này, thư viện libexplain sử dụng thống kê(2) cuộc gọi sysem (với một
đối số thứ hai tốt) để kiểm tra tính hợp lệ của chuỗi C. Trả lại không thành công && errno == EFAULT
là "không", và bất kỳ câu nào khác là "có". Điều này, tất nhiên giới hạn chuỗi ở PATH_MAX
nhưng đó thường không phải là vấn đề đối với thư viện libexplain, vì đó là
hầu như luôn luôn là chuỗi dài nhất mà nó quan tâm.

EMFILE, Quá nhiều mở các tập tin
Lỗi này xảy ra khi một quá trình đã mở số lượng bộ mô tả tệp tối đa.
Nếu giới hạn thực tế sẽ được in và thư viện libexplain cố gắng làm như vậy, bạn không thể mở
một tập tin trong / proc để đọc nó là gì.
open_max = sysconf (_SC_OPEN_MAX);
Cái này không khó lắm, có một sysconf(3) cách đạt được giới hạn.

ĐIỀN, Quá nhiều mở các tập tin in hệ thống
Lỗi này xảy ra khi giới hạn hệ thống về tổng số tệp đang mở
đạt. Trong trường hợp này không có gì tiện dụng sysconf(3) cách đạt được giới hạn.

Tìm hiểu sâu hơn, người ta có thể phát hiện ra rằng trên Linux có một / proc mục nhập chúng tôi có thể đọc
có được giá trị này. Catch ‐ 22: chúng tôi không có trình mô tả tệp, vì vậy chúng tôi không thể mở tệp để
đọc giới hạn.

Trên Linux, có một lệnh gọi hệ thống để lấy nó, nhưng nó không có chức năng trình bao bọc [e] glibc, vì vậy
bạn phải làm tất cả rất cẩn thận:
Dài
giải thích_maxfile (void)
{
#ifdef __linux__
cấu trúc __sysctl_args đối số;
int32_t tệp tối đa;
size_t maxfile_size = kích thước(tệp tối đa);
int name [] = {CTL_FS, FS_MAXFILE};
memset (& args, 0, sizeof (struct __sysctl_args));
args.name = tên;
args.nlen = 2;
args.oldval = & maxfile;
args.oldlenp = & maxfile_size;
if (syscall (SYS__sysctl, & args)> = 0)
trả về maxfile;
#endif
trả về -1;
}
Điều này cho phép giới hạn được đưa vào thông báo lỗi, khi có sẵn.

EINVAL "Không hợp lệ lý lẽ" vs ENOSYS "Chức năng không thực hiện ”
Các hành động không được hỗ trợ (chẳng hạn như liên kết tượng trưng(2) trên hệ thống tệp FAT) không được báo cáo
nhất quán từ lệnh gọi hệ thống này sang lệnh gọi tiếp theo. Có thể có EINVAL hoặc
ENOSYS đã trở lại.

Do đó, cần phải chú ý đến những trường hợp lỗi này để xử lý chúng cho đúng, đặc biệt
vì EINVAL cũng có thể đề cập đến các vấn đề với một hoặc nhiều đối số lệnh gọi hệ thống.

Chú thích việc này sai(3) is không luôn luôn định
Đôi khi cần phải đọc các nguồn [e] glibc để xác định cách thức và
khi lỗi được trả về cho một số cuộc gọi hệ thống.

giả vờ(3) thư mục số(3)
Người ta thường cho rằng các hàm này không thể trả về lỗi. Điều này chỉ đúng nếu
các dòng đối số là hợp lệ, tuy nhiên chúng có khả năng phát hiện ra một đối số không hợp lệ
con trỏ.

fpathconf(3) đường dẫn(3)
Giá trị trả về của fpathconf(2) đường dẫn(2) hợp pháp có thể là -1, vì vậy nó là
cần thiết để xem nếu sai(3) đã được thiết lập rõ ràng.

ioctls(2)
Giá trị trả về của ioctls(2) hợp pháp có thể là -1, vì vậy cần phải xem nếu
sai(3) đã được thiết lập rõ ràng.

thư mục đọc(3)
Giá trị trả về của thư mục đọc(3) là NULL cho cả lỗi và phần cuối của ‐ tệp. Nó là
cần thiết để xem nếu sai(3) đã được thiết lập rõ ràng.

setbuf(3) bộ đệm(3) setlinebuf(3) setvbuf(3)
Tất cả trừ hàm cuối cùng của những hàm này đều trả về giá trị vô hiệu. Và setvbuf(3) chỉ được ghi nhận là
trả về "non ‐ zero" khi bị lỗi. Nó là cần thiết để xem nếu sai(3) đã được rõ ràng
thiết lập.

sải bước(3) sải bước(3) đi đứng(3) sải bước(3) strtoul(3) sải bước(3)
Các hàm này trả về 0 khi bị lỗi, nhưng đó cũng là một giá trị trả về hợp pháp. Nó là
cần thiết để xem nếu sai(3) đã được thiết lập rõ ràng.

ungetc(3)
Mặc dù chỉ một ký tự sao lưu duy nhất được yêu cầu bởi tiêu chuẩn ANSI C, nó sẽ biến
ra rằng [e] glibc cho phép nhiều hơn ... nhưng điều đó có nghĩa là nó có thể không thành công với ENOMEM. Nó có thể
cũng không thành công với EBADF nếu fp là không có thật. Khó nhất là nếu bạn vượt qua lỗi EOF
trả về xảy ra, nhưng errno không được đặt.

Thư viện libexplain phát hiện tất cả các lỗi này một cách chính xác, ngay cả trong trường hợp
giá trị lỗi không được ghi chép lại, nếu có.

máy tính, Không không gian trái on thiết bị
Khi lỗi này đề cập đến một tệp trên hệ thống tệp, thư viện libexplain sẽ in gắn kết
điểm của hệ thống tệp có vấn đề. Điều này có thể làm cho nguồn gốc của lỗi nhiều
rõ ràng hơn.
ghi (fildes = 1 "example", data = 0xbfff2340, data_size = 5) không thành công, Không còn khoảng trống
trên thiết bị (28, ENOSPC) vì hệ thống tệp có chứa bộ lọc ("/ Home") không có
thêm không gian cho dữ liệu
Khi hỗ trợ thiết bị đặc biệt hơn được thêm vào, các thông báo lỗi dự kiến ​​sẽ bao gồm thiết bị
tên và kích thước thực tế của thiết bị.

EROFS, Chỉ đọc hồ sơ hệ thống
Khi lỗi này đề cập đến một tệp trên hệ thống tệp, thư viện libexplain sẽ in gắn kết
điểm của hệ thống tệp có vấn đề. Điều này có thể làm cho nguồn gốc của lỗi nhiều
rõ ràng hơn.

Khi hỗ trợ thiết bị đặc biệt hơn được thêm vào, các thông báo lỗi dự kiến ​​sẽ bao gồm thiết bị
tên và loại.
mở (pathname = "/ dev / fd0", O_RDWR, 0666) không thành công, hệ thống tệp chỉ đọc (30, EROFS)
bởi vì đĩa mềm có bộ bảo vệ ghi

... vì đĩa CD ‐ ROM không thể ghi được
... bởi vì thẻ nhớ có bộ tab chống ghi
... bởi vì băng từ ½ inch không có vòng ghi

đổi tên
Sản phẩm đổi tên(2) lệnh gọi hệ thống được sử dụng để thay đổi vị trí hoặc tên của một tệp, di chuyển nó
giữa các thư mục nếu được yêu cầu. Nếu tên đường dẫn đích đã tồn tại, nó sẽ là
được thay thế nguyên tử, để không có điểm nào mà quá trình khác cố gắng
truy cập nó sẽ thấy nó bị thiếu.

Tuy nhiên, có những hạn chế: bạn chỉ có thể đổi tên một thư mục trên đầu một thư mục khác
nếu thư mục đích không trống.
đổi tên (oldpath = "foo", newpath = "bar") không thành công, Thư mục không trống (39,
ENOTEMPTY) bởi vì newpath không phải là một thư mục trống; nghĩa là, nó chứa các mục nhập
khác với "." và ".."
Bạn cũng không thể đổi tên một thư mục trên đầu một thư mục không phải ‐.
đổi tên (oldpath = "foo", newpath = "bar") không thành công, Không phải thư mục (20, ENOTDIR)
bởi vì oldpath là một thư mục, nhưng newpath là một tệp thông thường, không phải là một thư mục
Cũng không được phép ngược lại
đổi tên (oldpath = "foo", newpath = "bar") không thành công, Là một thư mục (21, EISDIR)
bởi vì newpath là một thư mục, nhưng oldpath là một tệp thông thường, không phải là một thư mục

Tất nhiên, điều này làm cho công việc của thư viện libexplain phức tạp hơn, bởi vì
bỏ liên kết(2) hoặc là rm(2) lệnh gọi hệ thống được gọi ngầm bởi đổi tên(2), và tất cả
bỏ liên kết(2) hoặc là rm(2) các lỗi cũng phải được phát hiện và xử lý.

Dup2
Sản phẩm Dup2(2) lệnh gọi hệ thống được sử dụng để tạo bộ mô tả tệp thứ hai tham chiếu đến
cùng một đối tượng như trình mô tả tệp đầu tiên. Thông thường, điều này được sử dụng để triển khai đầu vào shell
và chuyển hướng đầu ra.

Điều thú vị là, giống như đổi tên(2) có thể đổi tên nguyên tử một tệp trên đầu trang
tệp hiện có và xóa tệp cũ, Dup2(2) có thể thực hiện việc này trên một tệp đã mở
bộ mô tả.

Một lần nữa, điều này làm cho công việc của thư viện libexplain trở nên phức tạp hơn, bởi vì gần(2)
lệnh gọi hệ thống được gọi ngầm bởi Dup2(2), và tất cả gần(2) lỗi phải được
cũng được phát hiện và xử lý.

ƯU ĐÃI IN IOCTL HỖ TRỢ


Sản phẩm ioctls(2) cuộc gọi hệ thống cung cấp cho tác giả trình điều khiển thiết bị một cách để giao tiếp với
không gian người dùng không phù hợp với API hạt nhân hiện có. Nhìn thấy ioctl_list(2).

Giải mã Yêu cầu Số
Từ một cái nhìn lướt qua ioctls(2) giao diện, dường như sẽ có một giao diện lớn nhưng hữu hạn
số lượng có thể ioctls(2) yêu cầu. Mỗi khác nhau ioctls(2) yêu cầu có hiệu quả
một lệnh gọi hệ thống khác, nhưng hoàn toàn không có bất kỳ loại ‐ an toàn nào - trình biên dịch không thể giúp
lập trình viên hiểu đúng. Đây có lẽ là động lực đằng sau tcflush(3)
bạn bè.

Ấn tượng ban đầu là bạn có thể giải mã ioctls(2) yêu cầu sử dụng một công tắc lớn
bản tường trình. Điều này hóa ra là không khả thi bởi vì một người rất nhanh chóng phát hiện ra rằng nó là
không thể bao gồm tất cả các tiêu đề hệ thống cần thiết xác định các ioctls(2)
yêu cầu, bởi vì họ rất khó chơi thân thiện với nhau.

Một cái nhìn sâu hơn cho thấy rằng có một loạt các số yêu cầu "riêng tư" và thiết bị
các tác giả trình điều khiển được khuyến khích sử dụng chúng. Điều này có nghĩa là có một
tập hợp các yêu cầu, với số lượng yêu cầu không rõ ràng, hơn là rõ ràng ngay lập tức. Cũng thế,
cũng có một số mơ hồ lịch sử.

Chúng tôi đã biết rằng việc chuyển đổi là không thực tế, nhưng bây giờ chúng tôi biết điều đó để chọn
tên yêu cầu thích hợp và lời giải thích, chúng tôi phải xem xét không chỉ số yêu cầu mà
cũng là bộ mô tả tệp.

Việc thực hiện ioctls(2) hỗ trợ trong thư viện libexplain là có một bảng
trỏ tới ioctls(2) bộ mô tả yêu cầu. Mỗi bộ mô tả này bao gồm một tùy chọn
con trỏ đến một hàm định hướng.

Mỗi yêu cầu thực sự được triển khai trong một tệp nguồn riêng biệt, do đó
các tệp bao gồm không có nghĩa vụ chơi đẹp với những người khác.

Đại diện
Triết lý đằng sau thư viện libexplain là cung cấp càng nhiều thông tin càng
có thể, bao gồm một bản trình bày chính xác của lệnh gọi hệ thống. Trong trường hợp
ioctls(2) điều này có nghĩa là in đúng số yêu cầu (theo tên) và cũng chính xác (hoặc
ít nhất là hữu ích) đại diện của đối số thứ ba.

Sản phẩm ioctls(2) nguyên mẫu trông như thế này:
int ioctl (int fildes, int request, ...);
mà sẽ có báo động an toàn loại ‐ của bạn tắt. Nội bộ đối với [e] glibc, điều này đã được chuyển
thành nhiều dạng khác nhau:
int __ioctl (int fildes, int request, long arg);
int __ioctl (int fildes, int request, void * arg);
và giao diện syscall hạt nhân Linux mong đợi
asmlinkage long sys_ioctl (unsigned int fildes, unsigned int request, unsigned long
cãi);
Sự thay đổi cực độ của đối số thứ ba là một thách thức, khi thư viện giải thích tự do
cố gắng in ra một biểu diễn của đối số thứ ba đó. Tuy nhiên, khi số yêu cầu
đã được phân loại, mỗi mục nhập trong bảng ioctl của thư viện libexplain có một
chức năng print_data tùy chỉnh (OO được thực hiện thủ công).

Giải thích
Có ít vấn đề hơn khi xác định lời giải thích được sử dụng. Một khi số yêu cầu
đã được phân loại, mỗi mục nhập trong bảng ioctl của thư viện libexplain có một tùy chỉnh
chức năng print_explanation (một lần nữa, OO được thực hiện thủ công).

Không giống như phần 2 và phần 3 lệnh gọi hệ thống, hầu hết ioctls(2) yêu cầu không có lỗi
được lập thành tài liệu. Điều này có nghĩa là, để đưa ra các mô tả lỗi tốt, cần phải đọc kernel
nguồn để khám phá

· gì sai(3) các giá trị có thể được trả về, và

· Nguyên nhân của mỗi lỗi.

Do bản chất OO của điều phối lệnh gọi hàm trong nhân, bạn cần đọc
tất cả các các nguồn thực hiện điều đó ioctls(2) yêu cầu, không chỉ là việc thực hiện chung chung. Nó
dự kiến ​​rằng các hạt nhân khác nhau sẽ có số lỗi khác nhau và
nguyên nhân lỗi khác nhau.

EINVAL vs THƯỞNG THỨC
Tình hình thậm chí còn tồi tệ hơn đối với ioctls(2) các yêu cầu hơn là các cuộc gọi hệ thống, với EINVAL và
ENOTTY cả hai đều được sử dụng để chỉ ra rằng một ioctls(2) yêu cầu không phù hợp ở chỗ
ngữ cảnh và đôi khi ENOSYS, ENOTSUP và EOPNOTSUPP (có nghĩa là được sử dụng cho các ổ cắm) như
Tốt. Có những nhận xét trong các nguồn nhân Linux dường như cho thấy một sự tiến bộ
đang trong quá trình dọn dẹp. Để có thêm sự hỗn loạn, BSD thêm ENOIOCTL vào sự nhầm lẫn.

Do đó, cần phải chú ý đến những trường hợp lỗi này để xử lý chúng cho đúng, đặc biệt
vì EINVAL cũng có thể đề cập đến các vấn đề với một hoặc nhiều đối số lệnh gọi hệ thống.

intptr_t
Tiêu chuẩn C99 xác định một kiểu số nguyên được đảm bảo có thể chứa bất kỳ con trỏ nào
mà không mất đại diện.

Nguyên mẫu syscall hàm trên sẽ được viết tốt hơn
long sys_ioctl (unsigned int fildes, unsigned int request, intptr_t arg);
Vấn đề là sự bất hòa về nhận thức do thiết bị cụ thể hoặc hệ thống cụ thể gây ra
ioctls(2) triển khai, chẳng hạn như:
long vfs_ioctl (struct file * filp, unsigned int cmd, unsigned long arg);
Đa số ioctls(2) các yêu cầu thực sự có đối số thứ ba int * arg. Nhưng có nó
khai báo dài dẫn đến mã coi điều này là long * arg. Điều này là vô hại trên 32 ‐ bit
(sizeof (long) == sizeof (int)) nhưng khó chịu trên 64 ‐ bit (sizeof (long)! = sizeof (int)).
Tùy thuộc vào kết quả cuối cùng, bạn có đạt được hay không nhận được giá trị mà bạn mong đợi, nhưng bạn luôn luôn được
một nét vẽ nguệch ngoạc trong bộ nhớ hoặc chữ viết nguệch ngoạc ngăn xếp cũng vậy.

Viết tất cả những điều này dưới dạng
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);
long vfs_ioctl (struct file * filp, unsigned int cmd, intptr_t arg);
nhấn mạnh rằng số nguyên chỉ là một số nguyên để biểu thị một đại lượng gần như
luôn luôn là một loại con trỏ không liên quan.

KẾT LUẬN


Sử dụng libexplain, người dùng của bạn sẽ thích nó.

BẢN QUYỀN


phiên bản libexplain 1.4
Bản quyền (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Peter Miller

Sử dụng giải thích_lca2010 trực tuyến bằng các dịch vụ onworks.net


Máy chủ & Máy trạm miễn phí

Tải xuống ứng dụng Windows & Linux

  • 1
    VÒI
    VÒI
    SWIG là một công cụ phát triển phần mềm
    kết nối các chương trình được viết bằng C và
    C ++ với nhiều cấp độ cao
    ngôn ngữ lập trình. SWIG được sử dụng với
    khác nhau...
    Tải xuống SWIG
  • 2
    Chủ đề WooCommerce Nextjs React
    Chủ đề WooCommerce Nextjs React
    Chủ đề React WooCommerce, được xây dựng với
    JS tiếp theo, Webpack, Babel, Node và
    Express, sử dụng GraphQL và Apollo
    Khách hàng. Cửa hàng WooCommerce trong React (
    chứa: Sản phẩm ...
    Tải xuống Chủ đề phản ứng WooC Commerce Nextjs
  • 3
    Archlabs_repo
    Archlabs_repo
    Gói repo cho ArchLabs Đây là một
    ứng dụng cũng có thể được tìm nạp
    từ
    https://sourceforge.net/projects/archlabs-repo/.
    Nó đã được lưu trữ trong OnWorks ở...
    Tải xuống archlabs_repo
  • 4
    Dự án Zephyr
    Dự án Zephyr
    Dự án Zephyr là một thế hệ mới
    hệ điều hành thời gian thực (RTOS)
    hỗ trợ nhiều phần cứng
    kiến trúc. Nó dựa trên một
    hạt nhân có dấu chân nhỏ ...
    Tải xuống dự án Zephyr
  • 5
    SCons
    SCons
    SCons là một công cụ xây dựng phần mềm
    đó là một sự thay thế vượt trội so với
    công cụ xây dựng "Make" cổ điển
    tất cả chúng ta đều biết và yêu thích. SCons là
    thực hiện một ...
    Tải xuống SCons
  • 6
    PSeInt
    PSeInt
    PSeInt là trình thông dịch mã giả cho
    sinh viên lập trình nói tiếng Tây Ban Nha.
    Mục đích chính của nó là trở thành một công cụ để
    học và hiểu cơ bản
    quan niệm ...
    Tải xuống PSeInt
  • Khác »

Lệnh Linux

  • 1
    7z
    7z
    7z - Trình lưu trữ tệp cao nhất
    tỷ lệ nén ...
    Chạy 7z
  • 2
    7za
    7za
    7za - Trình lưu trữ tệp cao nhất
    tỷ lệ nén ...
    Chạy 7za
  • 3
    creepy
    creepy
    CREEPY - Một thông tin định vị địa lý
    công cụ tổng hợp MÔ TẢ: rùng rợn là một
    ứng dụng cho phép bạn thu thập
    thông tin liên quan đến vị trí địa lý về
    người dùng từ...
    Chạy rùng rợn
  • 4
    cricket-biên dịch
    cricket-biên dịch
    cricket - Một chương trình để quản lý
    thu thập và hiển thị chuỗi thời gian
    dữ liệu ...
    Chạy cricket-biên dịch
  • 5
    g-quấn-config
    g-quấn-config
    g-wrap-config - tập lệnh để nhận
    thông tin về phiên bản đã cài đặt
    của G-Wrap...
    Chạy g-wrap-config
  • 6
    g.accessgrass
    g.accessgrass
    g.access - Kiểm soát quyền truy cập vào
    bộ bản đồ hiện tại cho những người dùng khác trên
    hệ thống. Nếu không có tùy chọn nào được đưa ra, hãy in
    tình trạng hiện tại. TỪ KHÓA: tổng hợp, bản đồ
    quản lý,...
    Chạy g.accessgrass
  • Khác »

Ad