ภาษาอังกฤษภาษาฝรั่งเศสสเปน

Ad


ไอคอน Fav ของ OnWorks

อธิบาย_lca2010 - ออนไลน์ในคลาวด์

เรียกใช้ expand_lca2010 ในผู้ให้บริการโฮสต์ฟรีของ OnWorks ผ่าน Ubuntu Online, Fedora Online, โปรแกรมจำลองออนไลน์ของ Windows หรือโปรแกรมจำลองออนไลน์ของ MAC OS

นี่คือคำสั่ง description_lca2010 ที่สามารถเรียกใช้ในผู้ให้บริการโฮสต์ฟรีของ OnWorks โดยใช้เวิร์กสเตชันออนไลน์ฟรีของเรา เช่น Ubuntu Online, Fedora Online, โปรแกรมจำลองออนไลน์ของ Windows หรือโปรแกรมจำลองออนไลน์ของ MAC OS

โครงการ:

ชื่อ


Explain_lca2010 - ไม่พบสื่อ: เมื่อถึงเวลาต้องหยุดพยายามอ่าน ตกใจ(3) ของ
ใจ

แรงจูงใจ


แนวคิดเรื่อง libexplain เกิดขึ้นกับฉันเมื่อต้นทศวรรษ 1980 เมื่อใดก็ตามที่ระบบเรียก
ส่งคืนข้อผิดพลาด เคอร์เนลรู้ว่าเกิดอะไรขึ้น... และบีบอัดสิ่งนี้เป็น
น้อยกว่า 8 บิตของ Errno. พื้นที่ผู้ใช้สามารถเข้าถึงข้อมูลเดียวกับเคอร์เนล it
ควรจะเป็นไปได้สำหรับพื้นที่ผู้ใช้ในการพิจารณาว่าเกิดอะไรขึ้นเพื่อกระตุ้นข้อผิดพลาด
กลับมาและใช้สิ่งนี้เพื่อเขียนข้อความแสดงข้อผิดพลาดที่ดี

มันจะง่ายอย่างนั้นเหรอ?

ความผิดพลาด ข้อความ as กลเม็ดเด็ดพราย
ข้อความแสดงข้อผิดพลาดที่ดีมักเป็นงาน "หนึ่งเปอร์เซ็นต์" ที่หลุดจากกำหนดการ
แรงกดดันบีบคั้นโครงการของคุณ อย่างไรก็ตาม ข้อความแสดงข้อผิดพลาดที่ดีสามารถสร้างสิ่งที่ยิ่งใหญ่ได้
การปรับปรุงประสบการณ์ผู้ใช้ที่ไม่สมส่วนเมื่อผู้ใช้เดินเข้าไปในที่น่ากลัว
ดินแดนที่ไม่รู้จักมักไม่พบ นี่ไม่ใช่งานง่าย

ในฐานะที่เป็นโปรแกรมเมอร์ตัวอ่อน ผู้เขียนไม่เห็นปัญหา (ถูกต้องสมบูรณ์) ข้อผิดพลาด
ข้อความเช่นนี้:
ข้อยกเว้นแบบลอยตัว (คอร์ดัมพ์)
จนกว่าจะมีการชี้ให้เห็นการตีความอื่นที่ไม่ใช่โปรแกรมเมอร์ แต่นั่นไม่ใช่
สิ่งเดียวที่ผิดปกติกับข้อความแสดงข้อผิดพลาด Unix คุณเห็นข้อความแสดงข้อผิดพลาดบ่อยเพียงใด เช่น:
$ ./โง่
เปิดไฟล์ไม่ได้
$
มีสองตัวเลือกสำหรับนักพัฒนา ณ จุดนี้:

1.
คุณสามารถเรียกใช้ดีบักเกอร์เช่น จีดีบี(1) หรือ

2.
คุณสามารถใช้ได้ สเตรซ(1) หรือ มัด(1) มองเข้าไปข้างใน

· จำไว้ว่าผู้ใช้ของคุณอาจไม่สามารถเข้าถึงเครื่องมือเหล่านี้ได้ด้วยซ้ำ นับประสาความสามารถ
เพื่อใช้พวกเขา (มันนานมากแล้วตั้งแต่ ยูนิกซ์ มือใหม่ หมายถึง “ได้เขียนเพียง หนึ่ง
ไดรเวอร์อุปกรณ์”)

อย่างไรก็ตาม ในตัวอย่างนี้ ใช้ สเตรซ(1) เผย
$ สเตรซ -e ติดตาม = เปิด ./โง่
open("some/file", O_RDONLY) = -1 ENOENT (ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว)
เปิดไฟล์ไม่ได้
$
นี่เป็นข้อมูลที่มากกว่าข้อความแสดงข้อผิดพลาดอย่างมาก โดยปกติ
รหัสที่มาโง่มีลักษณะเช่นนี้
int fd = เปิด ("บางสิ่งบางอย่าง", O_RDONLY);
ถ้า (fd < 0)
{
fprintf(stderr, "ไม่สามารถเปิดไฟล์\n");
ทางออก(1);
}
ผู้ใช้ไม่ได้บอก ที่ ไฟล์และยังไม่สามารถบอกผู้ใช้ได้ ที่ ข้อผิดพลาด. เป็นไฟล์
แม้กระทั่งที่นั่น? มีปัญหาการอนุญาตหรือไม่? มันบอกคุณว่ากำลังพยายามเปิด
ไฟล์ แต่นั่นอาจเป็นเรื่องบังเอิญ

หยิบไม้เบาะแสของคุณและไปเอาชนะโปรแกรมเมอร์ตัวอ่อนด้วยมัน บอกเขาเกี่ยวกับ ความผิดพลาด(3)
ครั้งต่อไปที่คุณใช้โปรแกรม คุณจะเห็นข้อความแสดงข้อผิดพลาดอื่น:
$ ./โง่
เปิด: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
$
ก้าวหน้า แต่ไม่ใช่สิ่งที่เราคาดหวัง ผู้ใช้จะแก้ไขปัญหาได้อย่างไรหากข้อความแสดงข้อผิดพลาด
ไม่บอกเขาว่ามีปัญหาอะไร? เมื่อดูจากแหล่งที่มาเราจะเห็น
int fd = เปิด ("บางสิ่งบางอย่าง", O_RDONLY);
ถ้า (fd < 0)
{
perror("เปิด");
ทางออก(1);
}
ได้เวลาวิ่งอีกครั้งด้วยไม้เบาะแส คราวนี้ ข้อความแสดงข้อผิดพลาดใช้เวลาหนึ่งขั้นตอน
ไปข้างหน้าและถอยหลังหนึ่งก้าว:
$ ./โง่
บางสิ่งบางอย่าง: ไม่พบไฟล์หรือโฟลเดอร์ที่คุณค้นหา
$
ตอนนี้เรารู้แล้วว่าไฟล์ที่พยายามเปิดอยู่แต่ไม่ได้รับแจ้งอีกต่อไปว่าเป็นไฟล์ เปิด(2)
ที่ล้มเหลว ในกรณีนี้อาจไม่มีความสำคัญ แต่อาจมีความสำคัญสำหรับ
เรียกระบบอื่นๆ อาจจะเป็น ครีเอทีฟ(2) แทนการดำเนินการที่มีความหมายว่า
จำเป็นต้องมีการอนุญาตที่แตกต่างกัน
อักขระ const *ชื่อไฟล์ = "บางสิ่งบางอย่าง";
int fd = เปิด (ชื่อไฟล์ O_RDONLY);
ถ้า (fd < 0)
{
ความหวาดกลัว (ชื่อไฟล์);
ทางออก(1);
}
โค้ดตัวอย่างข้างต้นนั้น น่าเสียดายที่โปรแกรมเมอร์ที่ไม่ใช่ตัวอ่อนเป็นแบบอย่างด้วย เวลา
เพื่อบอกผู้เรียนพาดาวันของเราเกี่ยวกับ ตกใจ(3) การเรียกระบบ
$ ./โง่
เปิด บางสิ่งบางอย่าง: ไม่พบไฟล์หรือโฟลเดอร์ที่คุณค้นหา
$
ข้อมูลนี้สามารถนำเสนอต่อผู้ใช้ได้สูงสุด รหัสดูเหมือน
นี้:
อักขระ const *ชื่อไฟล์ = "บางสิ่งบางอย่าง";
int fd = เปิด (ชื่อไฟล์ O_RDONLY);
ถ้า (fd < 0)
{
fprintf(stderr, "เปิด %s: %s\n", ชื่อไฟล์, strerror(errno));
ทางออก(1);
}
ตอนนี้ เรามีการเรียกระบบ ชื่อไฟล์ และสตริงข้อผิดพลาด นี้มีทั้งหมด
ข้อมูลที่ สเตรซ(1) พิมพ์ ที่ดีเท่าที่จะได้รับ

หรือไม่?

ข้อ จำกัด of ความผิดพลาด และ ตกใจ
ปัญหาที่ผู้เขียนเห็นในทศวรรษ 1980 คือข้อความแสดงข้อผิดพลาดไม่สมบูรณ์
“ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว” หมายถึง “บาง” ไดเร็กทอรี หรือไปที่ “สิ่ง” ไฟล์ใน
"บาง” ไดเรกทอรี?

ดูหน้าคนอย่างรวดเร็วสำหรับ ตกใจ(3) กำลังบอกว่า:
strerror - สตริงส่งคืนที่อธิบายหมายเลขข้อผิดพลาด
หมายเหตุให้ดี: มันกำลังอธิบายข้อผิดพลาด จำนวนไม่ใช่ข้อผิดพลาด

ในทางกลับกัน เคอร์เนล รู้ ข้อผิดพลาดคืออะไร มีจุดเฉพาะใน
รหัสเคอร์เนลเกิดจากเงื่อนไขเฉพาะ โดยที่รหัสเคอร์เนลแยกสาขาและกล่าวว่า "ไม่"
โปรแกรมพื้นที่ผู้ใช้สามารถระบุเงื่อนไขเฉพาะและเขียนข้อผิดพลาดที่ดีกว่าได้หรือไม่
ข้อความ?

อย่างไรก็ตาม ปัญหายิ่งลึกลงไปอีก เกิดอะไรขึ้นถ้าปัญหาเกิดขึ้นระหว่าง อ่าน(2) ระบบ
โทรมากกว่า เปิด(2) โทร? มันง่ายสำหรับข้อความแสดงข้อผิดพลาดที่เกี่ยวข้องกับ
เปิด(2) เพื่อรวมชื่อไฟล์ไว้ตรงนั้น แต่เพื่อให้สามารถใส่ชื่อไฟล์ได้
ในข้อผิดพลาดที่เกี่ยวข้องกับ อ่าน(2) การเรียกระบบ คุณต้องส่งชื่อไฟล์ทั้งหมด
วิธีลง call stack เช่นเดียวกับ file descriptor

และนี่คือบิตที่เกรี้ยวกราด: เคอร์เนลรู้แล้วว่าไฟล์นั้นชื่อไฟล์อะไร
descriptor มีความเกี่ยวข้องกับ ทำไมโปรแกรมเมอร์ต้องส่งข้อมูลซ้ำซ้อนทั้งหมด
ทางลง call stack เพียงเพื่อปรับปรุงข้อความแสดงข้อผิดพลาดที่อาจไม่เคยออก? ใน
ในความเป็นจริง โปรแกรมเมอร์หลายคนไม่สนใจ และข้อความแสดงข้อผิดพลาดที่เป็นผลกลับแย่ลงไปอีกสำหรับ
มัน

