Câu trả lời:
Các chương trình được biên dịch thông thường sẽ "chạy trực tiếp" trên CPU, nhưng một chương trình không chạy trong chân không:
Nhiều chương trình dựa vào các thư viện ( DLLs
hoặc .so
thư viện) được tải động bên ngoài . Cách để liên kết chúng tùy thuộc vào trình biên dịch / trình liên kết và mỗi HĐH có các tiêu chuẩn khác nhau. Tuy nhiên, cũng có những chương trình "liên kết tĩnh" cung cấp tất cả mã riêng của họ.
Một hệ điều hành hiện đại không cung cấp quyền kiểm soát hoàn toàn máy tính cho một chương trình đang chạy. Các chương trình dựa trên "các cuộc gọi hệ thống" cho i / o, truy cập vào phần cứng và những thứ như tín hiệu và đi vào trạng thái ngủ. Các dịch vụ và giao diện có sẵn được xác định bởi HĐH. HĐH cũng kiểm soát các phần nào của hệ thống (bộ nhớ, thanh ghi, ngắt) chương trình được phép sử dụng.
Một chương trình GUI cũng phải hoạt động thông qua môi trường người dùng đồ họa để tự vẽ trên màn hình. Nhưng có lẽ bạn đã nghĩ về điều này rồi.
Vì những lý do này, các ứng dụng độc lập với hệ điều hành phải dựa vào một "máy ảo" nào đó, giống như ứng dụng được cung cấp bởi bộ thực thi java. Điều quan trọng, VM cung cấp giao diện chuẩn cho tài nguyên HĐH (i / o, tín hiệu, v.v.). Tất nhiên, java hoặc python cũng diễn giải "mã byte" thay vì xử lý các yêu cầu của tập lệnh của Intel; nhưng đó là một câu chuyện khác nhau.
Các hệ điều hành khác nhau cũng có chức năng khác nhau. Windows có cổng hoàn thành I / O, Linux thì không. FreeBSD có kqueue, Linux thì không. Linux có tương lai, Windows thì không. Họ cũng có nhiều cách khác nhau để làm điều tương tự - bạn vượt qua tham số nào để mở tệp? Họ đi theo thứ tự nào? Làm thế nào cụ thể để bạn gọi chức năng "mở tệp" của hệ điều hành?
Nói chung, các chương trình không tương thích do sự khác biệt trong giao diện nhị phân ứng dụng (ABI) của chúng .
Không phải chương trình chạy trực tiếp trên CPU?
KHÔNG ! Đó là công việc của hệ điều hành, để ngăn các ứng dụng chạy "trực tiếp" trên CPU. Thông thường, ở mức thấp nhất (tức là API hệ điều hành được xây dựng), một giao diện ứng dụng với nhân của hệ điều hành .
Có phải vì bản thân chương trình đã biên dịch cần tham chiếu các thư viện cụ thể của HĐH?
Có . Nhiều thư viện hệ điều hành được viết để tạo điều kiện giao tiếp với chính hệ điều hành, nhưng cũng có nhiều thư viện được viết là đa nền tảng. Chúng ẩn hệ điều hành cấp thấp giao tiếp với nhà phát triển và giả sử phiên bản được biên dịch cho hệ điều hành đó sẽ có sẵn trong thời gian chạy (xem bên dưới).
Mặc dù các thư viện có thể được viết theo cách đa nền tảng, nhưng khi được biên dịch, chúng không thể chạy đa nền tảng. Chúng vẫn cần được biên dịch lại cho hệ điều hành đích cụ thể, một lần nữa để sử dụng các thành phần cơ bản cụ thể của hệ điều hành (kernel).
Sự khác biệt giữa một chương trình được biên dịch cho một hệ điều hành so với hệ điều hành khác là gì?
Cuối cùng, bản thân các tệp thực thi thường chứa các tiêu đề tải nhị phân rất cụ thể và tương tự (ví dụ: định dạng tệp PE Executable [.exe, đậm, v.v ...] cho Windows hoặc ELF cho Linux [none, .o, .so , Vân vân...]). Chúng cũng có thể bao gồm mã để tải các nhị phân dành riêng cho hệ điều hành được biên dịch cho một thư viện phần mềm cụ thể.
Cuối cùng, từ quan điểm của một lập trình viên: gọi quy ước . Mã được biên dịch chuyển các biến cho các hàm theo một cách nhất định (nghĩa là thông qua các thanh ghi hoặc trên ngăn xếp) theo một thứ tự rất cụ thể. Ngay cả sau đó, nó cũng cần phải được thỏa thuận khi ai chịu trách nhiệm "dọn dẹp" các cuộc gọi chức năng (người gọi hoặc callee?). Mặc dù có một số quy ước gọi x86 tiêu chuẩn và được sử dụng rộng rãi , một số có thể không được hỗ trợ bởi một số hệ điều hành nhất định (đây là một phần của ABI).