Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình C

Hiểu các cuộc gọi hệ thống:Mục đích, chức năng và cách sử dụng phổ biến trong Linux

Trong bài viết Linuxhint này, chúng tôi sẽ giải thích lệnh gọi hệ thống là gì, chúng được dùng để làm gì và điều gì khiến chúng khác biệt với các hàm khác trong thư viện C tiêu chuẩn. Chúng tôi cũng sẽ cho bạn biết chúng phục vụ chức năng gì cho kernel trong hệ thống và cách các tiến trình sử dụng dịch vụ mà chúng cung cấp. Chúng tôi cũng sẽ hiển thị cho bạn danh sách các lệnh gọi hệ thống được sử dụng phổ biến nhất kèm theo mô tả ngắn gọn về từng chức năng và tiêu đề mà chúng được khai báo. Trong phần khác, chúng tôi sẽ hướng dẫn bạn cách giám sát hoạt động của các lệnh gọi hệ thống thông qua bảng điều khiển lệnh.

Về mặt khái niệm, tất cả các hệ thống đều được tạo thành từ các lớp, trong đó mỗi lớp có chức năng và đặc quyền riêng. Ngăn xếp các lớp tạo nên hệ thống này bắt đầu ở cấp thấp nhất với các thành phần phần cứng và kết thúc ở lớp trên cùng được gọi là chế độ người dùng.

Tất cả các chương trình chúng tôi chạy trên máy tính và tất cả các mã, chúng tôi viết và biên dịch kết quả trong một quy trình chạy ở chế độ người dùng của hệ thống. Ở chế độ này, người dùng làm việc và thực hiện các công việc hàng ngày của mình, khởi chạy và sử dụng các ứng dụng khác nhau, quản lý tệp, v.v. Ở cấp độ bảo mật, đây là lớp bề ngoài nhất của hệ thống và do đó bị hạn chế nhất và theo mặc định, hoàn toàn bị giới hạn trong việc quản lý và sử dụng trực tiếp tài nguyên hệ thống.

Như đã đề cập trước đó, lớp phần cứng là cấp độ thấp nhất của hệ thống. Ngay phía trên nó là nhân Linux. Nhân là trái tim của hệ điều hành, nơi nó tích hợp với phần cứng và quản lý chặt chẽ nó, là nhân duy nhất có đặc quyền làm điều đó. Ví dụ:các tiến trình và bộ nhớ được quản lý ở đây, dữ liệu được truy cập từ đĩa cứng hoặc SSD, các thiết bị mạng được điều khiển, v.v. Mọi thứ mà hệ điều hành và các tiến trình thực hiện với phần cứng đều được thực hiện thông qua kernel. Vì vậy, có thể nói nó là một loại firmware tích hợp phần mềm và phần cứng.

Do các hạn chế về truy cập và quản lý tài nguyên mà hệ điều hành áp đặt cho chế độ người dùng và vì chỉ có thể truy cập vào các tài nguyên này thông qua kernel, nên cần phải có một cơ chế cho phép các tiến trình tương tác với các tài nguyên mà chúng cần để hoạt động.

Cuộc gọi hệ thống, hay SysCalls, là một tập hợp các chức năng được cung cấp bởi hệ điều hành, đóng vai trò là giao diện giữa tiến trình người dùng và kernel. Các chức năng này cho phép chúng tôi tương tác với HĐH và yêu cầu một dịch vụ thông qua nó yêu cầu sử dụng tài nguyên hệ thống. Các tòa nhà cao tầng không cấp quyền truy cập trực tiếp vào tài nguyên hoặc quản lý chúng, nhưng kernel là thứ quản lý chúng và cung cấp chúng cho quá trình gọi chúng, nhưng luôn nằm dưới sự quản lý chặt chẽ của nó.

Trong thực tế, các hàm gọi hệ thống trông giống như các hàm thông thường và được triển khai theo cách đó. Chúng có các đối số đầu vào để gửi dữ liệu cần xử lý và các đối số đầu ra để hệ điều hành trả về kết quả.

Phương thức gọi loại hàm này giống như bất kỳ hàm nào khác mà chúng ta tìm thấy trong thư viện C. Do đó, câu hỏi liệu nó có phải là chức năng gọi hay không, trên thực tế, là một câu hỏi thuần túy mang tính khái niệm đối với người lập trình.