แต่นั่นคือช่วงทศวรรษ 1980 บน PDP11 ที่มีทรัพยากรจำกัดและไม่มีไลบรารีที่ใช้ร่วมกัน กลับ
แล้วไม่มีรสชาติของ Unix รวมอยู่ด้วย / proc แม้แต่ในรูปแบบพื้นฐานและ ลซ(1) โปรแกรม
อยู่ห่างออกไปกว่าทศวรรษ แนวคิดจึงถูกจัดว่าทำไม่ได้

ชั้น ความไม่มีที่สิ้นสุด ระบบขอใช้บริการ
ลองนึกภาพว่าคุณกำลังสนับสนุนระดับอินฟินิตี้ รายละเอียดงานของคุณบอกว่าคุณไม่เคย
เคย ต้องพูดคุยกับผู้ใช้ แล้วทำไมยังมีคนอยากได้อยู่เรื่อยๆ
คุณกูรู Unix ในพื้นที่เพื่อถอดรหัสข้อความแสดงข้อผิดพลาดอื่นหรือไม่

น่าแปลกที่ 25 ปีต่อมา แม้จะมีระบบการอนุญาตแบบง่าย ๆ ก็ตาม ใช้งานด้วยความสมบูรณ์
ความสม่ำเสมอ ผู้ใช้ Unix ส่วนใหญ่ยังไม่รู้วิธีถอดรหัส "ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว"
หรือข้อความแสดงข้อผิดพลาดที่เป็นความลับอื่นๆ ที่พวกเขาเห็นทุกวัน หรืออย่างน้อยก็คลุมเครือถึง
พวกเขา

คงจะดีไม่น้อยหากการสนับสนุนด้านเทคนิคระดับแรกไม่จำเป็นต้องถอดรหัสข้อความแสดงข้อผิดพลาด
จะดีกว่าไหมถ้ามีข้อความแสดงข้อผิดพลาดที่ผู้ใช้เข้าใจได้โดยไม่ต้องโทร
การสนับสนุนด้านเทคนิค?

วันนี้ / proc บน Linux เป็นมากกว่าการให้ข้อมูลที่จำเป็นในการถอดรหัส
ข้อความแสดงข้อผิดพลาดส่วนใหญ่ และชี้ให้ผู้ใช้ทราบสาเหตุที่แท้จริงของ
ปัญหา. บนระบบที่มีข้อจำกัด / proc การดำเนินการ, the ลซ(1) คำสั่งกรอกได้
ช่องว่างมากมาย

ในปี 2008 กระแสการร้องขอการแปลเกิดขึ้นกับผู้เขียนบ่อยเกินไป มันเป็น
ถึงเวลาทบทวนความคิดอายุ 25 ปีนั้นอีกครั้ง และ libexplain ก็คือผลลัพธ์

ใช้ DIE ห้องสมุด


อินเทอร์เฟซไปยังไลบรารีพยายามให้สอดคล้องกัน หากเป็นไปได้ มาเริ่มกันที่ an
ตัวอย่างการใช้ ตกใจ(3):
ถ้า (เปลี่ยนชื่อ (old_path, new_path) < 0)
{
fprintf(stderr, "เปลี่ยนชื่อ %s %s: %s\n", old_path, new_path,
strerror(เออร์โน));
ทางออก(1);
}
แนวคิดเบื้องหลัง libexplain คือการจัดเตรียม a ตกใจ(3) เทียบเท่ากับ แต่ละ ระบบเรียก
ปรับให้เหมาะกับการเรียกระบบนั้นโดยเฉพาะ เพื่อให้สามารถระบุข้อผิดพลาดที่มีรายละเอียดมากขึ้น
ข้อความที่มีข้อมูลจำนวนมากที่คุณเห็นภายใต้หัวข้อ "ข้อผิดพลาด" ของส่วน
และ 2 3 มนุษย์ หน้าเสริมด้วยข้อมูลสภาพจริงข้อโต้แย้งที่เกิดขึ้นจริง
ค่าและขีดจำกัดของระบบ

พื้นที่ ง่าย กรณี
พื้นที่ ตกใจ(3) การเปลี่ยน:
ถ้า (เปลี่ยนชื่อ (old_path, new_path) < 0)
{
fprintf(stderr, "%s\n", description_rename(old_path, new_path));
ทางออก(1);
}

พื้นที่ เออร์โน กรณี
นอกจากนี้ยังเป็นไปได้ที่จะผ่านการที่ชัดเจน Errno(3) ค่าถ้าคุณต้องทำบางอย่างก่อน
การประมวลผลที่จะรบกวน Errnoเช่น การกู้คืนข้อผิดพลาด:
ถ้า (เปลี่ยนชื่อ (old_path, new_path < 0))
{
int old_errno = เออร์โน;
...รหัส ที่ รบกวน Errno...
fprintf(stderr, "%s\n", อธิบาย_errno_rename(old_errno,
old_path, new_path));
ทางออก(1);
}

พื้นที่ มัลติเธรด กรณี
แอปพลิเคชั่นบางตัวเป็นแบบมัลติเธรด ดังนั้นจึงไม่สามารถแชร์ภายในของ libexplain ได้
กันชน. คุณสามารถจัดหาบัฟเฟอร์ของคุณเองโดยใช้
ถ้า (ยกเลิกการเชื่อมโยง (ชื่อพาธ))
{
ข้อความถ่าน[3000];
อธิบาย_message_unlink(ข้อความ ขนาดของ(ข้อความ) ชื่อพา ธ );
error_dialog(ข้อความ);
กลับ -1;
}
และเพื่อความครบถ้วนทั้ง Errno(3) และเธรดที่ปลอดภัย:
ssize_t nbytes = อ่าน (fd, data, sizeof (ข้อมูล));
ถ้า (nbytes < 0)
{
ข้อความถ่าน[3000];
int old_errno = เออร์โน;
...ความผิดพลาด การฟื้นตัว...
อธิบาย_message_errno_read(ข้อความ ขนาดของ(ข้อความ),
old_errno, fd, data, sizeof(ข้อมูล));
error_dialog(ข้อความ);
กลับ -1;
}

สิ่งเหล่านี้เป็นการทดแทนสำหรับ strerror_r(3) บนระบบที่มีมัน

อินเตอร์เฟซ เด็ก
ชุดของฟังก์ชันที่เพิ่มเป็นฟังก์ชันอำนวยความสะดวก เพื่อแสวงหาโปรแกรมเมอร์ให้ใช้
ไลบรารี libexplain กลายเป็นฟังก์ชัน libexplain ที่ใช้บ่อยที่สุดของผู้เขียนใน
โปรแกรมบรรทัดคำสั่ง:
int fd = อธิบาย_creat_or_die (ชื่อไฟล์, 0666);
ฟังก์ชันนี้พยายามสร้างไฟล์ใหม่ หากไม่สามารถทำได้ จะพิมพ์ข้อความแสดงข้อผิดพลาดและ
ออกด้วย EXIT_FAILURE หากไม่มีข้อผิดพลาด จะส่งคืน file descriptor ใหม่

ฟังก์ชั่นที่เกี่ยวข้อง:
int fd = อธิบาย_creat_on_error (ชื่อไฟล์, 0666);
จะพิมพ์ข้อความแสดงข้อผิดพลาดเมื่อล้มเหลว แต่ยังส่งคืนผลลัพธ์ข้อผิดพลาดเดิมและ
Errno(3) ไม่ถูกข่มเหงเช่นกัน

ทั้งหมด อื่น ๆ ระบบ โทร
โดยทั่วไปการเรียกระบบทุกครั้งจะมีไฟล์รวมของตัวเอง
#รวมชื่อ.h>
ที่กำหนดฟังก์ชันต้นแบบสำหรับ XNUMX ฟังก์ชัน:

· อธิบาย_ชื่อ,

· อธิบาย_errno_ชื่อ,

· อธิบาย_ข้อความ_ชื่อ,

· อธิบาย_message_errno_ชื่อ,

· อธิบาย_ชื่อ_or_die และ

· อธิบาย_ชื่อ_on_ข้อผิดพลาด

ทุกฟังก์ชันต้นแบบมีเอกสาร Doxygen และเอกสารนี้ is ไม่ เปลือยเปล่า
เมื่อมีการติดตั้งไฟล์รวม

พื้นที่ รอ(2) การโทรของระบบ (และเพื่อน) มีรูปแบบพิเศษบางอย่างที่ตีความความล้มเหลวด้วย
ให้เป็นสถานะออกที่ไม่ใช่ EXIT_SUCCESS สิ่งนี้ใช้กับ ระบบ(3) และ ปิด(3) เช่น
ดี.

ความครอบคลุมรวมถึงการเรียกระบบ 221 ครั้งและคำขอ ioctl 547 รายการ มีระบบอีกมากมาย
ยังเรียกร้องให้ดำเนินการ ระบบเรียกที่ไม่เคยกลับมาเช่น ทางออก(2) ไม่อยู่
ในห้องสมุดและจะไม่มีวันเป็น ดิ exec ครอบครัวของระบบเรียก เป็น ได้รับการสนับสนุนเพราะ
พวกเขากลับมาเมื่อมีข้อผิดพลาด

แคท
นี่คือสิ่งที่โปรแกรม "cat" สมมติอาจมีหน้าตา โดยมีการรายงานข้อผิดพลาดแบบเต็ม
โดยใช้ libexplain
#รวม
# รวม
#รวม
มีหนึ่งรายการสำหรับ libexplain บวกกับผู้ต้องสงสัยตามปกติ (หากต้องการลดค่า
โหลดตัวประมวลผลล่วงหน้า คุณสามารถใช้เฉพาะชื่อ.h> รวมถึง.)
โมฆะคง
กระบวนการ (ไฟล์ *fp)
{
สำหรับ (;;)
{
บัฟเฟอร์ถ่าน [4096];
size_t n = อธิบาย_fread_or_die(บัฟเฟอร์, 1, sizeof(บัฟเฟอร์), fp);
ถ้า (!n)
break;
อธิบาย_fwrite_or_die(บัฟเฟอร์, 1, n, stdout);
}
}
พื้นที่ กระบวนการ ฟังก์ชั่นคัดลอกสตรีมไฟล์ไปยังเอาต์พุตมาตรฐาน หากมีข้อผิดพลาดเกิดขึ้น
สำหรับการอ่านหรือการเขียนจะมีการรายงาน (และชื่อเส้นทางจะรวมอยู่ใน
ข้อผิดพลาด) และคำสั่งออกด้วย EXIT_FAILURE เราไม่ได้กังวลเกี่ยวกับการติดตาม
ชื่อพาธ หรือส่งต่อไปยัง call stack
int
หลัก (int argc, อักขระ **argv)
{
สำหรับ (;;)
{
int c = getopt(argc, argv, "o:");
ถ้า (c == EOF)
break;
สวิตช์ (ค)
{
กรณี 'o':
อธิบาย_freopen_or_die(optarg, "w", stdout);
break;
ส่วนที่สนุกของโค้ดนี้คือ libexplain สามารถรายงานข้อผิดพลาดได้ รวมทั้ง ชื่อพา ธ แม้
ถ้าคุณ ทำไม่ได้ เปิด stdout อีกครั้งอย่างชัดเจนตามที่ทำที่นี่ เราไม่ได้กังวลเกี่ยวกับ
ติดตามชื่อไฟล์
ค่าเริ่มต้น:
fprintf(stderr, "การใช้งาน: %ss [ -o ] ...\n",
อาร์จีวี[0]);
ส่งคืน EXIT_FAILURE;
}
}
ถ้า (optind == argc)
กระบวนการ (stdin);
อื่น
{
ในขณะที่ (optind < argc)
{
ไฟล์ *fp = อธิบาย_fopen_or_die(argv[optind]++, "r");
กระบวนการ(fp);
อธิบาย_fclose_or_die(fp);
}
}
เอาต์พุตมาตรฐานจะถูกปิดโดยปริยาย แต่สายเกินไปสำหรับการรายงานข้อผิดพลาด
ออก ดังนั้นเราจึงทำที่นี่ ในกรณีที่บัฟเฟอร์ I/O ยังไม่ได้เขียนอะไรเลย และ
มีข้อผิดพลาด ENOSPC หรือบางอย่าง
อธิบาย_fflush_or_die(stdout);
ส่งคืน EXIT_SUCCESS;
}
นั่นคือทั้งหมดที่ การรายงานข้อผิดพลาดแบบเต็ม รหัสที่ชัดเจน

