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.h
thư 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)
là 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.