Làm thế nào tôi có thể tìm thấy việc thực hiện các cuộc gọi hệ thống nhân Linux?


375

Tôi đang cố gắng hiểu làm thế nào một chức năng, nói mkdir, hoạt động bằng cách nhìn vào nguồn kernel. Đây là một nỗ lực để hiểu các phần bên trong kernel và điều hướng giữa các chức năng khác nhau. Tôi biết mkdirđược định nghĩa trong sys/stat.h. Tôi tìm thấy nguyên mẫu:

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

Bây giờ tôi cần xem trong đó tập tin C chức năng này được thực hiện. Từ thư mục nguồn, tôi đã thử

ack "int mkdir"

được hiển thị

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);

Nhưng không ai trong số họ phù hợp với định nghĩa trong sys/stat.h.

Câu hỏi

  1. Tập tin nào đã mkdirthực hiện?
  2. Với định nghĩa hàm như trên, làm thế nào tôi có thể tìm ra tệp nào có triển khai? Có bất kỳ mẫu nào mà kernel theo sau trong việc xác định và thực hiện các phương thức không?

LƯU Ý: Tôi đang sử dụng kernel 2.6.36-rc1 .


2
Nhân tiện, hãy xem cái này: voinici.ceata.org/~tct/resurse/utlk.pdf
Tom Brito

Câu trả lời:


386

Các cuộc gọi hệ thống không được xử lý như các cuộc gọi chức năng thông thường. Nó cần mã đặc biệt để thực hiện chuyển đổi từ không gian người dùng sang không gian kernel, về cơ bản là một chút mã lắp ráp nội tuyến được đưa vào chương trình của bạn tại trang web cuộc gọi. Mã bên nhân "bắt" cuộc gọi hệ thống cũng là thứ cấp thấp mà bạn có thể không cần hiểu sâu, ít nhất là lúc đầu.

Trong include/linux/syscalls.hthư mục nguồn kernel, bạn tìm thấy điều này:

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

Sau đó /usr/include/asm*/unistd.h, bạn tìm thấy điều này:

#define __NR_mkdir                              83
__SYSCALL(__NR_mkdir, sys_mkdir)

Mã này đang nói mkdir(2)là hệ thống gọi # 83. Điều đó có nghĩa là, các cuộc gọi hệ thống được gọi theo số chứ không phải theo địa chỉ như với một cuộc gọi chức năng bình thường trong chương trình của riêng bạn hoặc đến một chức năng trong thư viện được liên kết với chương trình của bạn. Mã keo lắp ráp nội tuyến tôi đã đề cập ở trên sử dụng điều này để thực hiện chuyển đổi từ người dùng sang không gian kernel, mang theo các tham số của bạn cùng với nó.

Một bằng chứng khác cho thấy mọi thứ hơi kỳ lạ ở đây là không phải lúc nào cũng có một danh sách tham số nghiêm ngặt cho các cuộc gọi hệ thống: open(2)ví dụ, có thể lấy 2 hoặc 3 tham số. Điều đó có nghĩa open(2)quá tải , một tính năng của C ++, không phải C, nhưng giao diện tòa nhà tương thích với C. (Đây không giống với tính năng varargs của C , cho phép một hàm duy nhất có số lượng đối số thay đổi.)

Để trả lời câu hỏi đầu tiên của bạn, không có tệp mkdir()nào tồn tại. Linux hỗ trợ nhiều hệ thống tệp khác nhau và mỗi hệ thống có triển khai riêng hoạt động "mkdir". Lớp trừu tượng cho phép kernel ẩn tất cả những gì đằng sau một lệnh gọi hệ thống duy nhất được gọi là VFS . Vì vậy, bạn có thể muốn bắt đầu đào fs/namei.c, với vfs_mkdir(). Việc triển khai thực tế của mã sửa đổi hệ thống tệp cấp thấp là ở nơi khác. Ví dụ, việc thực hiện ext4 được gọi ext4_mkdir(), được định nghĩa trong fs/ext4/namei.c.

Đối với câu hỏi thứ hai của bạn, có có các mẫu cho tất cả điều này, nhưng không phải là một quy tắc duy nhất. Những gì bạn thực sự cần là một sự hiểu biết khá rộng về cách thức hoạt động của hạt nhân để tìm ra nơi bạn nên tìm kiếm bất kỳ cuộc gọi hệ thống cụ thể nào. Không phải tất cả các cuộc gọi hệ thống đều liên quan đến VFS, vì vậy các chuỗi cuộc gọi phía hạt nhân của chúng không bắt đầu fs/namei.c. mmap(2), chẳng hạn, bắt đầu bằng mm/mmap.c, vì đó là một phần của hệ thống con quản lý bộ nhớ ("mm") của hạt nhân.

