Cuộc gọi hệ thống Linux Exec

Linux Exec System Call



Lệnh gọi hệ thống thực thi được sử dụng để thực thi một tệp đang nằm trong một quá trình hoạt động. Khi thực thi được gọi, tệp thực thi trước đó sẽ được thay thế và tệp mới được thực thi.

Chính xác hơn, chúng ta có thể nói rằng việc sử dụng lệnh gọi hệ thống thực thi sẽ thay thế tệp hoặc chương trình cũ từ tiến trình bằng một tệp hoặc chương trình mới. Toàn bộ nội dung của quy trình được thay thế bằng một chương trình mới.







Phân đoạn dữ liệu người dùng thực hiện lệnh gọi hệ thống thực thi () được thay thế bằng tệp dữ liệu có tên được cung cấp trong đối số trong khi gọi lệnh thực thi ().



Chương trình mới được tải vào cùng một không gian quy trình. Quy trình hiện tại chỉ được chuyển thành một quy trình mới và do đó id quy trình PID không bị thay đổi, điều này là do chúng tôi không tạo một quy trình mới, chúng tôi chỉ thay thế một quy trình bằng một quy trình khác trong thực thi.



Nếu tiến trình hiện đang chạy chứa nhiều hơn một luồng thì tất cả các luồng sẽ bị chấm dứt và hình ảnh tiến trình mới sẽ được tải và sau đó được thực thi. Không có hàm hủy kết thúc các luồng của tiến trình hiện tại.





PID của quy trình không bị thay đổi nhưng dữ liệu, mã, ngăn xếp, đống, v.v. của quy trình được thay đổi và được thay thế bằng những dữ liệu của quy trình mới được tải. Quá trình mới được thực hiện từ điểm nhập.

Lệnh gọi hệ thống thực thi là một tập hợp các hàm và trong ngôn ngữ lập trình C, tên tiêu chuẩn cho các hàm này như sau:



  1. người thực thi
  2. người thi hành
  3. thực thi
  4. người thực thi
  5. thi hành
  6. thực thi


Ở đây cần lưu ý rằng các hàm này có cùng cơ sở người điều hành theo sau bởi một hoặc nhiều chữ cái. Những điều này được giải thích dưới đây:

Và: Nó là một mảng các con trỏ trỏ đến các biến môi trường và được chuyển một cách rõ ràng cho tiến trình mới được tải.

NS: l là cho các đối số dòng lệnh được chuyển một danh sách vào hàm

P: p là biến môi trường đường dẫn giúp tìm tệp được truyền dưới dạng đối số để được tải vào quy trình.

v: v dành cho các đối số dòng lệnh. Chúng được chuyển dưới dạng một mảng con trỏ đến hàm.

Tại sao thực thi được sử dụng?

execute được sử dụng khi người dùng muốn khởi chạy một tệp hoặc chương trình mới trong cùng một quy trình.

Hoạt động bên trong của người điều hành

Hãy xem xét các điểm sau để hiểu hoạt động của executive:

  1. Hình ảnh quy trình hiện tại được ghi đè bằng hình ảnh quy trình mới.
  2. Hình ảnh quy trình mới là hình ảnh bạn đã chuyển làm đối số thực thi
  3. Quá trình hiện đang chạy đã kết thúc
  4. Hình ảnh quy trình mới có cùng ID quy trình, cùng môi trường và cùng bộ mô tả tệp (vì hình ảnh quy trình không được thay thế được thay thế)
  5. Chỉ số CPU và bộ nhớ ảo bị ảnh hưởng. Ánh xạ bộ nhớ ảo của ảnh quá trình hiện tại được thay thế bằng bộ nhớ ảo của ảnh quá trình mới.

Cú pháp của các hàm họ thực thi:

Sau đây là các cú pháp cho mỗi hàm của thực thi:

int executel (const char * path, const char * arg,…)
int executelp (const char * file, const char * arg,…)
int thực thi (const char * path, const char * arg,…, char * const envp [])
int executev (const char * path, const char * argv [])
int executevp (const char * file, const char * argv [])
int executevpe (const char * file, const char * argv [], char * const envp [])

