2013-01-13 19 views
20

Tôi biết execvp có thể được sử dụng để thực hiện các lệnh đơn giản như sau:execvp chạy lệnh như thế nào?

char* arg[] = {"ls", "-l", NULL}; 
execvp(arg[0],arg); 

Tôi muốn biết những gì đang diễn ra trong đây khi tôi chạy execvp. Trong trang người đàn ông nó nói execvp thay thế hình ảnh của hình ảnh quá trình bằng hình ảnh mới. Tuy nhiên ở đây tôi đang chạy một lệnh không phải là một thực thi.

Để cụ thể, hãy nói rằng có một lệnh yêu cầu cụ thể đầu vào, ví dụ: con mèo. Nếu tôi có tệp văn bản text.txt chứa tên tệp được mong đợi cho mèo và tôi chuyển hướng stdin tới luồng tệp của tệp, thì đầu ra của execle("cat","cat",NULL) hoặc execvp("cat", arg) (rõ ràng là nơi các cửa hàng arg "cat"NULL) dẫn đến kết quả đầu ra giao diện điều khiển là cat /filename sẽ? Trực giác của tôi là tôi phải đọc các tập tin và có thể phân tích nó để lưu trữ các đối số trong arg. Tuy nhiên tôi muốn chắc chắn.

Cảm ơn trước!

+1

Tất cả các lệnh trong linux đều có thể thực thi được. – Alex

+2

Nhập 'ls' vào thiết bị đầu cuối của bạn để xem vị trí của chương trình' ls'. Bạn thực sự đang chạy một tệp thực thi khi bạn nói 'ls'. – Cornstalks

+1

@Alex: Ngoại trừ một số lệnh đặc biệt được triển khai trong trình bao, như 'cd',' source' và 'exit'. – duskwuff

Trả lời

16

Đây là những gì xảy ra trong một cuộc gọi execvp:

  1. libc bạn tìm kiếm thực hiện trong PATH, nếu có, đối với các tập tin đó là để được thực thi. Hầu hết, nếu không phải tất cả, các lệnh trong các hệ thống giống UNIX là các tệp thực thi. Điều gì sẽ xảy ra nếu nó không? Thử nó. Hãy xem how glibc does it.
  2. Thông thường, nếu thực thi được tìm thấy, một cuộc gọi đến execve sẽ được thực hiện. Các bộ phận của execve có thể được thực hiện trong libc hoặc nó có thể là một cuộc gọi hệ thống (như trong Linux).
  3. Linux chuẩn bị chương trình bằng cách cấp phát bộ nhớ cho nó, mở nó, lập lịch trình để thực thi, khởi tạo cấu trúc bộ nhớ, thiết lập đối số và môi trường từ đối số được cung cấp đến cuộc gọi execvp. đặt tác vụ hiện tại (gọi là execvp) khi không thực thi. Bạn có thể tìm thấy việc triển khai của nó here.

Tất cả các bước trên tuân theo các yêu cầu được đặt bởi POSIX được mô tả trong manual pages có liên quan.

+0

Giải thích tuyệt vời !. Một nghi ngờ nhỏ - Liệu nó có nghĩa là ảnh mới được tải sẽ có cùng giá trị CR3 như cũ không? –

+0

Không. Mỗi quy trình có CR3 riêng của mình, đó là trách nhiệm của mã thiết lập các bảng trang của nó. –

2

"ls" không chỉ là một lệnh, nó thực sự là một chương trình (hầu hết các lệnh). Khi bạn chạy execvp như vậy, nó sẽ nuke toàn bộ chương trình của bạn, bộ nhớ của nó, ngăn xếp của nó, đống của nó, vv ... khái niệm "rõ ràng nó ra" và đưa nó vào "ls" để nó có thể sử dụng nó cho ngăn xếp của riêng mình, đống, v.v.

Tóm lại, execvp sẽ hủy chương trình của bạn và thay thế bằng chương trình khác, trong trường hợp này là "ls".

+0

Tại sao nó được giảm giá? – Alex

+0

Không chắc chắn ... có vẻ như một người nào đó đã upvoted nó trở lại 0 mặc dù lol. – Verdagon

1

Trực giác của tôi là tôi phải đọc tệp và có thể phân tích cú pháp để lưu trữ các đối số trong arg. Tuy nhiên tôi muốn chắc chắn.

Trực giác của bạn phần lớn là chính xác. Tiện ích cat mà bạn đang sử dụng làm ví dụ có hai đường dẫn mã riêng biệt:

  • Nếu có tên tệp được chỉ định làm đối số, nó sẽ mở và đọc từng đối số.
  • Nếu không có tên tệp nào được chỉ định, nó sẽ đọc từ đầu vào tiêu chuẩn.