Rusty's ขนาด of อินเตอร์เฟซ ความดีงาม
สำหรับคนที่ไม่คุ้นเคย Rusty Russel เรื่อง “How Do I Make This Hard to Misuse?” ของ Rusty Russel
หน้าเป็นสิ่งที่ต้องอ่านสำหรับผู้ออกแบบ API
http://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html

10. มัน เป็นไปไม่ได้ ไปยัง ได้รับ ไม่ถูกต้อง.

ต้องตั้งเป้าหมายให้สูง ทะเยอทะยาน เกรงว่าคุณจะทำสำเร็จและคิดว่าตัวเองเป็น
เสร็จเมื่อคุณไม่ได้

ไลบรารี libexplain ตรวจจับพอยน์เตอร์ปลอมและพารามิเตอร์การเรียกระบบปลอมอื่น ๆ อีกมากมาย
และพยายามหลีกเลี่ยงความผิดแม้ในสถานการณ์ที่ยากลำบากที่สุด

ไลบรารี libexplain ได้รับการออกแบบมาให้ปลอดภัยสำหรับเธรด การใช้งานจริงมีแนวโน้มมากขึ้น
เปิดเผยสถานที่ที่สามารถปรับปรุงได้

ปัญหาที่ใหญ่ที่สุดคือชื่อฟังก์ชันจริงเอง เพราะซีไม่มี
name-spaces ไลบรารี libexplain ใช้คำนำหน้าชื่อ description_ เสมอ นี้เป็น
วิธีดั้งเดิมในการสร้างชื่อสเปซปลอมเพื่อหลีกเลี่ยงความขัดแย้งของสัญลักษณ์
อย่างไรก็ตาม มันส่งผลให้มีชื่อที่ฟังดูไม่เป็นธรรมชาติ

9. พื้นที่ ผู้รวบรวม or ลิงค์ เคยชิน ให้ เธอ ได้รับ it ไม่ถูกต้อง.

ข้อผิดพลาดทั่วไปคือการใช้คำอธิบาย_open โดยที่คำอธิบาย_open_or_die ตั้งใจไว้
โชคดีที่คอมไพเลอร์มักจะออกข้อผิดพลาดประเภท ณ จุดนี้ (เช่น มอบหมายไม่ได้
const char * rvalue เป็น int lvalue)

8. พื้นที่ ผู้รวบรวม จะ เตือน if เธอ ได้รับ it ไม่ถูกต้อง.

หากใช้คำอธิบาย_rename เมื่อมีเจตนาที่จะอธิบาย_rename_or_die อาจทำให้ผู้อื่นได้
ปัญหา. GCC มีแอททริบิวต์ฟังก์ชัน warn_unused_result ที่มีประโยชน์ และlibexplain
ห้องสมุดแนบมากับคำอธิบายทั้งหมด_ชื่อ เรียกฟังก์ชันเพื่อสร้างคำเตือนเมื่อคุณ
ทำผิดพลาดนี้ รวมสิ่งนี้ด้วย gcc - ผิดพลาด เพื่อส่งเสริมสิ่งนี้ไปสู่ความดีระดับ 9

7. พื้นที่ ชัดเจน ใช้ is (อาจจะ) แก้ไข หนึ่ง.

ชื่อฟังก์ชันได้รับเลือกให้สื่อความหมาย แต่ก็ไม่เสมอไป
ประสบความสำเร็จ. ในขณะที่อธิบาย_ชื่อ_or_die และอธิบาย_ชื่อ_on_error อธิบายได้ค่อนข้างดี
ตัวแปรความปลอดภัยของเธรดที่ใช้น้อยกว่านั้นยากต่อการถอดรหัส ต้นแบบฟังก์ชันช่วย
คอมไพเลอร์สู่ความเข้าใจ และความคิดเห็นของ Doxygen ในไฟล์ส่วนหัวช่วยผู้ใช้
ไปสู่ความเข้าใจ

6. พื้นที่ ชื่อ บอก เธอ อย่างไร ไปยัง ใช้ มัน

เป็นสิ่งสำคัญอย่างยิ่งที่จะต้องอ่าน อธิบาย_ชื่อ_or_die เป็น “อธิบาย (ชื่อ หรือตาย)”
การใช้คำนำหน้าชื่อ-ช่องว่างของคำอธิบายที่สอดคล้องกันมีผลข้างเคียงที่โชคร้ายใน
แผนกความชัดเจนเช่นกัน

ลำดับของคำในชื่อยังระบุลำดับของการโต้แย้งด้วย อาร์กิวเมนต์
รายการเสมอ ปลาย ด้วยอาร์กิวเมนต์เดียวกันกับที่ส่งผ่านไปยังการเรียกของระบบ ทั้งหมด of พวกเขา. ถ้า
_errno_ ปรากฏในชื่อ อาร์กิวเมนต์จะอยู่ก่อนอาร์กิวเมนต์การเรียกของระบบเสมอ ถ้า
_message_ ปรากฏในชื่อ อาร์กิวเมนต์สองข้อมาก่อนเสมอ

5. Do it ขวา or it จะ ทำลาย at รันไทม์

ไลบรารี libexplain ตรวจจับพอยน์เตอร์ปลอมและพารามิเตอร์การเรียกระบบปลอมอื่น ๆ อีกมากมาย
และพยายามหลีกเลี่ยงความผิดแม้ในสถานการณ์ที่ยากลำบากที่สุด มันควรจะ
ไม่เคยหยุดทำงาน แต่การใช้งานจริงมากขึ้นจะช่วยปรับปรุงสิ่งนี้อย่างไม่ต้องสงสัย

ข้อความแสดงข้อผิดพลาดบางข้อความมุ่งเป้าไปที่นักพัฒนาและผู้ดูแลมากกว่าผู้ใช้ปลายทางเช่นนี้
สามารถช่วยในการแก้ไขข้อบกพร่อง ไม่มาก "หยุดพักที่รันไทม์" เป็น "ให้ข้อมูลที่
รันไทม์” (หลังจากที่ระบบเรียก barfs)

4. ติดตาม ร่วมกัน การประชุม และ คุณจะ ได้รับ it ขวา.

เนื่องจาก C ไม่มีเนมสเปซ ไลบรารี libexplain จึงใช้ชื่ออธิบายเสมอ
คำนำหน้า นี่เป็นวิธีดั้งเดิมในการสร้างนามแฝงเพื่อหลีกเลี่ยง
ความขัดแย้งของสัญลักษณ์

อาร์กิวเมนต์ต่อท้ายของการเรียก libexplain ทั้งหมดนั้นเหมือนกับการเรียกของระบบ พวกเขา
กำลังอธิบาย โดยมีจุดมุ่งหมายเพื่อให้มีข้อตกลงที่สอดคล้องกับ
ระบบเรียกตัวเองว่า

3. อ่าน เอกสาร และ คุณจะ ได้รับ it ขวา.

ไลบรารี libexplain มีเป้าหมายเพื่อให้มีเอกสาร Doxygen ที่สมบูรณ์สำหรับทุกๆ
การเรียก API สาธารณะ (และภายในด้วย)

ข้อความ เนื้อหา


การทำงานกับ libexplain นั้นเหมือนกับการมองไปด้านล่างรถของคุณเมื่อตอนขึ้น
รอกที่ช่าง มีของน่าเกลียดอยู่ใต้นั้น รวมทั้งโคลนและดินเหนียว และ
ผู้ใช้ไม่ค่อยเห็น ข้อความแสดงข้อผิดพลาดที่ดีจะต้องให้ข้อมูล แม้แต่กับผู้ใช้ที่
ก็ยังโชคดีที่ไม่ต้องมองข้างใต้บ่อยๆ แถมยัง
ข้อมูลสำหรับช่างที่กำลังฟังคำอธิบายของผู้ใช้ทางโทรศัพท์ นี่คือ
ไม่มีงานง่าย

ทบทวนตัวอย่างแรกของเรา โค้ดจะชอบสิ่งนี้หากใช้ libexplain:
int fd = อธิบาย_open_or_die("บางอย่าง/สิ่งของ", O_RDONLY, 0);
จะล้มเหลวโดยมีข้อความแสดงข้อผิดพลาดเช่นนี้
open(pathname = "some/file", flags = O_RDONLY) ล้มเหลว, ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
(2, ENOENT) เพราะไม่มีไดเร็กทอรี "บาง" ในไดเร็กทอรีปัจจุบัน
แบ่งออกเป็นสามส่วน
ระบบ-เรียก ล้มเหลว, ระบบผิดพลาด เพราะ
คำอธิบาย

ก่อน เพราะ
เป็นไปได้ที่จะเห็นส่วนของข้อความก่อน "เพราะ" เป็นเทคนิคมากเกินไปถึงไม่ใช่
ผู้ใช้ทางเทคนิคส่วนใหญ่เป็นผลมาจากการพิมพ์ระบบเรียกตัวเองอย่างแม่นยำที่
จุดเริ่มต้นของข้อความแสดงข้อผิดพลาด และดูเหมือนว่า สเตรซ(1) ผลลัพธ์สำหรับโบนัสเกินบรรยาย
จุด
open(pathname = "some/file", flags = O_RDONLY) ล้มเหลว, ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
(2, อีโนเอนท์)
ข้อความแสดงข้อผิดพลาดส่วนนี้มีความสำคัญต่อนักพัฒนาซอฟต์แวร์เมื่อเขากำลังเขียนโค้ด
และมีความสำคัญเท่าเทียมกันสำหรับผู้ดูแลที่ต้องอ่านรายงานจุดบกพร่องและแก้ไขจุดบกพร่องใน
รหัส. มันบอกว่าสิ่งที่ล้มเหลว

หากข้อความนี้ไม่แสดงต่อผู้ใช้ ผู้ใช้จะไม่สามารถคัดลอกและวางลงใน
รายงานบั๊ก และถ้าไม่อยู่ในรายงานบั๊ก ผู้ดูแลจะไม่รู้ว่าเกิดอะไรขึ้นจริง ๆ
ไม่ถูกต้อง.

