Gọi hệ thống Linux là gì?

What Is Linux System Call



Trước khi chúng ta đi sâu vào định nghĩa của một lệnh gọi hệ thống Linux và kiểm tra chi tiết về quá trình thực thi của nó, cách tốt nhất là bắt đầu với việc xác định các lớp phần mềm khác nhau của một hệ thống Linux điển hình.

Nhân Linux là một chương trình chuyên dụng khởi động và chạy ở mức thấp nhất hiện có trên phần cứng của bạn. Nó có nhiệm vụ sắp xếp mọi thứ chạy trên máy tính, bao gồm xử lý các sự kiện bàn phím, đĩa và mạng để cung cấp các lát cắt thời gian để thực hiện song song nhiều chương trình.







Khi hạt nhân thực thi một chương trình cấp người dùng, nó sẽ ảo hóa không gian bộ nhớ để các chương trình tin rằng chúng là tiến trình duy nhất đang chạy trong bộ nhớ. Bong bóng bảo vệ cách ly phần cứng và phần mềm này làm tăng tính bảo mật và độ tin cậy. Một ứng dụng không có đặc quyền không thể truy cập bộ nhớ của các chương trình khác, và nếu chương trình đó bị treo, hạt nhân sẽ kết thúc để nó không thể gây hại cho phần còn lại của hệ thống.



Phá vỡ rào cản với cuộc gọi hệ thống Linux

Lớp cách ly giữa các ứng dụng không có đặc quyền này cung cấp một ranh giới tuyệt vời để bảo vệ các ứng dụng và người dùng khác trên hệ thống. Tuy nhiên, nếu không có một số cách để giao tiếp với các phần tử khác trong máy tính và thế giới bên ngoài, các chương trình sẽ không thể thực hiện được nhiều điều.



Để tạo điều kiện tương tác, hạt nhân chỉ định một cổng phần mềm cho phép chương trình đang chạy yêu cầu hạt nhân hành động thay mặt cho nó. Giao diện này được gọi là lệnh gọi hệ thống.





Vì Linux tuân theo triết lý UNIX về mọi thứ đều là tệp, nhiều chức năng có thể được thực hiện bằng cách mở và đọc hoặc ghi vào tệp, đó có thể là một thiết bị. Ví dụ: trên Windows, bạn có thể sử dụng một hàm có tên CryptGenRandom để truy cập các byte ngẫu nhiên. Nhưng trên Linux, điều này có thể được thực hiện bằng cách chỉ cần mở tệp / dev / urandom và đọc các byte từ nó bằng cách sử dụng các lệnh gọi hệ thống đầu vào / đầu ra tệp tiêu chuẩn. Sự khác biệt quan trọng này cho phép một giao diện cuộc gọi hệ thống đơn giản hơn.

Wafer-Thin Wrapper

Trong hầu hết các ứng dụng, các cuộc gọi hệ thống không được thực hiện trực tiếp tới hạt nhân. Hầu như tất cả các chương trình đều liên kết trong thư viện C chuẩn, cung cấp một lớp bao bọc mỏng nhưng quan trọng xung quanh các lệnh gọi hệ thống Linux. Thư viện đảm bảo rằng các đối số của hàm được sao chép vào đúng thanh ghi của bộ xử lý sau đó đưa ra lệnh gọi hệ thống Linux tương ứng. Khi dữ liệu được nhận từ cuộc gọi, trình bao bọc sẽ diễn giải kết quả và trả nó trở lại chương trình một cách nhất quán.



Đằng sau hậu trường

Mọi chức năng trong một chương trình tương tác với hệ thống cuối cùng được chuyển thành một lệnh gọi hệ thống. Để thấy điều này trong thực tế, hãy bắt đầu với một ví dụ cơ bản.

vô hiệuchủ chốt() {
}

Đây có lẽ là chương trình C tầm thường nhất mà bạn từng thấy. Nó chỉ đơn giản là giành được quyền kiểm soát thông qua điểm vào chính và sau đó thoát ra. Nó thậm chí không trả về giá trị vì main được định nghĩa là void. Lưu tệp dưới dạng ctest.c và biên dịch nó:

gcc ctest.NS -ctest

Sau khi nó được biên dịch, chúng tôi có thể thấy kích thước tệp là 8664 byte. Nó có thể thay đổi một chút trên hệ thống của bạn, nhưng nó phải là khoảng 8k. Đó là rất nhiều mã chỉ để nhập và thoát! Lý do nó là 8k là thời gian chạy libc đang được đưa vào. Ngay cả khi chúng tôi loại bỏ các biểu tượng, nó vẫn còn hơn 6k.

Trong một ví dụ đơn giản hơn, chúng ta có thể thực hiện lệnh gọi hệ thống Linux để thoát thay vì phụ thuộc vào thời gian chạy C để thực hiện điều đó cho chúng ta.

vô hiệu_bắt đầu() {
asm('movl $ 1,% eax;'
'xorl% ebx,% ebx;'
'int $ 0x80');
}

Ở đây chúng ta chuyển 1 vào thanh ghi EAX, xóa thanh ghi EBX (nếu không sẽ chứa giá trị trả về), sau đó gọi ngắt lệnh gọi hệ thống Linux 0x80 (hoặc 128 ở dạng thập phân). Ngắt này kích hoạt hạt nhân để xử lý cuộc gọi của chúng ta.

Nếu chúng tôi biên dịch ví dụ mới của mình, được gọi là asmtest.c và loại bỏ các ký hiệu và loại trừ thư viện tiêu chuẩn:

gcc-NS-nostdlib asmtest.NS -o asmtest

chúng tôi sẽ tạo ra một nhị phân nhỏ hơn 1k (trên hệ thống của tôi, nó mang lại 984 byte). Hầu hết mã này là các tiêu đề thực thi. Bây giờ chúng tôi đang gọi cuộc gọi hệ thống Linux trực tiếp.

Cho tất cả mục đích thiết thực

Trong hầu hết các trường hợp, bạn sẽ không bao giờ phải thực hiện các cuộc gọi hệ thống trực tiếp trong các chương trình C của mình. Tuy nhiên, nếu bạn sử dụng hợp ngữ, nhu cầu có thể phát sinh. Tuy nhiên, trong tối ưu hóa, tốt nhất là để các hàm của thư viện C thực hiện các lệnh gọi của hệ thống và chỉ có mã quan trọng về hiệu suất của bạn được nhúng trong các chỉ thị hợp ngữ.

Hướng dẫn cách lập trình cuộc gọi hệ thống

Danh sách tất cả các cuộc gọi hệ thống

Nếu bạn muốn xem danh sách tất cả các lệnh gọi hệ thống có sẵn cho Linux, bạn có thể kiểm tra các trang tham khảo sau: Danh sách đầy đủ các lệnh gọi hệ thống trên LinuxHint.com, filippo.io/linux-syscall-table/ và hoặc syscalls.kernelgrok.com