Hành vi này được triển khai cụ thể trong tiện ích cat - nó không được triển khai ở bất kỳ cấp thấp hơn nào. Đặc biệt, nó chắc chắn không phải là một phần của cuộc gọi hệ thống exec. Các cuộc gọi hệ thống exec không "nhìn vào" đối số ở tất cả; họ chỉ chuyển chúng thẳng vào quy trình mới trong argv và quy trình đó sẽ xử lý chúng tuy nhiên nó phù hợp.

12

Về câu hỏi của bạn:

Trong trang người đàn ông nó nói execvp thay thế hình ảnh của hình ảnh quá trình với cái mới. Tuy nhiên ở đây tôi đang chạy một lệnh không phải là thực thi.

Thời gian dài trước đây trình bao rất hạn chế và hầu hết tất cả các lệnh UNIX là các tệp thực thi độc lập. Bây giờ, chủ yếu cho mục đích tốc độ một số tập hợp con của lệnh UNIX được thực hiện bên trong vỏ chính nó, những lệnh được gọi là builtins. Bạn có thể kiểm tra bất cứ lệnh được thực hiện trong vỏ của bạn như built-in hoặc không qua type lệnh:

λ ~/ type echo 
echo is a shell builtin 

(. Danh mục đầy đủ các lệnh nội trú với mô tả có thể được tìm thấy trong man trang để shell của bạn ví dụ như man bash-builtins hoặc man builtin)

Nhưng vẫn hầu hết các lệnh vẫn có họ thi hành được đối tác:

λ ~/ whereis echo 
/bin/echo 

Vì vậy, trong trường hợp cụ thể của bạn khi bạn đang chạy:

char* arg[] = {"ls", "-l", NULL}; 
execvp(arg[0],arg); 

Bạn đang thực sự thay thế không gian địa chỉ của quy trình hiện tại bằng không gian địa chỉ (rất có thể) /bin/ls.


trực giác của tôi là tôi phải đọc các tập tin và có thể được phân tích nó để lưu trữ các đối số trong arg.

Thực tế là bạn có. Nhưng bạn cũng có thể sử dụng một số chức năng trong hạt nhân cho rằng aka "công việc":
Thay vì đặt tên tập tin trong tập tin riêng biệt add cái gọi là công việc như dòng đầu tiên của tập tin bạn muốn mèo:

#!/bin/cat 

Và thêm chmod +x vào đó. Sau đó, bạn có thể chạy nó như là thực thi (thông qua bất kỳ exec chức năng hoặc vỏ):

λ ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me 
λ ~/tmp/ chmod +x cat_me 
λ ~/tmp/ ./cat_me 
#!/bin/cat 
TEST 

Trong số nguyên nhân đó là có một nhược điểm của in shebang tự với tập tin nhưng nó vẫn còn vui vẻ để làm điều đó trong-kernel =)

BTW. Vấn đề mà bạn mô tả nếu quá phổ biến rằng có một tập tin thực thi đặc biệt gọi là xargs mà (trong lời giải thích rất đơn giản) thực thi chương trình được đưa ra trong danh sách các đối số được truyền qua stdin. Để biết thêm thông tin, hãy tham khảo man xargs.


Đối ghi nhớ dễ dàng exec -family Tôi thường sử dụng bảng sau:

  Figure 8.14. Differences among the six exec functions 
+----------+----------+----------+----------+--------+---------+--------+ 
| Function | pathname | filename | agr list | argv[] | environ | envp[] | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execl | *  |   |  * |  | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execlp |   | *  |  * |  | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execle | *  |   |  * |  |   | * | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execv | *  |   |   | * | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execvp |   | *  |   | * | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execve | *  |   |   | * |   | * | 
+----------+----------+----------+----------+--------+---------+--------+ 
| letter |   | p  |  l | v |   | e | 
+----------+----------+----------+----------+--------+---------+--------+ 

Vì vậy, trong trường hợp của bạn execvp mất filename, argv (v) và environ (e). Sau đó, nó cố gắng "đoán" tên đường dẫn (còn gọi là đường dẫn đầy đủ) bằng cách thêm filename (trong trường hợp của bạn cat) vào từng thành phần đường dẫn trong PATH cho đến khi tìm đường dẫn có thể thực thi filename.

Thông tin chi tiết hơn về những gì đang diễn ra dưới mui xe của exec (bao gồm cả nội dung thừa kế) có thể được tìm thấy trong Advanced Programming in the UNIX Environment (2nd Edition) by W. Richard Stevens and Stephen A. Rago aka APUE2.
Nếu bạn quan tâm đến UNIX internals bạn có lẽ nên đọc nó.

Các vấn đề liên quan