บ่อยครั้งที่เจ้าหน้าที่ด้านเทคนิคจะใช้ สเตรซ(1) หรือ มัด(1) เพื่อให้ได้ข้อมูลที่แน่นอนนี้ แต่
ถนนสายนี้ไม่เปิดเมื่ออ่านรายงานข้อผิดพลาด ระบบรายงานข้อผิดพลาดอยู่ไกล
ออกไปและตอนนี้อยู่ในสภาพที่ต่างไปจากเดิมอย่างสิ้นเชิง ดังนั้นข้อมูลนี้จะต้องอยู่ใน
รายงานข้อผิดพลาด ซึ่งหมายความว่าจะต้องอยู่ในข้อความแสดงข้อผิดพลาด

การแสดงการเรียกของระบบยังให้บริบทกับข้อความที่เหลืออีกด้วย ถ้าจำเป็น
เกิดขึ้น อาร์กิวเมนต์การเรียกระบบที่กระทำผิดอาจถูกเรียกตามชื่อในการอธิบาย
หลัง “เพราะ” นอกจากนี้ สตริงทั้งหมดถูกยกมาโดยสมบูรณ์และยกเว้นสตริง C ดังนั้น
การขึ้นบรรทัดใหม่แบบฝังและอักขระที่ไม่พิมพ์จะไม่ทำให้เทอร์มินัลของผู้ใช้ทำงาน
ยุ่งเหยิง

พื้นที่ ระบบผิดพลาด คือสิ่งที่ออกมาจาก ตกใจ(2) บวกกับสัญลักษณ์แสดงข้อผิดพลาด ใจร้อนและ
ผู้ดูแลระบบผู้เชี่ยวชาญอาจหยุดอ่าน ณ จุดนี้ แต่ประสบการณ์ของผู้เขียนจนถึงปัจจุบันคือ
ว่าการอ่านต่อไปเป็นรางวัล (ถ้าไม่คุ้มก็อาจจะเป็นพื้นที่ของ
libexplain ที่สามารถปรับปรุงได้ การมีส่วนร่วมรหัสยินดีต้อนรับแน่นอน)

หลังจาก เพราะ
นี่คือส่วนหนึ่งของข้อความแสดงข้อผิดพลาดที่มุ่งเป้าไปที่ผู้ใช้ที่ไม่ใช่ด้านเทคนิค มันดูเกินไ
อาร์กิวเมนต์การเรียกระบบอย่างง่าย และค้นหาบางสิ่งที่เฉพาะเจาะจงมากขึ้น
ไม่มีไดเร็กทอรี "บาง" ในไดเร็กทอรีปัจจุบัน
ส่วนนี้พยายามอธิบายสาเหตุที่แท้จริงของข้อผิดพลาดในภาษาธรรมดาและมัน
อยู่ที่นี่ที่ความเป็นสากลเป็นสิ่งสำคัญ

โดยทั่วไป นโยบายจะรวมข้อมูลให้มากที่สุด เพื่อให้ผู้ใช้
ไม่ต้องไปหามัน (และไม่ทิ้งมันไว้ในรายงานข้อผิดพลาด)

สากล
ข้อความแสดงข้อผิดพลาดส่วนใหญ่ในไลบรารี libexplain เป็นสากล ที่นั่น
ยังไม่มีการแปลเป็นภาษาท้องถิ่น ดังนั้นหากคุณต้องการคำอธิบายในภาษาของคุณ
กรุณามีส่วนร่วม

ตัวระบุ "ส่วนใหญ่" ข้างต้น เกี่ยวข้องกับข้อเท็จจริงที่ว่าการพิสูจน์แนวคิด
การดำเนินการไม่รวมถึงการสนับสนุนความเป็นสากล ฐานรหัสกำลัง
แก้ไขไปเรื่อย ๆ มักจะเป็นผลมาจากการ refactoring ข้อความเพื่อให้แต่ละข้อผิดพลาด
สตริงข้อความปรากฏในรหัสเพียงครั้งเดียว

มีการจัดเตรียมสำหรับภาษาที่จำเป็นต้องประกอบส่วนต่างๆ ของ
ระบบ-เรียก ล้มเหลว, ระบบผิดพลาด เพราะ คำอธิบาย
ในลำดับที่แตกต่างกันสำหรับไวยากรณ์ที่ถูกต้องในข้อความแสดงข้อผิดพลาดที่แปลแล้ว

ชันสูตรพลิกศพ
มีบางครั้งที่โปรแกรมยังไม่ได้ใช้ libexplain และคุณยังใช้ไม่ได้ สเตรซ(1)
ทั้ง. มี อธิบาย(1) คำสั่งที่มาพร้อมกับ libexplain ที่สามารถใช้เพื่อ
ถอดรหัสข้อความแสดงข้อผิดพลาด หากสถานะของระบบพื้นฐานไม่เปลี่ยนแปลงมากเกินไป
$ อธิบาย ตั้งชื่อใหม่ foo /tmp/bar/บาซ -e อีน็อนต์
เปลี่ยนชื่อ (oldpath = "foo", newpath = "/tmp/bar/baz") ล้มเหลว ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
(2, ENOENT) เนื่องจากไม่มีไดเร็กทอรี "bar" ใน newpath "/ Tmp" ไดเรกทอรี
$
โปรดสังเกตว่าความกำกวมของพาธได้รับการแก้ไขโดยใช้ชื่ออาร์กิวเมนต์การเรียกของระบบได้อย่างไร ของ
แน่นอนคุณต้องรู้ข้อผิดพลาดและระบบเรียกหา อธิบาย(1) ให้เป็นประโยชน์ เป็นอัน
นี่เป็นวิธีหนึ่งที่ใช้โดยชุดทดสอบอัตโนมัติของ libexplain เพื่อตรวจสอบว่า
libexplain กำลังทำงาน

ปรัชญา
“บอกฉันทุกอย่าง รวมถึงสิ่งที่ฉันไม่รู้ว่าต้องค้นหา”

ไลบรารีถูกนำไปใช้ในลักษณะที่เมื่อเชื่อมโยงแบบสแตติก มีเพียงรหัสที่คุณ
การใช้งานจริงจะถูกเชื่อมโยง สิ่งนี้ทำได้โดยมีหนึ่งฟังก์ชันต่อไฟล์ต้นทาง
เมื่อใดก็ตามที่เป็นไปได้

เมื่อสามารถให้ข้อมูลเพิ่มเติมได้ libexplain จะทำเช่นนั้น ผู้ใช้น้อยลง
ต้องติดตามกันเองยิ่งดี ซึ่งหมายความว่า UID จะมาพร้อมกับ
ชื่อผู้ใช้ GID จะมาพร้อมกับชื่อกลุ่ม PID จะมาพร้อมกับกระบวนการ
ชื่อไฟล์และสตรีมมาพร้อมกับชื่อพา ธ ฯลฯ.

เมื่อแก้ไขพาธ หากไม่มีองค์ประกอบพาธ libexplain จะค้นหาที่คล้ายกัน
ชื่อ เพื่อที่จะแนะนำทางเลือกอื่นสำหรับข้อผิดพลาดในการพิมพ์

ไลบรารี libexplain พยายามใช้ฮีปให้น้อยที่สุดเท่าที่จะทำได้ และมักจะไม่มีเลย นี่คือ
เพื่อไม่ให้รบกวนกระบวนการให้มากที่สุดเท่าที่จะมากได้ แม้ว่าบางครั้งจะเป็น
หลีกเลี่ยงไม่ได้

ไลบรารี libexplain พยายามทำให้เธรดปลอดภัย โดยการหลีกเลี่ยงตัวแปรโกลบอล การรักษา
ระบุบนสแต็กให้มากที่สุด มีบัฟเฟอร์ข้อความทั่วไปเพียงตัวเดียวและ
ฟังก์ชันที่ใช้ได้รับการบันทึกไว้ว่าไม่ปลอดภัยสำหรับเธรด

ไลบรารี libexplain ไม่รบกวนตัวจัดการสัญญาณของกระบวนการ สิ่งนี้ทำให้
กำหนดว่าพอยน์เตอร์จะแยกแยะความท้าทายหรือไม่ แต่ก็ใช่ว่าจะเป็นไปไม่ได้

เมื่อมีข้อมูลผ่านระบบเรียกและพร้อมใช้งานผ่าน a / proc
รายการที่ต้องการเรียกระบบ ทั้งนี้เพื่อหลีกเลี่ยงการรบกวนสถานะของกระบวนการ
นอกจากนี้ยังมีบางครั้งที่ไม่มีตัวอธิบายไฟล์

ไลบรารี libexplain ถูกคอมไพล์ด้วยการสนับสนุนไฟล์ขนาดใหญ่ ไม่มีขนาดใหญ่/เล็ก
โรคจิตเภท. ที่สิ่งนี้ส่งผลกระทบต่อประเภทอาร์กิวเมนต์ใน API และจะออกข้อผิดพลาด
หากไม่มีการกำหนดไฟล์ขนาดใหญ่ที่จำเป็น

FIXME: จำเป็นต้องทำงานเพื่อให้แน่ใจว่าโควต้าระบบไฟล์ได้รับการจัดการในโค้ด นี้
นำไปใช้กับบาง รับลิมิต(2) ขอบเขตเช่นกัน

มีหลายกรณีที่เส้นทางของญาติไม่มีข้อมูล ตัวอย่างเช่น: ระบบภูต,
เซิร์ฟเวอร์และกระบวนการเบื้องหลัง ในกรณีเหล่านี้ เส้นทางสัมบูรณ์ถูกใช้ในข้อผิดพลาด
คำอธิบาย

เส้นทาง การแก้ไข


เวอร์ชันสั้น: ดู เส้นทาง_ความละเอียด(7)

เวอร์ชันยาว: ผู้ใช้ส่วนใหญ่ไม่เคยได้ยินเกี่ยวกับ เส้นทาง_ความละเอียด(7) และผู้ใช้ขั้นสูงจำนวนมาก
ไม่เคยอ่านเลย นี่คือเวอร์ชันที่มีคำอธิบายประกอบ:

ขั้นตอน 1: เริ่มต้น of ความละเอียด กระบวนการ
หากชื่อพาธขึ้นต้นด้วยเครื่องหมายทับ (“/”) ไดเร็กทอรีการค้นหาเริ่มต้นคือ
ไดเร็กทอรีรากของกระบวนการเรียก

หากชื่อพาธไม่ขึ้นต้นด้วยเครื่องหมายทับ (“/”) การค้นหาเริ่มต้น
ไดเร็กทอรีของกระบวนการแก้ไขคือไดเร็กทอรีการทำงานปัจจุบันของกระบวนการ

ขั้นตอน 2: เดิน ตาม เส้นทาง
ตั้งค่าไดเร็กทอรีการค้นหาปัจจุบันเป็นไดเร็กทอรีการค้นหาเริ่มต้น ตอนนี้สำหรับแต่ละคนที่ไม่ใช่-
องค์ประกอบสุดท้ายของชื่อพาธ โดยที่ส่วนประกอบเป็นสตริงย่อยที่คั่นด้วยเครื่องหมายทับ (“/”)
อักขระ คอมโพเนนต์นี้จะถูกค้นหาในไดเร็กทอรีการค้นหาปัจจุบัน