Đối số của các hàm này sử dụng các kiểu tiêu chuẩn của ngôn ngữ C. Mặc dù, về bản chất nhiệm vụ, chúng thường là các con trỏ lưu trữ địa chỉ bộ nhớ, bộ mô tả, đường dẫn, v.v.

Trên Linux, hiện có khoảng 350 cuộc gọi hệ thống. Ngoài ra, có một số lượng lớn các hàm không phải là lệnh gọi hệ thống mà quản lý tài nguyên thông qua chúng, chẳng hạn như các hàm malloc(), free(), calloc() và realloc() quản lý bộ nhớ một cách linh hoạt bằng cách sử dụng lệnh gọi hệ thống trong mã của bạn.

Cách giám sát lệnh gọi hệ thống bằng lệnh Strace trong Bảng điều khiển Linux

Bây giờ bạn đã biết chức năng gọi hệ thống là gì, hãy chỉ cho bạn cách giám sát chúng trong thời gian thực từ bảng điều khiển lệnh Linux bằng lệnh “strace”. Lệnh “strace” rất linh hoạt. Nó được sử dụng để giám sát hệ thống và cung cấp một số tùy chọn mà bạn có thể thấy bằng lệnh sau:

Khi bạn chạy lệnh này, danh sách các tùy chọn giám sát do “srace” cung cấp sẽ được hiển thị trong bảng điều khiển lệnh.

Hiểu các cuộc gọi hệ thống:Mục đích, chức năng và cách sử dụng phổ biến trong Linux

Để giám sát các cuộc gọi chung của một tiến trình, chúng ta cần chạy nó bằng lệnh sau:

strac
strace ./process
e -h

Để kiểm tra điều này, chúng tôi biên dịch đoạn mã sau mà chúng tôi đã đưa ra làm ví dụ trong bài viết có tựa đề “Chức năng kết nối trong ngôn ngữ C”. Mã này, mặc dù rất đơn giản nhưng lại rất thú vị vì nó kết nối chúng ta với máy chủ Google thông qua dịch vụ HTTP và cho phép chúng ta gửi lệnh và nhận phản hồi.

#include
#include
#include
#include
#include
#include
#include
#include