Sự miêu tả:

Kiểu trả về của các hàm này là Int. Khi hình ảnh quá trình được thay thế thành công, không có gì được trả về chức năng gọi bởi vì quá trình đã gọi nó không còn chạy nữa. Nhưng nếu có bất kỳ lỗi nào -1 sẽ được trả về. Nếu có bất kỳ lỗi nào xảy ra, errno được thiết lập.

Theo cú pháp:

  1. con đường được sử dụng để chỉ định tên đường dẫn đầy đủ của tệp sẽ được thực thi.
  1. tức giận là đối số được thông qua. Nó thực sự là tên của tệp sẽ được thực thi trong quá trình này. Hầu hết các lần giá trị của arg và path là như nhau.
  1. const char * arg trong các chức năng executel (), thi hành () và thực thi () được coi là arg0, arg1, arg2,…, argn. Về cơ bản, nó là một danh sách các con trỏ đến các chuỗi bị kết thúc bằng null. Ở đây, đối số đầu tiên trỏ đến tên tệp sẽ được thực thi như được mô tả trong điểm 2.
  1. envp là một mảng chứa các con trỏ trỏ đến các biến môi trường.
  1. tập tin được sử dụng để chỉ định tên đường dẫn sẽ xác định đường dẫn của tệp hình ảnh quy trình mới.
  1. Các chức năng của cuộc gọi thực thi kết thúc bằng được sử dụng để thay đổi môi trường cho hình ảnh quy trình mới. Các hàm này chuyển danh sách cài đặt môi trường bằng cách sử dụng đối số envp . Đối số này là một mảng các ký tự trỏ đến Chuỗi kết thúc rỗng và xác định biến môi trường.

Để sử dụng các hàm họ thực thi, bạn cần đưa tệp tiêu đề sau vào chương trình C của mình:

#bao gồm

Ví dụ 1: Sử dụng lệnh gọi hệ thống thực thi trong chương trình C

Hãy xem xét ví dụ sau, trong đó chúng tôi đã sử dụng lệnh gọi hệ thống thực thi trong lập trình C trong Linux, Ubuntu: Chúng tôi có hai tệp c ở đây example.c và hello.c:

example.c

MÃ SỐ:

#bao gồm
#bao gồm
#bao gồm
NSchủ chốt(NSargc, char *argv[])
{
printf ('PID của example.c =% d ',người lém lỉnh());
char *args[] = {'Xin chào', 'NS', 'Lập trình',VÔ GIÁ TRỊ};
người thực thi('./xin chào',args);
printf ('Quay lại example.c');
trở lại 0;
}

chào c

MÃ SỐ:

#bao gồm
#bao gồm
#bao gồm
NSchủ chốt(NSargc, char *argv[])
{
printf ('Chúng tôi đang ở trong Hello.c ');
printf ('PID của hello.c =% d ',người lém lỉnh());
trở lại 0;
}

ĐẦU RA:

PID của example.c = 4733
Chúng tôi đang ở trong Hello.c
PID của hello.c = 4733

Trong ví dụ trên, chúng ta có tệp example.c và tệp hello.c. Trong tệp .c ví dụ, trước hết chúng ta đã in ID của quy trình hiện tại (tệp example.c đang chạy trong quy trình hiện tại). Sau đó, trong dòng tiếp theo, chúng ta đã tạo một mảng các con trỏ ký tự. Phần tử cuối cùng của mảng này phải là NULL làm điểm kết thúc.

Sau đó, chúng ta đã sử dụng hàm executev () lấy tên tệp và mảng con trỏ ký tự làm đối số của nó. Ở đây cần lưu ý rằng chúng ta đã sử dụng ./ với tên tệp, nó chỉ định đường dẫn của tệp. Vì tệp nằm trong thư mục chứa example.c nên không cần chỉ định đường dẫn đầy đủ.

Khi hàm executev () được gọi, hình ảnh quy trình của chúng ta sẽ được thay thế bây giờ tệp example.c không có trong quá trình nhưng tệp hello.c đang trong quá trình này. Có thể thấy rằng ID quy trình giống nhau cho dù hello.c là hình ảnh quy trình hay example.c là hình ảnh quy trình vì quy trình là giống nhau và hình ảnh quy trình chỉ được thay thế.