หากกระบวนการไม่มีสิทธิ์ในการค้นหาในไดเร็กทอรีการค้นหาปัจจุบัน EACCES
ข้อผิดพลาดถูกส่งกลับ ("การอนุญาตถูกปฏิเสธ")
open(pathname = "/home/archives/.ssh/private_key", flags = O_RDONLY) ล้มเหลว
การอนุญาตถูกปฏิเสธ (13, EACCES) เนื่องจากกระบวนการไม่มีสิทธิ์ในการค้นหา
ไปยังไดเร็กทอรีชื่อพาธ "/home/archives/.ssh" กระบวนการที่มีประสิทธิภาพ GID 1000
"pmiller" ไม่ตรงกับเจ้าของไดเรกทอรี 1001 "เก็บถาวร" ดังนั้นเจ้าของ
โหมดการอนุญาต "rwx" ถูกละเว้น โหมดการอนุญาตอื่น ๆ คือ "---" และ
กระบวนการไม่ได้รับสิทธิพิเศษ (ไม่มีความสามารถ DAC_READ_SEARCH)

หากไม่พบส่วนประกอบ ข้อผิดพลาด ENOENT จะถูกส่งคืน ("ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว")
unlink(pathname = "/home/microsoft/rubbish") ล้มเหลว ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว (2,
ENOENT) เนื่องจากไม่มีไดเร็กทอรี "microsoft" ในชื่อพาธ "/ หน้าแรก" ไดเรกทอรี

นอกจากนี้ยังมีการสนับสนุนสำหรับผู้ใช้เมื่อพวกเขาพิมพ์ชื่อพาธผิด ให้คำแนะนำเมื่อ
ส่งคืน ENOENT:
open(pathname = "/user/include/fcntl.h", flags = O_RDONLY) ล้มเหลว, ไม่มีไฟล์ดังกล่าวหรือ
ไดเร็กทอรี (2, ENOENT) เนื่องจากไม่มีไดเร็กทอรี "ผู้ใช้" ในชื่อพาธ "/"
ไดเร็กทอรีคุณหมายถึงไดเร็กทอรี "usr" แทนหรือไม่

หากพบส่วนประกอบ แต่ไม่ใช่ไดเร็กทอรีหรือลิงก์สัญลักษณ์ แสดงว่า ENOTDIR
ส่งคืนข้อผิดพลาด ("ไม่ใช่ไดเรกทอรี")
open(pathname = "/home/pmiller/.netrc/lca", flags = O_RDONLY) ล้มเหลว ไม่ใช่
ไดเร็กทอรี (20, ENOTDIR) เนื่องจากไฟล์ปกติ ".netrc" ในชื่อพาธ
ไดเร็กทอรี "/home/pmiller" ถูกใช้เป็นไดเร็กทอรีเมื่อไม่ใช่ไดเร็กทอรี

หากพบส่วนประกอบและเป็นไดเร็กทอรี เราจะตั้งค่าไดเร็กทอรีการค้นหาปัจจุบันเป็น that
ไดเร็กทอรีและไปที่องค์ประกอบถัดไป

หากพบองค์ประกอบและเป็นลิงค์สัญลักษณ์ (symlink) เราจะแก้ไขสัญลักษณ์นี้ก่อน
ลิงก์ (โดยมีไดเร็กทอรีการค้นหาปัจจุบันเป็นไดเร็กทอรีการค้นหาเริ่มต้น) เมื่อผิดพลาดว่า
ข้อผิดพลาดถูกส่งกลับ ถ้าผลลัพธ์ไม่ใช่ไดเร็กทอรี ข้อผิดพลาด ENOTDIR จะถูกส่งคืน
unlink(pathname = "/tmp/dangling/rubbish") ล้มเหลว ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว (2,
ENOENT) เนื่องจากลิงก์สัญลักษณ์ "ห้อยต่องแต่ง" ในชื่อพาธ "/ Tmp" ไดเรกทอรี
หมายถึง "ไม่มีที่ไหนเลย" ที่ไม่มีอยู่จริง
หากความละเอียดของ symlink สำเร็จและส่งคืนไดเร็กทอรี เราจะตั้งค่าcurrent
ค้นหาไดเร็กทอรีไปยังไดเร็กทอรีนั้น และไปที่คอมโพเนนต์ถัดไป โปรดทราบว่า
กระบวนการแก้ไขที่นี่เกี่ยวข้องกับการเรียกซ้ำ เพื่อป้องกันเคอร์เนลจาก stack
ล้นและเพื่อป้องกันการปฏิเสธการบริการมีขีดจำกัดสูงสุด
ความลึกของการเรียกซ้ำ และตามจำนวนลิงก์สัญลักษณ์สูงสุด ข้อผิดพลาด ELOOP คือ
ส่งคืนเมื่อเกินค่าสูงสุด ("ลิงก์สัญลักษณ์มีระดับมากเกินไป")
open(pathname = "/tmp/dangling", flags = O_RDONLY) ล้มเหลว มีระดับมากเกินไป
ลิงก์สัญลักษณ์ (40, ELOOP) เนื่องจากพบลูปลิงก์สัญลักษณ์ใน
ชื่อพาธ เริ่มต้นที่ "/tmp/dangling"
นอกจากนี้ยังสามารถรับข้อผิดพลาด ELOOP หรือ EMLINK ได้หากมีลิงก์เชื่อมโยงมากเกินไป แต่ไม่มี
ตรวจพบลูป
open(pathname = "/tmp/rabbit-hole", flags = O_RDONLY) ล้มเหลว มีระดับมากเกินไป
ลิงก์สัญลักษณ์ (40, ELOOP) เนื่องจากพบลิงก์สัญลักษณ์มากเกินไปใน
ชื่อพาธ (8)
สังเกตว่ามีการพิมพ์ขีด จำกัด จริงอย่างไร

ขั้นตอน 3: หา สุดท้าย การเข้า
การค้นหาองค์ประกอบสุดท้ายของชื่อพาธจะเหมือนกับของส่วนประกอบอื่นๆ ทั้งหมด
องค์ประกอบตามที่อธิบายไว้ในขั้นตอนที่แล้ว โดยมีความแตกต่างสองประการ:

(i) องค์ประกอบสุดท้ายไม่จำเป็นต้องเป็นไดเร็กทอรี (อย่างน้อยก็เท่ากับความละเอียดของเส้นทาง
กระบวนการที่เกี่ยวข้อง อาจต้องเป็นไดเร็กทอรี หรือไม่ใช่ไดเร็กทอรี เนื่องจาก
ความต้องการของระบบเฉพาะ)

(ii)
ไม่จำเป็นต้องเป็นข้อผิดพลาดหากไม่พบองค์ประกอบสุดท้าย บางทีเราก็แค่
การสร้างมัน รายละเอียดเกี่ยวกับการรักษารายการสุดท้ายได้อธิบายไว้ใน
หน้าคู่มือของการเรียกระบบเฉพาะ

(iii)
นอกจากนี้ยังอาจเกิดปัญหากับองค์ประกอบสุดท้ายหากเป็นลิงก์สัญลักษณ์
และไม่ควรปฏิบัติตาม ตัวอย่างเช่น การใช้ เปิด(2) แฟล็ก O_NOFOLLOW:
open(pathname = "a-symlink", flags = O_RDONLY | O_NOFOLLOW) ล้มเหลว มีระดับมากเกินไป
ลิงก์สัญลักษณ์ (ELOOP) เนื่องจากมีการระบุ O_NOFOLLOW แต่ชื่อพาธอ้างถึง a
การเชื่อมโยงสัญลักษณ์

(iv)
เป็นเรื่องปกติที่ผู้ใช้จะทำผิดพลาดเมื่อพิมพ์ชื่อพาธ ห้องสมุด libexplain
พยายามให้คำแนะนำเมื่อมีการส่งคืน ENOENT ตัวอย่างเช่น:
open(pathname = "/usr/include/filecontrl.h", flags = O_RDONLY) ล้มเหลว, ไม่มีไฟล์ดังกล่าวหรือ
ไดเร็กทอรี (2, ENOENT) เนื่องจากไม่มีไฟล์ "filecontrl.h" ปกติในชื่อพาธ
"/ usr / รวม" ไดเรกทอรี คุณหมายถึงไฟล์ปกติ "fcntl.h" แทนใช่หรือไม่

(v) นอกจากนี้ยังเป็นไปได้ที่องค์ประกอบสุดท้ายจะต้องเป็นอย่างอื่นที่ไม่ใช่
ไฟล์ปกติ:
readlink (ชื่อพาธ = "just-a-file", data = 0x7F930A50, data_size = 4097) ล้มเหลว,
อาร์กิวเมนต์ไม่ถูกต้อง (22, EINVAL) เนื่องจากชื่อพาธเป็นไฟล์ปกติ ไม่ใช่ลิงก์สัญลักษณ์

(vi)
FIXME: การจัดการบิต "t"

ข้อ จำกัด
มีข้อจำกัดหลายประการเกี่ยวกับชื่อพาธและชื่อไฟล์

จำกัดความยาวของชื่อเส้นทาง
ชื่อพาธมีความยาวสูงสุด ถ้าชื่อพาธ (หรือตัวกลางบางตัว
ชื่อพาธที่ได้รับขณะแก้ไขลิงก์สัญลักษณ์) ยาวเกินไป ENAMETOOLONG
ข้อผิดพลาดถูกส่งกลับ ("ชื่อไฟล์ยาวเกินไป") สังเกตว่ามีการจำกัดระบบอย่างไร
ในข้อความแสดงข้อผิดพลาด
เปิด (ชื่อพาธ = "นานมาก", ค่าสถานะ = O_RDONLY) ล้มเหลว ชื่อไฟล์ยาวเกินไป (36,
ENAMETOOLONG) เนื่องจากชื่อพาธเกินความยาวพาธสูงสุดของระบบ (4096)

ขีดจำกัดความยาวของชื่อไฟล์
Unix บางรุ่นมีการจำกัดจำนวนไบต์ในแต่ละองค์ประกอบพาธ
บางคนจัดการกับสิ่งนี้อย่างเงียบ ๆ และบางคนให้ ENAMETOOLONG; libexplain
การใช้ห้องสมุด เส้นทาง conf(3) _PC_NO_TRUNC ที่จะบอก หากข้อผิดพลาดนี้เกิดขึ้น
ไลบรารี libexplain จะระบุขีดจำกัดในข้อความแสดงข้อผิดพลาด ขีดจำกัดคือ
ได้รับจาก เส้นทาง conf(3) _PC_NAME_MAX. สังเกตว่ามีการจำกัดระบบอย่างไร
ในข้อความแสดงข้อผิดพลาด
เปิด (ชื่อพาธ = "system7/only-had-14-ตัวอักษร", ค่าสถานะ = O_RDONLY) ล้มเหลว, ไฟล์
ชื่อยาวเกินไป (36, ENAMETOOLONG) เนื่องจากองค์ประกอบ "มีอักขระเพียง 14 ตัวเท่านั้น" คือ
เกินขีดจำกัดของระบบ (14)

ชื่อพาธว่าง
ใน Unix ดั้งเดิม ชื่อพาธว่างจะอ้างอิงถึงไดเร็กทอรีปัจจุบัน
ทุกวันนี้ POSIX ออกคำสั่งว่าต้องไม่แก้ไขชื่อพาธที่ว่างเปล่าให้สำเร็จ
open(pathname = "", flags = O_RDONLY) ล้มเหลว, ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว (2,
ENOENT) เนื่องจาก POSIX กำหนดให้ต้องไม่แก้ไขชื่อพาธว่าง
ประสบความสำเร็จ

