ฉันจะค้นหาการนำไปใช้ของการเรียกระบบเคอร์เนล Linux ได้อย่างไร?


375

ฉันพยายามที่จะเข้าใจว่าฟังก์ชั่นพูดmkdirทำงานได้อย่างไรโดยดูที่เคอร์เนล นี่เป็นความพยายามที่จะเข้าใจเคอร์เนลภายในและนำทางระหว่างฟังก์ชั่นต่าง ๆ ฉันรู้ว่าถูกกำหนดไว้ในmkdir sys/stat.hฉันพบต้นแบบ:

/* Create a new directory named PATH, with permission bits MODE.  */
extern int mkdir (__const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

ตอนนี้ฉันต้องดูว่าไฟล์นี้ใช้ฟังก์ชั่นใดของ C จากไดเรกทอรีแหล่งฉันพยายาม

ack "int mkdir"

ซึ่งแสดง

security/inode.c
103:static int mkdir(struct inode *dir, struct dentry *dentry, int mode)

tools/perf/util/util.c
4:int mkdir_p(char *path, mode_t mode)

tools/perf/util/util.h
259:int mkdir_p(char *path, mode_t mode);

sys/stat.hแต่ไม่มีของพวกเขาตรงกับความหมายใน

คำถาม

  1. ไฟล์ใดที่มีmkdirการนำไปใช้
  2. ด้วยคำจำกัดความของฟังก์ชั่นด้านบนฉันจะทราบได้อย่างไรว่าไฟล์ใดที่มีการนำไปใช้ มีรูปแบบใดบ้างที่เคอร์เนลตามมาในการกำหนดและใช้วิธีการ?

หมายเหตุ: ผมใช้เคอร์เนล2.6.36-RC1


2
โดยวิธีการตรวจสอบนี้: voinici.ceata.org/~tct/resurse/utlk.pdf
Tom Brito

คำตอบ:


386

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

ในinclude/linux/syscalls.hไดเรกทอรีไดเรกทอรีเคอร์เนลของคุณคุณจะพบสิ่งนี้:

asmlinkage long sys_mkdir(const char __user *pathname, int mode);

จากนั้นใน/usr/include/asm*/unistd.hคุณจะพบสิ่งนี้:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

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

หลักฐานอีกเล็กน้อยที่สิ่งต่าง ๆ แปลก ๆ เล็กน้อยที่นี่คือไม่มีรายการพารามิเตอร์ที่เข้มงวดสำหรับการเรียกของระบบ: open(2)ตัวอย่างเช่นอาจใช้พารามิเตอร์ 2 หรือ 3 ซึ่งหมายความว่าopen(2)จะมากเกินไปคุณลักษณะของภาษา C ++, C ไม่ได้ที่ยังอินเตอร์เฟซ syscall คือ C ที่เข้ากันได้ (นี่ไม่ใช่สิ่งเดียวกับคุณสมบัติ varargsของ C ซึ่งช่วยให้ฟังก์ชั่นเดียวสามารถรับอาร์กิวเมนต์จำนวนตัวแปรได้)

เพื่อตอบคำถามแรกของคุณไม่มีไฟล์เดียวที่mkdir()มีอยู่ Linux รองรับระบบไฟล์ที่แตกต่างกันและแต่ละระบบมีการดำเนินการ "mkdir" ของตัวเอง ชั้นนามธรรมที่ช่วยให้เคอร์เนลซ่อนทุกสิ่งที่อยู่เบื้องหลังการเรียกระบบเดียวที่เรียกว่าวีเอฟเอ ดังนั้นคุณอาจต้องการที่จะเริ่มต้นในการขุดด้วยfs/namei.c vfs_mkdir()การใช้งานจริงของรหัสการแก้ไขระบบไฟล์ระดับต่ำนั้นอยู่ที่อื่น ยกตัวอย่างเช่นการดำเนินการ ext4 จะเรียกว่าที่กำหนดไว้ในext4_mkdir()fs/ext4/namei.c

สำหรับคำถามที่สองของคุณใช่มีรูปแบบทั้งหมดนี้ แต่ไม่ใช่กฎเดียว สิ่งที่คุณต้องการจริงๆคือความเข้าใจในวงกว้างเกี่ยวกับวิธีการทำงานของเคอร์เนลเพื่อหาว่าคุณควรค้นหาการเรียกใช้ระบบใดโดยเฉพาะ fs/namei.cไม่ทุกสายระบบที่เกี่ยวข้องกับวีเอฟเอเพื่อให้เคอร์เนลด้านโซ่โทรของพวกเขาทำไม่ได้ทั้งหมดเริ่มต้นใน mmap(2)ตัวอย่างเช่นเริ่มทำงานmm/mmap.cเนื่องจากเป็นส่วนหนึ่งของระบบย่อยการจัดการหน่วยความจำ ("mm") ของเคอร์เนล

ฉันขอแนะนำให้คุณรับสำเนาของ "การทำความเข้าใจเคอร์เนลลินุกซ์ " โดย Bovet และ Cesati


คำตอบที่ดีมาก จุดหนึ่งเกี่ยวกับหนังสือที่คุณพูดถึง "การทำความเข้าใจเคอร์เนลลินุกซ์" ฉันไม่ได้มี แต่จากวันที่วางจำหน่าย (2000) และ TOC (ที่ไซต์ oreilly) ดูเหมือนว่าฉันจะมีประมาณ 2.2 เมล็ดบวกกับข้อมูลเชิงลึกบางอย่างจาก 2.4 เมล็ด (แต่ฉันผิด) คำถามของฉันคือ: มีหนังสือเทียบเท่าที่ครอบคลุม 2.6 เมล็ดภายใน? (หรือดีกว่านั้นที่ครอบคลุม 2.2, 2.4 และ 2.6)?
DavAlPi

2
@DavAlPi: เท่าที่ฉันรู้ Bovet & Cesati ยังคงเป็นหนังสือเล่มเดียวที่ดีที่สุดในหัวข้อนี้ เมื่อฉันต้องการเสริมด้วยวัสดุที่ทันสมัยมากขึ้นฉันไปขุดในDocumentationไดเรกทอรีย่อยของต้นไม้ต้นสำหรับเคอร์เนลฉันทำงานด้วย
Warren Young

1
ในความเป็นจริง open (2) เป็นฟังก์ชัน varargs มีเพียงสองวิธีในการเรียกใช้ดังนั้น manpage จะจัดทำเอกสารด้วยวิธีนี้ต้นแบบที่แท้จริงมี...อยู่ในนั้นเป็นฟังก์ชัน varargs ใด ๆ แน่นอนว่าสิ่งนี้ถูกนำไปใช้ในระดับ libc มันอาจผ่าน 0 หรือค่าขยะไปยังเคอร์เนล ABI เมื่อไม่ได้ใช้พารามิเตอร์ที่สาม
Random832

"เป็นสิ่งที่คุณไม่จำเป็นต้องเข้าใจ" โลกจะเป็นสถานที่ที่ดีกว่าถ้าประโยคประเภทนี้ไม่มีที่ใดที่จะพบได้ในเครือข่ายสแต็คแลกเปลี่ยน
Petr

84

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

strace -o trace.txt mkdir mynewdir

ระบบเรียกใช้คำสั่งmkdir mynewdirจะถูกดัมพ์ไปยัง trace.txt เพื่อความพึงพอใจในการรับชมของคุณ


5
+1 เคล็ดลับเรียบร้อย! ฉันไม่เคยใช้มาก่อน
David Oneill

3
ยังดีกว่าสร้างไฟล์เอาต์พุต trace.strace และเปิดใน VIM VIM จะเน้นมันทำให้การอ่านง่ายขึ้นมาก
Marcin

55

แหล่งที่ดีสำหรับอ่านเคอร์เนล Linux คือLinux cross-reference (LXR) ¹ การค้นหาส่งคืนการจับคู่ที่พิมพ์ (ฟังก์ชั่นต้นแบบการประกาศตัวแปร ฯลฯ ) นอกเหนือจากผลลัพธ์การค้นหาข้อความแบบอิสระดังนั้นจึงเป็นเรื่องง่ายกว่า grep เพียงเล็กน้อย (และเร็วขึ้นด้วย)

LXR ไม่ขยายคำจำกัดความตัวประมวลผลล่วงหน้า การเรียกระบบมีชื่อของพวกเขายุ่งเหยิงโดยตัวประมวลผลล่วงหน้าทุกที่ อย่างไรก็ตามการเรียกระบบส่วนใหญ่ (ทั้งหมด?) ถูกกำหนดด้วยหนึ่งในSYSCALL_DEFINExตระกูลของมาโคร ตั้งแต่mkdirใช้เวลาสองข้อโต้แย้งการค้นหาSYSCALL_DEFINE2(mkdirนำไปสู่การประกาศของmkdirsyscall :

SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)
{
    return sys_mkdirat(AT_FDCWD, pathname, mode);
}

ตกลงsys_mkdiratหมายความว่าเป็นmkdiratsyscall ดังนั้นการคลิกที่มันจะนำคุณไปสู่การประกาศinclude/linux/syscalls.hเท่านั้น แต่คำจำกัดความดังกล่าวข้างต้น

งานหลักของmkdiratคือการโทรvfs_mkdir(VFS เป็นเลเยอร์ระบบไฟล์ทั่วไป) การวนซ้ำที่แสดงผลการค้นหาสองรายการ: การประกาศในinclude/linux/fs.hและการนิยามสองสามบรรทัดด้านบน งานหลักของคือการเรียกใช้งานระบบแฟ้มเฉพาะ:vfs_mkdir dir->i_op->mkdirเพื่อหาวิธีการนี้จะดำเนินการที่คุณต้องเปิดการใช้งานของระบบแฟ้มบุคคลและไม่มีกฎอย่างหนักและรวดเร็ว - มันก็อาจจะเป็นโมดูลนอกต้นไม้เคอร์เนล

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


นั่นคือหนึ่งในทรัพยากร คำตอบที่ดี
Stabledog

"ข้อผิดพลาดภายในเซิร์ฟเวอร์" ในการเชื่อมโยงของlinux.no
Fredrick Gauss

@FredrickGauss ในขณะที่ lxr.linux.no ซึ่งเป็นอินเทอร์เฟซที่ดีที่สุดสำหรับ LXR แต่มีการหยุดทำงานบ่อยครั้ง ตอนนี้ฉันคิดว่ามันหายไปได้ดี ฉันแทนที่ลิงก์แรกไปยังอินเตอร์เฟส LXR อื่น
Gilles

21

การเรียกของระบบมักจะถูกห่อหุ้มในSYSCALL_DEFINEx()มาโครซึ่งเป็นเหตุผลว่าทำไม Simple grepไม่สามารถหาได้:

fs/namei.c:SYSCALL_DEFINE2(mkdir, const char __user *, pathname, int, mode)

sys_mkdirชื่อฟังก์ชั่นสุดท้ายหลังจากแมโครมีการขยายสิ้นสุดขึ้นเป็น SYSCALL_DEFINEx()แมโครเพิ่มสิ่งสำเร็จรูปเช่นรหัสติดตามว่าแต่ละนิยาม syscall ต้องมี


17

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

โดยทั่วไปไฟล์. h (ส่วนหัว) ใน C จะใช้เพื่อประกาศฟังก์ชันและกำหนดมาโคร

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

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


8

การใช้งานที่คุณพบไม่ตรงกับต้นแบบใน sys / stat.h บางทีการค้นหาคำสั่ง include กับไฟล์ส่วนหัวนี้จะประสบความสำเร็จมากกว่าหรือไม่


1
การนำไปใช้งาน (ดังอธิบายใน sys / stat.h) เป็นธุรกิจของ userland และ libc สิ่งที่เคอร์เนลภายใน (วิธีการทำจริง ๆ ) เป็นธุรกิจภายในเคอร์เนล สำหรับแฮ็กเกอร์เคอร์เนลทุกตัวฟังก์ชั่นภายในอาจเรียกว่า xyzzy และรับพารามิเตอร์ 5 ตัว เป็นหน้าที่ของ libc ในการรับสายผู้ใช้แปลมันเป็นสิ่งที่จำเป็นต้องใช้เคอร์เนลส่งออกไปและรวบรวมผลลัพธ์ใด ๆ
vonbrand

6

ต่อไปนี้เป็นบทความบล็อกที่ยอดเยี่ยมจริงๆที่อธิบายเทคนิคต่าง ๆ สำหรับการตามล่ารหัสเคอร์เนลระดับต่ำ


12
โปรดอย่าโพสต์เพียงแค่ลิงก์ไปยังบล็อกหรือฟอรัมสรุปเนื้อหาของพวกเขาเพื่อให้ผู้อ่านสามารถเห็นสิ่งที่พวกเขากำลังและมีบางสิ่งที่เหลือหากเว็บไซต์หายไป นอกจากนี้ลิงก์แรกของคุณเกี่ยวกับ libc ซึ่งไม่เกี่ยวข้องกับคำถามนี้
Gilles
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.