Làm thế nào để shell thực hiện một chương trình?


11

Nếu tôi biên dịch một chương trình bằng gcc và cố gắng thực thi nó từ bash shell, trình tự chính xác của các bước tiếp theo là bash để thực thi nó là gì?

Tôi biết fork(), execve(), loader, dynamic linker(và những thứ khác) đều được tham gia, nhưng có thể một người nào đó đưa ra một chuỗi chính xác các bước và một số tài liệu tham khảo đọc phù hợp?

Biên tập:

Từ các câu trả lời, có vẻ như câu hỏi có thể ngụ ý nhiều khả năng. Tôi muốn thu hẹp vào một trường hợp đơn giản:

(test.c chỉ in hello world)

$ gcc test.c -o test
$ ./test

Điều gì sẽ là các bước trong trường hợp trên ( ./test), cụ thể liên quan đến chương trình bắt đầu bash trong một số quy trình con, thực hiện tải, liên kết, v.v.?


4
Tôi mời bạn đọc lwn.net/Articles/630727
cuonglm

3
Tại sao không thử 'strace bash -c' test '?
Sergiy Kolodyazhnyy

2
Có vẻ như một cuốn sách giáo khoa Hệ điều hành phong nha sẽ là một nguồn tài nguyên tốt cho OP. Cố gắng học cách các hệ điều hành hoạt động bằng cách đặt các câu hỏi riêng lẻ như thế này không có khả năng là một quy trình hiệu quả.
Barmar

Sẽ rất hữu ích khi xem một ví dụ tối thiểu về vỏ: brennan.io/2015/01/16/write-a-shell-in-c
jinawee

Câu trả lời:


5

Chà, trình tự chính xác có thể khác nhau, vì có thể có một bí danh hoặc hàm đầu tiên được mở rộng / giải thích trước khi chương trình thực tế được thực thi, và sau đó là sự khác biệt cho một tên tệp đủ điều kiện ( /usr/libexec/foo) so với thứ sẽ được tìm kiếm trong tất cả các thư mục của PATHbiến môi trường (chỉ foo). Ngoài ra, các chi tiết của việc thực hiện có thể làm phức tạp vấn đề, như foo | bar | zotđòi hỏi làm việc nhiều hơn cho vỏ (một số số fork(2), dup(2), và, tất nhiên, pipe(2), trong số các cuộc gọi hệ thống khác), trong khi một cái gì đó giống như exec foolà ít hơn nhiều công việc như vỏ chỉ đơn thuần là thay thế chính nó với chương trình mới (nghĩa là không fork). Cũng quan trọng là các nhóm quy trình (đặc biệt là nhóm quy trình tiền cảnh, tất cả các PID đều ănSIGINTkhi ai đó bắt đầu trộn trên Ctrl+ C, phiên và liệu công việc sẽ được chạy trong nền, được theo dõi ( foo &) hoặc nền, bị bỏ qua ( foo & disown). Các chi tiết chuyển hướng I / O cũng sẽ thay đổi mọi thứ, ví dụ: nếu đầu vào tiêu chuẩn được đóng bởi shell ( foo <&-) hoặc liệu một tệp được mở dưới dạng stdin ( foo < blah).

stracehoặc tương tự sẽ có thông tin về các cuộc gọi hệ thống cụ thể được thực hiện trong quá trình này và nên có các trang hướng dẫn cho mỗi cuộc gọi đó. Việc đọc cấp độ hệ thống phù hợp sẽ là bất kỳ số chương nào trong "Lập trình nâng cao trong môi trường UNIX" của Stevens trong khi một cuốn sách vỏ (ví dụ: "Từ Bash đến Z Shell") sẽ trình bày chi tiết hơn về phần vỏ.


Tôi đã chỉnh sửa câu hỏi để thu hẹp vào một trường hợp đơn giản
Jake

1

Giả sử trình bao ví dụ trong sách giáo khoa (để rõ ràng về mã) đang chạy (vì vậy trình liên kết động được thực hiện), các lệnh bạn đề cập sẽ yêu cầu trình bao để thực hiện các cuộc gọi hệ thống sau:

  • đọc: nhận lệnh tiếp theo trong trường hợp này gcc
  • ngã ba: hai quá trình là cần thiết, chúng tôi giả sử cha mẹ có pid 500 và con để minh họa.
  • cha mẹ sẽ gọi chờ (501), trong khi đó đứa trẻ sẽ gọi exec. Tại thời điểm này, shell không còn chạy trên pid 501. gcc thực hiện nhiều cuộc gọi hệ thống bao gồm ở mức tối thiểu mở, đóng, đọc, viết, chmod, fork, exec, chờ và thoát.
  • Khi gcc gọi thoát, chờ sẽ quay lại, ghi được gọi để hiển thị lời nhắc và quá trình sẽ lặp lại.

Các lệnh phức tạp hơn tất nhiên làm tăng thêm sự phức tạp cho chuỗi cơ bản này. Hai ví dụ đơn giản hơn về các biến chứng cơ bản là chuyển hướng io cơ bản trong đó một chuỗi kép mở, đóng, được chèn giữa ngã ba và thực thi và các quy trình nền trong đó chờ đợi được bỏ qua (và chờ thêm vào trình xử lý sigchld).


Bổ sung nhỏ: câu hỏi hỏi về tải và liên kết động. Tất cả các mã được liên kết tĩnh, tức là thực sự có trong tệp chương trình, được thực hiện bởi kernel trước khi chương trình được khởi động. Các thư viện được tải động, tức là các tệp riêng biệt, được xử lý bởi chính chương trình trước khi bắt đầu hàm main (). Mã cho điều này được tự động thêm bởi gcc.
Stig Hemmer

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.