สิทธิ์
บิตการอนุญาตของไฟล์ประกอบด้วยสามกลุ่มสามบิต กลุ่มแรกของ
สามถูกใช้เมื่อ ID ผู้ใช้ที่มีประสิทธิภาพของกระบวนการโทรเท่ากับ ID เจ้าของของ
ไฟล์. กลุ่มที่สองของสามถูกใช้เมื่อ ID กลุ่มของไฟล์เท่ากับ
ID กลุ่มที่มีประสิทธิภาพของกระบวนการโทรหรือเป็นหนึ่งใน ID กลุ่มเสริมของ
กระบวนการโทร เมื่อไม่มีการระงับ กลุ่มที่สามจะถูกใช้
เปิด (ชื่อพาธ = "/ etc / passwd", ค่าสถานะ = O_WRONLY) ล้มเหลว, ปฏิเสธการอนุญาต (13,
EACCES) เนื่องจากกระบวนการไม่มีสิทธิ์ในการเขียน "passwd" ปกติ
ไฟล์ในชื่อพาธ "/ ฯลฯไดเร็กทอรี กระบวนการที่มีประสิทธิภาพ UID 1000 "pmiller"
ไม่ตรงกับเจ้าของไฟล์ปกติ 0 "root" ดังนั้นโหมดการอนุญาตของเจ้าของ "rw-"
ถูกละเว้น โหมดการอนุญาตอื่น ๆ คือ "r--" และกระบวนการนี้ไม่ได้รับสิทธิพิเศษ
(ไม่มีความสามารถ DAC_OVERRIDE)
คำอธิบายนี้มีพื้นที่พอสมควรเนื่องจากผู้ใช้ส่วนใหญ่ไม่ทราบว่าสิ่งนี้
เป็นวิธีการทำงานของระบบการอนุญาต โดยเฉพาะอย่างยิ่ง: เจ้าของกลุ่มและอื่น ๆ
สิทธิ์เป็นเอกสิทธิ์ ไม่ได้ "หรือ" ร่วมกัน

แปลก AND ที่น่าสนใจ ระบบ โทร


กระบวนการเขียนตัวจัดการข้อผิดพลาดเฉพาะสำหรับการเรียกระบบแต่ละครั้งมักจะเปิดเผย
นิสัยใจคอและเงื่อนไขขอบเขตที่น่าสนใจหรือคลุมเครือ Errno(3) ค่านิยม

เอโนเมเดียม, ไม่ กลาง พบ
การทำสำเนาซีดีเป็นที่มาของชื่อบทความ
$ dd ถ้า=/dev/cdrom ของ=fubar.iso
dd: เปิด “/dev/cdrom”: ไม่พบสื่อ
$
ผู้เขียนสงสัยว่าทำไมคอมพิวเตอร์ของเขาถึงบอกเขาว่าไม่มีสิ่งที่เรียกว่าจิต
ปานกลาง. ค่อนข้างมากนอกเหนือจากข้อเท็จจริงที่ว่าเจ้าของภาษาอังกฤษจำนวนมากไม่ได้
แม้รู้ว่า “สื่อ” เป็นพหูพจน์นับประสาว่า “กลาง” เป็นเอกพจน์ สตริง
ส่งคืนโดย ตกใจ(3) สำหรับ ENOMEDIUM นั้นสั้นมากจนเกือบจะปราศจาก
เนื้อหา

เมื่อ เปิด(2) ส่งคืน ENOMEDIUM คงจะดีถ้าไลบรารี libexplain สามารถขยายa
เล็กน้อยเกี่ยวกับสิ่งนี้ขึ้นอยู่กับประเภทของไดรฟ์ที่เป็น ตัวอย่างเช่น:
... เพราะไม่มีดิสก์ในฟลอปปีไดรฟ์
... เพราะไม่มีแผ่นดิสก์ในไดรฟ์ซีดีรอม
...เพราะไม่มีเทปในเทปไดรฟ์
...เพราะว่าเครื่องอ่านการ์ดไม่มีเมมโมรี่สติ๊ก

และแล้วมันก็เกิดขึ้น...
open(pathname = "/dev/cdrom", flags = O_RDONLY) ล้มเหลว ไม่พบสื่อ (123,
ENOMEDIUM) เนื่องจากไม่มีแผ่นดิสก์อยู่ในไดรฟ์ซีดีรอม
เคล็ดลับที่ผู้เขียนไม่เคยรู้มาก่อนคือการเปิดอุปกรณ์โดยใช้
แฟล็ก O_NONBLOCK ซึ่งจะช่วยให้คุณเปิดไดรฟ์ที่ไม่มีสื่ออยู่ในนั้น แล้วคุณ
ปัญหาเฉพาะอุปกรณ์ ไอโอทีแอล(2) ร้องขอจนกว่าคุณจะรู้ว่ามันคืออะไร (ไม่
แน่ใจว่านี่คือ POSIX หรือไม่ แต่ดูเหมือนว่าจะใช้งานได้ใน BSD และ Solaris ตาม
โวดิม(1) แหล่งที่มา)

โปรดสังเกตการใช้ "ดิสก์" และ "ดิสก์" ที่แตกต่างกันในบริบท มาตรฐานซีดีเกิดขึ้น
ในฝรั่งเศส แต่อย่างอื่นมี "k"

ความผิดพลาด ไม่ดี ที่อยู่
การเรียกของระบบที่ใช้อาร์กิวเมนต์ตัวชี้สามารถส่งคืน EFAULT ห้องสมุด libexplain
สามารถระบุได้ว่าข้อโต้แย้งใดเป็นความผิด และทำโดยไม่รบกวนกระบวนการ
(หรือเธรด) การจัดการสัญญาณ

เมื่อสามารถใช้ได้ มินิคอร์(2) ใช้การเรียกของระบบเพื่อถามว่าภูมิภาคหน่วยความจำถูกต้องหรือไม่
มันสามารถส่งคืนผลลัพธ์สามรายการ: แมปแต่ไม่อยู่ในหน่วยความจำกายภาพ, แมปและทางกายภาพ
หน่วยความจำและไม่ได้แมป เมื่อทดสอบความถูกต้องของพอยน์เตอร์ สองตัวแรกคือ "ใช่"
และสุดท้ายคือ "ไม่"

การตรวจสอบสตริง C นั้นยากกว่าเพราะแทนที่จะเป็นพอยน์เตอร์และขนาด เราเท่านั้น
มีตัวชี้ ในการกำหนดขนาดเราจะต้องหา NUL และสามารถ
segfault, จับ-22.

เพื่อแก้ไขปัญหานี้ ไลบรารี libexplain ใช้ the ลสแตท(2) sysem call (กับที่รู้จัก
อาร์กิวเมนต์ที่สองที่ดี) เพื่อทดสอบสตริง C เพื่อความถูกต้อง ความล้มเหลวส่งคืน && errno == EFAULT
คือ "ไม่" และสิ่งอื่นใดก็คือ "ใช่" แน่นอนว่าสิ่งนี้จำกัดสตริงไว้ที่ PATH_MAX
อักขระ แต่นั่นก็ไม่ใช่ปัญหาสำหรับไลบรารี libexplain เพราะนั่นคือ
เกือบจะเป็นสายที่ยาวที่สุดที่มันสนใจ

เอ็มฟิเล่ เกินไป หลาย เปิด ไฟล์
ข้อผิดพลาดนี้เกิดขึ้นเมื่อกระบวนการเปิดตัวอธิบายไฟล์ถึงจำนวนสูงสุดแล้ว
หากต้องพิมพ์ขีดจำกัดจริง และไลบรารี libexplain พยายาม คุณจะไม่สามารถเปิดได้
ไฟล์ใน / proc เพื่ออ่านว่ามันคืออะไร
open_max = sysconf (_SC_OPEN_MAX);
อันนี้ไม่ยากมี ซิสคอนฟ(๓) วิธีการได้มาซึ่งขอบเขต

เอนไฟล์ เกินไป หลาย เปิด ไฟล์ in ระบบ
ข้อผิดพลาดนี้เกิดขึ้นเมื่อระบบจำกัดจำนวนไฟล์ที่เปิดอยู่ทั้งหมด
ถึง. ในกรณีนี้มันไม่มีประโยชน์ ซิสคอนฟ(3) วิธีการได้รับวงเงิน

ขุดลึกลงไปอาจพบว่าบน Linux มี / proc รายการที่เราสามารถอ่านได้
ได้รับค่านี้ Catch-22: เราไม่มี file descriptor ดังนั้นเราจึงไม่สามารถเปิดไฟล์เพื่อ
อ่านขีด จำกัด

บน Linux มีการเรียกของระบบเพื่อรับมัน แต่ไม่มีฟังก์ชัน [e]glibc wrapper ดังนั้น
คุณต้องทำทุกอย่างอย่างระมัดระวัง:
ยาว
อธิบาย_maxfile(เป็นโมฆะ)
{
#ifdef __ลินุกซ์__
โครงสร้าง __sysctl_args หาเรื่อง;
int32_t ไฟล์สูงสุด;
size_t maxfile_size = ขนาดของ(ไฟล์สูงสุด);
ชื่อ int [] = { CTL_FS, FS_MAXFILE };
memset(&args, 0, sizeof(โครงสร้าง __sysctl_args));
args.name = ชื่อ;
args.nlen = 2;
args.oldval = &maxfile;
args.oldlenp = &maxfile_size;
ถ้า (syscall(SYS__sysctl, &args) >= 0)
ส่งคืน maxfile;
#เอนดิฟ
กลับ -1;
}
อนุญาตให้รวมขีดจำกัดในข้อความแสดงข้อผิดพลาด เมื่อมี

ไอน์วาล "ไม่ถูกต้อง การโต้เถียง" vs อีโนซิส "การทำงาน ไม่ ดำเนินการ”
การดำเนินการที่ไม่รองรับ (เช่น ลิงค์สัญลักษณ์(2) บนระบบไฟล์ FAT) จะไม่ถูกรายงาน
อย่างต่อเนื่องจากการเรียกระบบหนึ่งไปยังอีกระบบหนึ่ง เป็นไปได้ที่จะมี EINVAL หรือ
ENOSYS กลับมา

ด้วยเหตุนี้จึงต้องให้ความสนใจกับกรณีข้อผิดพลาดเหล่านี้เพื่อให้ถูกต้อง โดยเฉพาะ
เนื่องจาก EINVAL อาจหมายถึงปัญหาเกี่ยวกับอาร์กิวเมนต์การเรียกระบบตั้งแต่หนึ่งรายการขึ้นไป

หมายเหตุ ที่ Errno(3) is ไม่ เสมอ ชุด
มีบางครั้งที่จำเป็นต้องอ่านแหล่งที่มาของ [e]glibc เพื่อกำหนดวิธีการและ
เมื่อมีการส่งคืนข้อผิดพลาดสำหรับการเรียกระบบบางระบบ

เฟอฟ(3) ไฟล์โน(3)
มักสันนิษฐานว่าฟังก์ชันเหล่านี้ไม่สามารถส่งคืนข้อผิดพลาดได้ นี่เป็นจริงก็ต่อเมื่อ
กระแส อาร์กิวเมนต์ถูกต้อง อย่างไรก็ตาม พวกเขาสามารถตรวจพบว่าไม่ถูกต้อง
ตัวชี้