Tôi khuyên bạn nên lấy một bản sao " Tìm hiểu hạt nhân Linux " của Bovet và Cesati.


Câu trả lời rất hay. Một điểm về cuốn sách mà bạn đề cập, "Tìm hiểu về nhân Linux". Tôi không có nó, nhưng từ ngày phát hành (2000) và TOC (tại địa điểm oreilly) đối với tôi có khoảng 2,2 hạt nhân cộng với một số hiểu biết từ 2,4 hạt nhân (nhưng tôi đã sai). Câu hỏi của tôi là: có một cuốn sách tương đương bao gồm 2,6 hạt nhân bên trong? (hoặc thậm chí tốt hơn bao gồm 2.2, 2.4 và 2.6)?
DavAlPi

2
@DavAlPi: Theo như tôi biết, Bovet & Cesati vẫn là cuốn sách duy nhất hay nhất về chủ đề này. Khi tôi cần bổ sung nó với nhiều tài liệu cập nhật hơn, tôi sẽ đi sâu vào Documentationthư mục con của cây nguồn cho hạt nhân mà tôi đang làm việc.
Warren Young

1
Trong thực tế mở (2) là một hàm varargs. Chỉ có hai cách để gọi nó, vì vậy trang tài liệu này theo cách này, nguyên mẫu thực tế có ...trong đó như bất kỳ chức năng varargs nào. Tất nhiên, điều này được thực hiện ở cấp libc. Nó có thể chuyển 0 hoặc giá trị rác cho kernel ABI khi tham số thứ ba không được sử dụng.
Random832

"Đó là điều bạn không cần phải hiểu". Thế giới sẽ là một nơi tốt hơn nếu loại câu này không có ở đâu trên mạng stackexchange.
Petr

84

Điều này có thể không trả lời trực tiếp câu hỏi của bạn, nhưng tôi thấy stracethực sự tuyệt vời khi cố gắng hiểu các cuộc gọi hệ thống cơ bản, thực tế, được thực hiện cho ngay cả các lệnh shell đơn giản nhất. ví dụ

strace -o trace.txt mkdir mynewdir

Hệ thống gọi lệnh mkdir mynewdirsẽ được chuyển sang track.txt để bạn xem.


5
+1 Thủ thuật gọn gàng! Tôi chưa từng sử dụng nó trước đây
David Oneill

3
Tốt hơn nữa, tạo tệp đầu ra dấu vết.strace và mở nó trong VIM. VIM sẽ làm nổi bật nó, làm cho việc đọc nó dễ dàng hơn rất nhiều.
Marcin

55

Một nơi tốt để đọc nguồn nhân Linux là tham chiếu chéo Linux (LXR) . Tìm kiếm trả về kết quả khớp được nhập (nguyên mẫu hàm, khai báo biến, v.v.) ngoài kết quả tìm kiếm văn bản miễn phí, do đó, nó xử lý tốt hơn một grep đơn thuần (và cũng nhanh hơn).