int chính (){

// bước 1
int socket_id;
cổng int =80;
lỗi int;
bộ đệm char [1025];

cấu trúc máy chủ *máy chủ;
cấu trúc máy khách sockaddr_in;
memset(&server, 0, sizeof(server));

// bước 2
máy chủ =gethostbyname ("www.google.com" );
if(máy chủ ==NULL)
  {
     printf("\nLỗi lấy dữ liệu miền.\n");
     trả lại 1;
 

// bước 3
socket_id =ổ cắm ( AF_INET, SOCK_STREAM, 0 );

// bước 4
client.sin_family =AF_INET;
client.sin_port =htons(port);

// bước 5
bcopy((char *) máy chủ->h_addr,
  (char *) &client.sin_addr.s_addr,
  sizeof(server->h_length));

error=connect(socket_id, (struct sockaddr *) &client, sizeof(client));

nếu (lỗi <0){
  printf ("\nKhông thể thiết lập kết nối tới máy chủ\n");
  đóng(socket_id);
  trả về 1;
 

printf ("\nKết nối với :%s\n", inet_ntoa( client.sin_addr ));
trong khi (1){

printf("Để thoát nhấn Ctrl+c \nGửi lệnh http:");
fgets(bộ đệm, 1025, stdin);
gửi (socket_id, bộ đệm, 1025, 0);
bộ nhớ(&buffer, '\0', 1025);
recv(socket_id, bộ đệm, 1025, 0);
printf("%s", đệm);
memset(&buffer, '\0', 1025);

Chúng tôi biên dịch mã và đặt cho nó tên đầu ra là “kết nối”. Sau đó, chúng tôi thực thi nó bằng lệnh “./connect” và thêm lệnh “strace” để có thể giám sát các cuộc gọi tổng hợp.

Lệnh này hiển thị các tòa nhà cao tầng của các tiến trình trong bảng điều khiển lệnh. Như có thể thấy trong hình dưới đây, mặc dù mã của chúng tôi chỉ sử dụng các lệnh gọi tòa nhà socket(), connect(), send() và recv() nhưng việc thực thi nó yêu cầu các lệnh gọi hệ thống khác xảy ra trong mã của các hàm mà chúng tôi sử dụng.

Hiểu các cuộc gọi hệ thống:Mục đích, chức năng và cách sử dụng phổ biến trong Linux

Lệnh sau hiển thị bản tóm tắt các lệnh gọi hệ thống cho một quy trình khi nó kết thúc:

Hiểu các cuộc gọi hệ thống:Mục đích, chức năng và cách sử dụng phổ biến trong Linux

Chức năng gọi hệ thống để quản lý quy trình:

Chức năng Mô tả Tiêu đề thực thi ()

execlp()

thực thi()

thực thi()

execvp()

execvpe()

Nhóm hàm hệ thống gọi các lệnh gọi thay thế tiến trình này bằng tiến trình khác bằng cách kế thừa PID và tài nguyên từ tiến trình cha.unistd.hfork()Sao chép một tiến trình.unistd.hgetpid()Lấy PID của tiến trình đang gọi.unistd.hgetppid()Lấy PID của tiến trình cha của tiến trình đang gọi.unistd.hexit()Báo cáo trạng thái thoát của một tiến trình.stdlib.hgetcwd()

getwd()

Trả về một chuỗi có thư mục làm việc hiện tại của tiến trình đang gọi.unistd.hpause() Tạm dừng quá trình cho đến khi có tín hiệu đến.unistd.hwait() Đợi đầu ra của một tiến trình con từ tiến trình cha.wait.h

Chức năng gọi hệ thống để quản lý tệp:

Chức năng Mô tả Tiêu đề mở()

openat()

Open files.fcntl.hclose()Đóng files.unistd.hread()Đọc files.unistd.hpoll() Thăm dò tính khả dụng của các tệp cho một thao tác cụ thể.poll.hwrite()Viết files.unistd.hfcntl() Thao tác mô tả tệp.fcntl.htruncate()

ftruncate()

Cắt bớt một tệp theo chiều dài được chỉ định.hcreat()Tạo một tệp.fcntl.hchmod()

fchmod()

Đặt quyền của filesys/stat.hunlink() Xóa file.unistd.h

Chức năng gọi hệ thống để xử lý tín hiệu:

Chức năng Mô tả signal() Liên kết tín hiệu với một trình xử lý.signal.hkill() Gửi tín hiệu đến một tiến trình.signal.hkillpg() Gửi tín hiệu đến một nhóm các tiến trình.signal.hraise() Thực hiện hành động của một tín hiệu trong quá trình gọi ra nó.signal.hsigaction() Đặt hành động của một tín hiệu.signal.hsigwait() Tạm dừng thực thi chuỗi cuộc gọi cho đến khi tín hiệu được chỉ định đến.signal.hsighold()Thêm tín hiệu vào cuộc gọi tiến trình' signal Mask.signal.hsigignore()Bỏ qua signal.signal.hsigblock()Chặn signal.signal.hpsignal()

psiginfo()

In thông báo có mô tả về signal.signal.h

Các hàm gọi hệ thống để xử lý ổ cắm:

Chức năng Mô tả socket()Tạo socket.socket.hbind()Liên kết tên với socketsocket.hconnect()Kết nối socket.socket.hlisten()Lắng nghe các kết nối trên socket.socket.haccept()Chấp nhận kết nối trên socket.socket.hrecv()

recvfrom()

recvmsg()

Nhận tin nhắn từ socket.socket.hsend()

gửi tới()

gửi tin nhắn()

Gửi tin nhắn từ socket.socket.hgetsockname() Trả về địa chỉ của ổ cắm cụ thể bằng bộ mô tả.socket.hgetsockopt() Đặt hoặc nhận các tùy chọn trên sockets.socket.h

Kết luận

Trong bài viết Linuxhint này, chúng tôi đã giải thích chức năng gọi hệ thống là gì và cách chúng được sử dụng để yêu cầu các dịch vụ hạt nhân liên quan đến việc sử dụng tài nguyên hệ thống. Chúng tôi đã giải thích ngắn gọn cho bạn về quy trình của người dùng và cách chúng tương tác với kernel thông qua lệnh gọi hệ thống.

Để giúp bạn nhanh chóng áp dụng các tính năng này vào thực tế, chúng tôi đưa vào danh sách các lệnh gọi hệ thống được sử dụng phổ biến nhất cùng với mô tả ngắn gọn và tiêu đề mà bạn cần đưa vào mã của mình để sử dụng chúng. Chúng tôi cũng đưa vào một phần trong đó chúng tôi đã hướng dẫn bạn cách giám sát các tòa nhà cao tầng của một quy trình thông qua bảng điều khiển lệnh.