fpathconf(3) เส้นทาง conf(3)
ค่าส่งคืนของ fpathconf(2) และ เส้นทาง conf(2) ถูกต้องตามกฎหมายอาจเป็น -1 ดังนั้นจึงเป็น
จำเป็นต้องดูว่า Errno(3) ได้กำหนดไว้อย่างชัดเจน

ไอโอทีแอล(2)
ค่าส่งคืนของ ไอโอทีแอล(2) ถูกต้องตามกฎหมายอาจเป็น -1 ดังนั้นจึงจำเป็นต้องดูว่า
Errno(3) ได้กำหนดไว้อย่างชัดเจน

อ่าน(3)
ค่าส่งคืนของ อ่าน(3) เป็น NULL สำหรับทั้งข้อผิดพลาดและการสิ้นสุดไฟล์ มันคือ
จำเป็นต้องดูว่า Errno(3) ได้กำหนดไว้อย่างชัดเจน

เซ็ตบัฟ(3) ชุดบัฟเฟอร์(3) ตั้งค่าไลน์บัฟ(3) setvbuf(3)
ทั้งหมดยกเว้นฟังก์ชันสุดท้ายกลับเป็นโมฆะ และ setvbuf(3) มีเอกสารเป็น .เท่านั้น
ส่งคืนข้อผิดพลาด "ไม่ใช่ศูนย์" ต้องดูว่า Errno(3) ได้รับอย่างชัดเจน
ตั้ง

สตรอ(3) สตรอล(3) หยุด(3) เดินเล่น(3) สตรูล(3) strtoll(3)
ฟังก์ชันเหล่านี้คืนค่า 0 เมื่อเกิดข้อผิดพลาด แต่นั่นเป็นผลตอบแทนที่ถูกต้องด้วย มันคือ
จำเป็นต้องดูว่า Errno(3) ได้กำหนดไว้อย่างชัดเจน

ว่าง(3)
แม้ว่าอักขระสำรองเพียงตัวเดียวจะได้รับคำสั่งจากมาตรฐาน ANSI C แต่กลับกลายเป็น
ว่า [e]glibc อนุญาตมากกว่านี้... แต่นั่นหมายความว่าอาจล้มเหลวด้วย ENOMEM มันสามารถ
ก็ล้มเหลวด้วย EBADF if fp เป็นของปลอม ยากที่สุด หากคุณส่ง EOF ข้อผิดพลาด
การส่งคืนเกิดขึ้น แต่ไม่ได้ตั้งค่า errno

ไลบรารี libexplain ตรวจพบข้อผิดพลาดเหล่านี้ทั้งหมดอย่างถูกต้อง แม้ในกรณีที่
ค่าความผิดพลาดได้รับการบันทึกไว้ไม่ดี แต่อย่างใด

อีนอสพีซี ไม่ ช่องว่าง ซ้าย on เครื่อง
เมื่อข้อผิดพลาดนี้อ้างถึงไฟล์บนระบบไฟล์ ไลบรารี libexplain จะพิมพ์ mount
จุดของระบบไฟล์ที่มีปัญหา ซึ่งจะทำให้ต้นเหตุของข้อผิดพลาดได้มาก
ชัดเจนขึ้น
เขียน (fildes = 1 "ตัวอย่าง", data = 0xbfff2340, data_size = 5) ล้มเหลว, ไม่มีที่ว่างเหลือ
บนอุปกรณ์ (28, ENOSPC) เนื่องจากระบบไฟล์มีไฟล์ ("/ หน้าแรก") ไม่มี
พื้นที่มากขึ้นสำหรับข้อมูล
เมื่อมีการเพิ่มการรองรับอุปกรณ์พิเศษเพิ่มเติม ข้อความแสดงข้อผิดพลาดก็คาดว่าจะรวมอุปกรณ์ด้วย
ชื่อและขนาดที่แท้จริงของอุปกรณ์

อีรอฟส์, อ่านเท่านั้น ไฟล์ ระบบ
เมื่อข้อผิดพลาดนี้อ้างถึงไฟล์บนระบบไฟล์ ไลบรารี libexplain จะพิมพ์ mount
จุดของระบบไฟล์ที่มีปัญหา ซึ่งจะทำให้ต้นเหตุของข้อผิดพลาดได้มาก
ชัดเจนขึ้น

เมื่อมีการเพิ่มการรองรับอุปกรณ์พิเศษเพิ่มเติม ข้อความแสดงข้อผิดพลาดก็คาดว่าจะรวมอุปกรณ์ด้วย
ชื่อและประเภท
open(pathname = "/dev/fd0", O_RDWR, 0666) ล้มเหลว, ระบบไฟล์แบบอ่านอย่างเดียว (30, EROFS)
เนื่องจากฟลอปปีดิสก์มีชุดแท็บป้องกันการเขียน

...เพราะซีดีรอมไม่สามารถเขียนได้
...เนื่องจากการ์ดหน่วยความจำมีชุดแท็บป้องกันการเขียน
...เพราะเทปแม่เหล็ก ½ นิ้ว ไม่มีวงแหวน

ตั้งชื่อใหม่
พื้นที่ ตั้งชื่อใหม่(2) system call ใช้สำหรับเปลี่ยนตำแหน่งหรือชื่อไฟล์ ย้ายไฟล์
ระหว่างไดเร็กทอรีหากจำเป็น หากมีชื่อพาธปลายทางอยู่แล้ว จะเป็น
แทนที่ด้วยอะตอม เพื่อไม่ให้มีกระบวนการอื่นที่พยายามจะ
การเข้าถึงจะพบว่ามันหายไป

อย่างไรก็ตาม มีข้อจำกัด: คุณสามารถเปลี่ยนชื่อไดเร็กทอรีที่อยู่ด้านบนของไดเร็กทอรีอื่นเท่านั้น
ไดเร็กทอรีถ้าไดเร็กทอรีปลายทางไม่ว่างเปล่า
เปลี่ยนชื่อ (oldpath = "foo", newpath = "bar") ล้มเหลว ไดเรกทอรีไม่ว่างเปล่า (39,
ENOTEMPTY) เนื่องจาก newpath ไม่ใช่ไดเร็กทอรีว่าง นั่นคือ มันมีรายการ
นอกเหนือจากนี้ "." และ ".."
คุณไม่สามารถเปลี่ยนชื่อไดเร็กทอรีบนไดเร็กทอรีที่ไม่ใช่ไดเร็กทอรีได้เช่นกัน
เปลี่ยนชื่อ (oldpath = "foo", newpath = "bar") ล้มเหลว ไม่ใช่ไดเรกทอรี (20, ENOTDIR)
เพราะ oldpath เป็นไดเร็กทอรี แต่ newpath เป็นไฟล์ปกติ ไม่ใช่ไดเร็กทอรี
ไม่อนุญาตให้ย้อนกลับ
เปลี่ยนชื่อ (oldpath = "foo", newpath = "bar") ล้มเหลว เป็นไดเรกทอรี (21, EISDIR)
เพราะ newpath เป็นไดเร็กทอรี แต่ oldpath เป็นไฟล์ปกติ ไม่ใช่ไดเร็กทอรี

แน่นอนว่าสิ่งนี้ทำให้งานของห้องสมุด libexplain ซับซ้อนมากขึ้นเพราะ
ยกเลิกการเชื่อมโยง(2) หรือ คือ rm(2) การเรียกระบบถูกเรียกโดยปริยายโดย ตั้งชื่อใหม่(2) และดังนั้น . ทั้งหมด
ยกเลิกการเชื่อมโยง(2) หรือ คือ rm(2) ต้องตรวจพบและจัดการข้อผิดพลาดด้วย

สำเนา2
พื้นที่ สำเนา2(2) การเรียกระบบใช้เพื่อสร้างตัวอธิบายไฟล์ตัวที่สองที่อ้างอิงถึง
วัตถุเดียวกันกับตัวอธิบายไฟล์แรก โดยทั่วไปจะใช้เพื่อใช้งานเชลล์อินพุต
และการเปลี่ยนเส้นทางเอาต์พุต

สิ่งที่สนุกก็คือเช่นเดียวกับ ตั้งชื่อใหม่(2) สามารถเปลี่ยนชื่อไฟล์บน an . ได้
ไฟล์ที่มีอยู่และลบไฟล์เก่า สำเนา2(2) สามารถทำได้บนไฟล์ที่เปิดอยู่แล้ว
คำอธิบาย

อีกครั้ง สิ่งนี้ทำให้งานของห้องสมุด libexplain ซับซ้อนมากขึ้นเพราะว่า ปิดการขาย(2)
ระบบเรียกโดยปริยายโดย สำเนา2(2) และดังนั้น . ทั้งหมด ปิดการขาย(2) ข้อผิดพลาดต้องเป็น
ตรวจพบและจัดการเช่นกัน

การผจญภัย IN ไอโอทีแอล การสนับสนุน


พื้นที่ ไอโอทีแอล(2) การเรียกระบบช่วยให้ผู้เขียนโปรแกรมควบคุมอุปกรณ์มีวิธีการสื่อสารกับ
พื้นที่ผู้ใช้ที่ไม่พอดีกับเคอร์เนล API ที่มีอยู่ ดู ioctl_list(2)

ถอดรหัส ขอร้อง เบอร์
จากการดูคร่าวๆ ที่ ไอโอทีแอล(2) อินเทอร์เฟซ ดูเหมือนว่าจะมีขนาดใหญ่แต่มีจำกัด
จำนวนที่เป็นไปได้ ไอโอทีแอล(2) คำขอ คนละแบบกัน ไอโอทีแอล(2) คำขอมีประสิทธิผล
การเรียกระบบอื่น แต่ไม่มีความปลอดภัยประเภทใด ๆ เลย - คอมไพเลอร์ไม่สามารถช่วย
โปรแกรมเมอร์ได้รับสิทธิ์เหล่านี้ นี่อาจเป็นแรงจูงใจเบื้องหลัง ทีซีฟลัช(3) และ
เพื่อน

ความประทับใจแรกเริ่มคือคุณสามารถถอดรหัสได้ ไอโอทีแอล(2) ขอใช้สวิตช์ขนาดใหญ่
คำให้การ. สิ่งนี้กลายเป็นสิ่งที่เป็นไปไม่ได้เพราะมีคนค้นพบอย่างรวดเร็วว่ามันคือ
เป็นไปไม่ได้ที่จะรวมส่วนหัวของระบบที่จำเป็นทั้งหมดที่กำหนดส่วนต่างๆ ไอโอทีแอล(2)
ขอเพราะพวกเขามีช่วงเวลาที่ยากลำบากในการเล่นอย่างดีซึ่งกันและกัน

มองลึกลงไปมีหมายเลขคำขอ "ส่วนตัว" และอุปกรณ์
ผู้เขียนไดรเวอร์ได้รับการสนับสนุนให้ใช้พวกเขา ซึ่งหมายความว่ามีความเป็นไปได้ที่ใหญ่กว่ามาก
ชุดคำขอที่มีหมายเลขคำขอคลุมเครือซึ่งปรากฏให้เห็นในทันที อีกด้วย,
มีความคลุมเครือทางประวัติศาสตร์บางอย่างเช่นกัน