LXR không mở rộng định nghĩa tiền xử lý. Các cuộc gọi hệ thống có tên của họ được xử lý bởi bộ tiền xử lý ở khắp mọi nơi. Tuy nhiên, hầu hết (tất cả?) Các cuộc gọi hệ thống được xác định với một trong các SYSCALL_DEFINExhọ macro. Kể từ khi mkdirnhận hai đối số, tìm kiếm SYSCALL_DEFINE2(mkdirdẫn đến sự khai báo của mkdirsyscall :

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

ok, sys_mkdiratcó nghĩa là nó là tòa nhà cao tầng mkdirat, vì vậy nhấp vào nó chỉ dẫn bạn đến phần khai báo include/linux/syscalls.h, nhưng định nghĩa chỉ ở trên.

Công việc chính của mkdiratlà gọi vfs_mkdir(VFS là lớp hệ thống tập tin chung). Cliking trên đó cho thấy hai kết quả tìm kiếm: khai báo include/linux/fs.hvà định nghĩa một vài dòng ở trên. Công việc chính của vfs_mkdirlà gọi việc thực hiện cụ thể theo hệ thống tập tin : dir->i_op->mkdir. Để tìm cách thực hiện điều này , bạn cần chuyển sang thực hiện hệ thống tệp riêng lẻ và không có quy tắc khó và nhanh - thậm chí nó có thể là một mô-đun bên ngoài cây nhân.

¹ LXR là một chương trình lập chỉ mục. Có một số trang web cung cấp giao diện cho LXR, với các bộ phiên bản đã biết khác nhau và giao diện web hơi khác nhau. Chúng có xu hướng đến và đi, vì vậy nếu cái bạn đã từng sử dụng không có sẵn, hãy thực hiện tìm kiếm trên web cho linux linux tham chiếu chéo để tìm cái khác.


Đó là một trong những tài nguyên. Câu trả lời chính xác.
Stablesog

"Lỗi máy chủ nội bộ" trong liên kết của linux.no .
Fredrick Gauss

@FredrickGauss Trong một thời gian lxr.linux.no đó là giao diện đẹp nhất cho LXR nhưng nó thường xuyên bị ngừng hoạt động. Bây giờ tôi nghĩ rằng nó đã đi cho tốt. Tôi đã thay thế liên kết đầu tiên đến một giao diện LXR khác.
Gilles

21

Các cuộc gọi hệ thống thường được gói trong SYSCALL_DEFINEx()macro, đó là lý do tại sao một đơn giản grepkhông tìm thấy chúng:

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

Tên hàm cuối cùng sau khi macro được mở rộng kết thúc sys_mkdir. Các SYSCALL_DEFINEx()vĩ mô cho biết thêm điều soạn sẵn như truy tìm mã mà mỗi định nghĩa syscall cần phải có.


17

Lưu ý: tệp .h không xác định hàm. Nó được khai báo trong tệp .h đó và được định nghĩa (triển khai) ở nơi khác. Điều này cho phép trình biên dịch bao gồm thông tin về chữ ký của hàm (nguyên mẫu) để cho phép kiểm tra kiểu đối số và khớp các kiểu trả về với bất kỳ bối cảnh gọi nào trong mã của bạn.

Nói chung, các tệp .h (tiêu đề) trong C được sử dụng để khai báo các hàm và xác định các macro.

mkdirđặc biệt là một cuộc gọi hệ thống. Có thể có một trình bao bọc libc GNU xung quanh lệnh gọi hệ thống đó (trên thực tế gần như chắc chắn là vậy). Việc thực hiện kernel thực sự mkdircó thể được tìm thấy bằng cách tìm kiếm các nguồn kernel và các cuộc gọi hệ thống nói riêng.

Lưu ý rằng cũng sẽ có một triển khai một số loại mã tạo thư mục cho mỗi hệ thống tập tin. Lớp VFS (hệ thống tập tin ảo) cung cấp một API chung mà lớp gọi hệ thống có thể gọi vào. Mọi hệ thống tập tin phải đăng ký các chức năng cho lớp VFS để gọi vào. Điều này cho phép các hệ thống tệp khác nhau thực hiện ngữ nghĩa riêng của chúng về cách cấu trúc các thư mục (ví dụ: nếu chúng được lưu trữ bằng cách sử dụng một số loại lược đồ băm để giúp tìm kiếm các mục cụ thể hiệu quả hơn). Tôi đề cập đến điều này bởi vì bạn có khả năng gặp phải các chức năng tạo thư mục cụ thể của hệ thống tệp này nếu bạn đang tìm kiếm cây nguồn Linux.


8

Không có cách triển khai nào bạn tìm thấy khớp với nguyên mẫu trong sys / stat.h Có thể tìm kiếm một câu lệnh bao gồm với tệp tiêu đề này sẽ thành công hơn?


1
Việc triển khai (như được mô tả trong sys / stat.h) là việc kinh doanh của userland và libc. Nội dung kernel (cách nó thực sự được thực hiện) là kernel kernel. Đối với tất cả các hacker tin tặc, chức năng bên trong có thể được gọi là xyzzy và lấy 5 tham số. Công việc của libc là thực hiện cuộc gọi của người dùng, dịch nó thành bất kỳ câu thần chú nào được yêu cầu, gửi đi và thu thập bất kỳ kết quả nào.
vonbrand

6

Dưới đây là một vài bài viết blog thực sự tuyệt vời mô tả các kỹ thuật khác nhau để săn lùng mã nguồn hạt nhân cấp thấp.


12
Vui lòng không chỉ đăng các liên kết đến blog hoặc diễn đàn, tóm tắt nội dung của chúng để người đọc có thể thấy những gì họ đang nói và để lại một cái gì đó nếu các trang web biến mất. Ngoài ra, liên kết đầu tiên của bạn là về libc, không có chủ đề cho câu hỏi này.
Gilles
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.