Sau đó, chúng ta có một điều khác cần lưu ý ở đây là câu lệnh printf () sau khi thi hành lệnh executev () không được thực thi. Điều này là do quyền điều khiển không bao giờ được đưa trở lại hình ảnh quy trình cũ sau khi hình ảnh quy trình mới thay thế nó. Điều khiển chỉ hoạt động trở lại chức năng gọi khi quá trình thay thế hình ảnh không thành công. (Giá trị trả về là -1 trong trường hợp này).

Sự khác biệt giữa các lệnh gọi hệ thống fork () và execute ():

Lời gọi hệ thống fork () được sử dụng để tạo một bản sao chính xác của một tiến trình đang chạy và bản sao được tạo là tiến trình con và tiến trình đang chạy là tiến trình mẹ. Trong khi đó, lệnh gọi hệ thống execute () được sử dụng để thay thế hình ảnh quy trình bằng hình ảnh quy trình mới. Do đó không có khái niệm về các tiến trình mẹ và con trong lệnh gọi hệ thống execute ().

Trong cuộc gọi hệ thống fork (), các tiến trình cha và con được thực hiện cùng một lúc. Nhưng trong lệnh gọi hệ thống thực thi (), nếu việc thay thế hình ảnh tiến trình thành công, điều khiển sẽ không quay trở lại nơi hàm thực thi đã được gọi thay vì nó sẽ thực thi tiến trình mới. Quyền kiểm soát sẽ chỉ được chuyển lại nếu có bất kỳ lỗi nào.

Ví dụ 2: Kết hợp các lệnh gọi hệ thống fork () và execute ()

Hãy xem xét ví dụ sau, trong đó chúng ta đã sử dụng cả lệnh gọi hệ thống fork () và execute () trong cùng một chương trình:

example.c

MÃ SỐ:

#bao gồm
#bao gồm
#bao gồm
NSchủ chốt(NSargc, char *argv[])
{
printf ('PID của example.c =% d ',người lém lỉnh());
pid_t p;
P=cái nĩa();
nếu như(P== -1)
{
printf ('Đã xảy ra lỗi khi gọi fork ()');
}
nếu như(P==0)
{
printf ('Chúng tôi đang trong quá trình trẻ em ');
printf ('Gọi hello.c từ quy trình con ');
char *args[] = {'Xin chào', 'NS', 'Lập trình',VÔ GIÁ TRỊ};
người thực thi('./xin chào',args);
}
khác
{
printf ('Chúng tôi đang trong quá trình dành cho phụ huynh');
}
trở lại 0;
}

chào c:

MÃ SỐ:

#bao gồm
#bao gồm
#bao gồm
NSchủ chốt(NSargc, char *argv[])
{
printf ('Chúng tôi đang ở trong Hello.c ');
printf ('PID của hello.c =% d ',người lém lỉnh());
trở lại 0;
}

ĐẦU RA:

PID của example.c = 4790
Chúng tôi đang trong Quy trình dành cho cha mẹ
Chúng tôi đang trong quá trình Trẻ em
Gọi hello.c từ quy trình con
Chúng tôi đang ở trong hello.c
PID của hello.c = 4791

Trong ví dụ này, chúng tôi đã sử dụng lệnh gọi hệ thống fork (). Khi tiến trình con được tạo 0 sẽ được gán cho p và sau đó chúng ta sẽ chuyển sang tiến trình con. Bây giờ khối câu lệnh với if (p == 0) sẽ được thực thi. Một thông báo được hiển thị và chúng tôi đã sử dụng lệnh gọi hệ thống executev () và hình ảnh quy trình con hiện tại là example.c sẽ được thay thế bằng hello.c. Trước khi thực hiện cuộc gọi con và quy trình cha giống nhau.

Có thể thấy rằng PID của example.c và hello.c hiện đã khác nhau. Điều này là do example.c là hình ảnh quy trình mẹ và hello.c là hình ảnh quy trình con.