เรารู้แล้วว่าสวิตช์ใช้งานไม่ได้ แต่ตอนนี้เรารู้แล้วว่าต้องเลือก
ชื่อคำขอและคำอธิบายที่เหมาะสม เราต้องพิจารณาไม่เพียงแต่หมายเลขคำขอแต่
ตัวอธิบายไฟล์ด้วย

การดำเนินงานของ ไอโอทีแอล(2) การสนับสนุนภายในไลบรารี libexplain จะต้องมีตารางของ
ชี้ไปที่ ไอโอทีแอล(2) คำอธิบายคำขอ ตัวอธิบายเหล่านี้แต่ละตัวรวมถึงตัวเลือก
ตัวชี้ไปยังฟังก์ชันแก้ความกำกวม

คำขอแต่ละรายการถูกนำไปใช้จริงในไฟล์ต้นฉบับที่แยกจากกัน ดังนั้นความจำเป็น
รวมไปถึงไฟล์ต่างๆ ที่ปลดเปลื้องภาระผูกพันในการเล่นกับผู้อื่นอย่างดี

การแสดง
ปรัชญาเบื้องหลังไลบรารี libexplain คือการให้ข้อมูลมากที่สุดเท่าที่
เป็นไปได้ รวมทั้งการแสดงการเรียกของระบบอย่างถูกต้อง ในกรณีของ
ไอโอทีแอล(2) หมายถึงการพิมพ์หมายเลขคำขอที่ถูกต้อง (ตามชื่อ) และถูกต้อง (หรือ
อย่างน้อยก็มีประโยชน์) การแสดงอาร์กิวเมนต์ที่สาม

พื้นที่ ไอโอทีแอล(2) ต้นแบบมีลักษณะดังนี้:
int ioctl (ไฟล์ int, คำขอ int, ...);
ซึ่งควรให้สัญญาณเตือนความปลอดภัยประเภทของคุณดับลง ภายใน [e]glibc เปลี่ยนเป็น
ในรูปแบบต่างๆ:
int __ioctl (ไฟล์ int, คำขอ int, arg แบบยาว);
int __ioctl (ไฟล์ int, คำขอ int, เป็นโมฆะ * arg);
และคาดว่าอินเตอร์เฟส syscall ของเคอร์เนลลินุกซ์
asmlinkage long sys_ioctl (ไฟล์ int ที่ไม่ได้ลงชื่อ, คำขอ int ที่ไม่ได้ลงชื่อ, ความยาวที่ไม่ได้ลงชื่อ
หาเรื่อง);
ความแปรปรวนสุดขีดของอาร์กิวเมนต์ที่สามเป็นสิ่งที่ท้าทายเมื่อไลบรารี libexplain
พยายามพิมพ์การแสดงอาร์กิวเมนต์ที่สามนั้น แต่เมื่อขอหมายเลข
ได้รับการแก้ความกำกวมแต่ละรายการในตาราง ioctl ของไลบรารี libexplain มี
ฟังก์ชัน print_data แบบกำหนดเอง (OO ทำด้วยตนเอง)

คำอธิบาย
มีปัญหาน้อยลงในการพิจารณาคำอธิบายที่จะใช้ เมื่อได้หมายเลขคำขอ
ได้รับการแก้ความกำกวมแต่ละรายการในตาราง ioctl ของไลบรารี libexplain มีกำหนดเอง
ฟังก์ชัน print_explanation (อีกครั้ง OO ทำด้วยตนเอง)

ไม่เหมือนกับการเรียกระบบส่วนที่ 2 และส่วนที่ 3 ส่วนใหญ่ ไอโอทีแอล(2) คำขอไม่มีข้อผิดพลาด
เอกสาร ซึ่งหมายความว่า เพื่อให้คำอธิบายข้อผิดพลาดที่ดี จำเป็นต้องอ่าน kernel
แหล่งที่จะค้นพบ

· อะไร Errno(3) ค่าอาจถูกส่งคืนและ

· สาเหตุของข้อผิดพลาดแต่ละครั้ง

เนื่องจากลักษณะ OO ของการเรียกใช้ฟังก์ชันที่ส่งภายในเคอร์เนล คุณต้องอ่าน
ทั้งหมด แหล่งที่ดำเนินการนั้น ไอโอทีแอล(2) คำขอ ไม่ใช่แค่การนำไปปฏิบัติทั่วไป มัน
คาดว่าเมล็ดต่างกันจะมีเลขคลาดเคลื่อนและละเอียดต่างกัน
สาเหตุของข้อผิดพลาดที่แตกต่างกัน

ไอน์วาล vs เอนทตี้
สถานการณ์เลวร้ายยิ่งกว่าสำหรับ ไอโอทีแอล(2) คำขอมากกว่าการเรียกระบบด้วย EINVAL และ
ENOTTY ทั้งคู่ใช้เพื่อระบุว่า an ไอโอทีแอล(2) คำขอไม่เหมาะสมในเรื่องนั้น
บริบทและบางครั้ง ENOSYS, ENOTSUP และ EOPNOTSUPP (หมายถึงใช้สำหรับซ็อกเก็ต) เป็น
ดี. มีความคิดเห็นในแหล่งเคอร์เนลของลินุกซ์ที่ดูเหมือนจะบ่งบอกถึงความก้าวหน้า
กำลังดำเนินการทำความสะอาด สำหรับความโกลาหลเป็นพิเศษ BSD จะเพิ่ม ENIOIOCTL ให้กับความสับสน

ด้วยเหตุนี้จึงต้องให้ความสนใจกับกรณีข้อผิดพลาดเหล่านี้เพื่อให้ถูกต้อง โดยเฉพาะ
เนื่องจาก EINVAL อาจหมายถึงปัญหาเกี่ยวกับอาร์กิวเมนต์การเรียกระบบตั้งแต่หนึ่งรายการขึ้นไป

intptr_t
มาตรฐาน C99 กำหนดประเภทจำนวนเต็มที่รับประกันว่าจะสามารถเก็บตัวชี้ใด ๆ ได้
โดยไม่สูญเสียการเป็นตัวแทน

ฟังก์ชัน syscall ต้นแบบข้างต้นน่าจะเขียนได้ดีกว่า
sys_ioctl แบบยาว (ไฟล์ int ที่ไม่ได้ลงชื่อ, คำขอ int ที่ไม่ได้ลงชื่อ, intptr_t arg);
ปัญหาคือความไม่สอดคล้องกันของการรับรู้ที่เกิดจากอุปกรณ์เฉพาะหรือเฉพาะระบบไฟล์
ไอโอทีแอล(2) การนำไปปฏิบัติ เช่น
vfs_ioctl แบบยาว (ไฟล์โครงสร้าง *filp, cmd int ที่ไม่ได้ลงชื่อ, arg แบบยาวที่ไม่ได้ลงชื่อ);
ส่วนใหญ่ ไอโอทีแอล(2) คำขอจริง ๆ แล้วมี int *arg อาร์กิวเมนต์ที่สาม แต่มีไว้
ประกาศยาวนำไปสู่รหัสที่ปฏิบัติต่อสิ่งนี้นาน * หาเรื่อง สิ่งนี้ไม่เป็นอันตรายต่อ 32-บิต
(sizeof(long) == sizeof(int)) แต่น่ารังเกียจใน 64-bits (sizeof(long) != sizeof(int))
ขึ้นอยู่กับ endian-ness คุณทำหรือไม่ได้รับคุณค่าที่คุณคาดหวัง แต่คุณ เสมอ ได้รับ
การเขียนลวก ๆ หน่วยความจำหรือการเขียนลวก ๆ กองเช่นกัน

เขียนทั้งหมดนี้ว่า
int ioctl (ไฟล์ int, คำขอ int, ...);
int __ioctl (ไฟล์ int, คำขอ int, intptr_t arg);
sys_ioctl แบบยาว (ไฟล์ int ที่ไม่ได้ลงชื่อ, คำขอ int ที่ไม่ได้ลงชื่อ, intptr_t arg);
vfs_ioctl แบบยาว (ไฟล์โครงสร้าง *filp, cmd int ที่ไม่ได้ลงชื่อ, intptr_t arg);
เน้นว่าจำนวนเต็มเป็นเพียงจำนวนเต็มเพื่อแสดงปริมาณที่เกือบ
ประเภทตัวชี้ที่ไม่เกี่ยวข้องเสมอ

สรุป


ใช้ libexplain ผู้ใช้ของคุณจะชอบมัน

ลิขสิทธิ์


libexplain เวอร์ชัน 1.4
ลิขสิทธิ์ (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Peter Miller

ใช้ expand_lca2010 ออนไลน์โดยใช้บริการ onworks.net


เซิร์ฟเวอร์และเวิร์กสเตชันฟรี

ดาวน์โหลดแอพ Windows & Linux

  • 1
    สวก
    สวก
    SWIG คือเครื่องมือพัฒนาซอฟต์แวร์
    ที่เชื่อมโปรแกรมที่เขียนด้วยภาษา C และ
    C++ ที่มีระดับสูงหลากหลาย
    ภาษาโปรแกรม SWIG ใช้กับ
    แตกต่าง...
    ดาวน์โหลด SWIG
  • 2
    WooCommerce Nextjs ตอบสนองธีม
    WooCommerce Nextjs ตอบสนองธีม
    ตอบสนองธีม WooCommerce ที่สร้างขึ้นด้วย
    JS, Webpack, Babel, Node และ . ถัดไป
    Express โดยใช้ GraphQL และ Apollo
    ลูกค้า. ร้านค้า WooCommerce ใน React (
    ประกอบด้วย: สินค้า...
    ดาวน์โหลด WooCommerce Nextjs React Theme
  • 3
    Archlabs_repo
    Archlabs_repo
    แพ็คเกจ repo สำหรับ ArchLabs นี่คือ
    แอปพลิเคชันที่สามารถดึงข้อมูลได้
    ราคาเริ่มต้นที่
    https://sourceforge.net/projects/archlabs-repo/.
    ได้รับการโฮสต์ใน OnWorks ใน...
    ดาวน์โหลด archlabs_repo
  • 4
    โครงการ Zephyr
    โครงการ Zephyr
    โครงการ Zephyr คือคนรุ่นใหม่
    ระบบปฏิบัติการแบบเรียลไทม์ (RTOS) ที่
    รองรับฮาร์ดแวร์หลายตัว
    สถาปัตยกรรม มันขึ้นอยู่กับ
    เคอร์เนลขนาดเล็ก...
    ดาวน์โหลดโครงการ Zephyr
  • 5
    SCCons
    SCCons
    SCons เป็นเครื่องมือสร้างซอฟต์แวร์
    ที่เป็นทางเลือกที่เหนือกว่า
    เครื่องมือสร้าง "Make" แบบคลาสสิกที่
    เราทุกคนรู้จักและชื่นชอบ SCCons คือ
    ดำเนินการก...
    ดาวน์โหลด SCCons
  • 6
    พีเอสอินท์
    พีเอสอินท์
    PSeInt เป็นล่ามรหัสหลอกสำหรับ
    นักศึกษาการเขียนโปรแกรมที่พูดภาษาสเปน
    จุดประสงค์หลักคือเพื่อเป็นเครื่องมือสำหรับ
    การเรียนรู้และทำความเข้าใจพื้นฐาน
    แนวคิด...
    ดาวน์โหลด PSeInt
  • เพิ่มเติม»

คำสั่ง Linux

Ad