Một thực thi sẽ cần một nhân hệ điều hành để chạy?


53

Tôi biết rằng khi mã nguồn, như C ++, được biên dịch, đầu ra từ trình biên dịch là mã máy (có thể thực thi) mà tôi nghĩ là hướng dẫn trực tiếp đến CPU. Gần đây tôi đã đọc về hạt nhân và tôi phát hiện ra rằng các chương trình không thể truy cập trực tiếp vào phần cứng mà phải thông qua kernel.

Vì vậy, khi chúng tôi biên dịch một số mã nguồn đơn giản, chỉ bằng một printf()hàm và quá trình biên dịch tạo ra mã máy thực thi, mỗi lệnh trong mã máy này sẽ được thực thi trực tiếp từ bộ nhớ (một khi mã được hệ điều hành nạp vào bộ nhớ) mỗi lệnh trong mã máy vẫn cần phải đi qua HĐH (kernel) để được thực thi?

Tôi đã đọc một câu hỏi tương tự . Nó không giải thích nếu mã máy được tạo sau khi biên dịch là một lệnh trực tiếp cho CPU hoặc nếu nó sẽ cần phải đi qua kernel để tạo hướng dẫn chính xác cho CPU. Tức là, điều gì xảy ra sau khi mã máy được tải vào bộ nhớ? Nó sẽ đi qua kernel hoặc nói chuyện trực tiếp với bộ xử lý?


29
Nếu bạn đang viết mã cho Arduino, bạn không cần HĐH.
stib

12
printfkhông phải là một ví dụ tuyệt vời Nó được định nghĩa rõ ràng bởi thông số C là một hàm chỉ có sẵn trong các triển khai "được lưu trữ" (nghĩa là chạy trên kernel, trái ngược với "freestanding", có thể không yêu cầu một). Và trên hầu hết các nền tảng, printfchỉ là một chức năng được cung cấp bởi bạn libcthực hiện một loạt các công cụ thay mặt bạn (cuối cùng bao gồm một tòa nhà cao tầng để in ra thiết bị xuất chuẩn). Nó thực sự không khác gọi libvlc_media_list_add_mediahay PyObject_GetAttr, ngoại trừ một số printfthực hiện được đảm bảo có thể kết nối mà không cần bổ sung thêm phi tiêu chuẩn -ls.
abarnert

1
Điều này tồn tại! (không liên kết, chỉ nghĩ rằng nó thật tuyệt) erikyyy.de/invaders
Nonny Moose

9
Điều này thực sự phụ thuộc vào định nghĩa chính xác của bạn về các thuật ngữ "thực thi", "kernel", "chạy", "cần", "nói chuyện" và "đi qua". Không có một định nghĩa chính xác về các điều khoản đó, câu hỏi là không thể trả lời.
Jörg W Mittag

3
@ JörgWMittag - Nếu bạn sẽ trở thành người phạm tội, vậy tại sao bạn chỉ xem xét kỹ những điều khoản đó và chỉ câu hỏi này? Thuật ngữ thực sự nổi bật cần xác định là "hệ điều hành", được áp dụng một cách nghi ngờ cho MS-DOS (và các môi trường thời gian chạy tác vụ đơn tương tự). Nếu có một vài người (thông tin sai) nghĩ rằng BIOS PC là HĐH , vậy thì mọi thứ đã sẵn sàng chưa? Tôi nghĩ là không. OP sử dụng những từ đó trong ngữ cảnh có vẻ hợp lý (đặc biệt nếu người nói tiếng Anh không phải là người bản xứ) hoặc không có kỹ thuật.
mùn cưa

Câu trả lời:


86

Là một người đã viết các chương trình thực thi mà không có HĐH, tôi đưa ra một câu trả lời dứt khoát.

Một thực thi sẽ cần một nhân hệ điều hành để chạy?

Điều đó phụ thuộc vào cách chương trình đó được viết và xây dựng.
Bạn có thể viết một chương trình (giả sử bạn có kiến ​​thức) hoàn toàn không yêu cầu HĐH.
Một chương trình như vậy được mô tả là độc lập .
Bộ tải khởi động và chương trình chẩn đoán là sử dụng điển hình cho các chương trình độc lập.

Tuy nhiên, chương trình điển hình được viết và xây dựng trong một số môi trường HĐH máy chủ sẽ mặc định thực thi trong cùng môi trường HĐH máy chủ đó.
Các quyết định và hành động rất rõ ràng được yêu cầu để viết và xây dựng một chương trình độc lập.


... Đầu ra từ trình biên dịch là mã máy (có thể thực thi) mà tôi nghĩ là hướng dẫn trực tiếp đến CPU.

Chính xác.

Gần đây tôi đã đọc về hạt nhân và tôi phát hiện ra rằng các chương trình không thể truy cập trực tiếp vào phần cứng mà phải thông qua kernel.

Đó là một hạn chế được áp đặt bởi chế độ CPU mà HĐH sử dụng để thực thi các chương trình và được hỗ trợ bởi một số công cụ xây dựng nhất định như trình biên dịch và thư viện.
Nó không phải là một giới hạn nội tại trên mỗi chương trình từng được viết.


Vì vậy, khi chúng tôi biên dịch một số mã nguồn đơn giản, chỉ bằng một hàm printf () và quá trình biên dịch tạo ra mã máy thực thi, mỗi lệnh trong mã máy này sẽ được thực thi trực tiếp từ bộ nhớ (một khi mã được hệ điều hành nạp vào bộ nhớ ) hoặc mỗi lệnh trong mã máy vẫn cần phải đi qua HĐH (kernel) để được thực thi?

Mỗi lệnh được thực thi bởi CPU.
Một lệnh không được hỗ trợ hoặc bất hợp pháp (ví dụ: quá trình không có đủ đặc quyền) sẽ gây ra ngoại lệ ngay lập tức và thay vào đó, CPU sẽ thực hiện một thói quen để xử lý tình trạng bất thường này.

Không nên sử dụng hàm printf () làm ví dụ về "mã nguồn đơn giản" .
Việc dịch từ ngôn ngữ lập trình cấp cao hướng đối tượng sang mã máy có thể không tầm thường như bạn ngụ ý.
Và sau đó bạn chọn một trong những hàm phức tạp nhất từ ​​thư viện thời gian thực hiện chuyển đổi dữ liệu I / O.

Lưu ý rằng câu hỏi của bạn quy định một môi trường với HĐH (và thư viện thời gian chạy).
Khi hệ thống được khởi động và HĐH được trao quyền kiểm soát máy tính, các hạn chế được áp dụng cho những gì chương trình có thể làm (ví dụ: I / O phải được thực hiện bởi HĐH).
Nếu bạn muốn thực hiện một chương trình độc lập (tức là không có HĐH), thì bạn không được khởi động máy tính để chạy HĐH.


... Điều gì xảy ra sau khi mã máy được tải vào bộ nhớ?

Điều đó phụ thuộc vào môi trường.

Đối với một chương trình độc lập, nó có thể được thực thi, tức là điều khiển được chuyển giao bằng cách chuyển đến địa chỉ bắt đầu của chương trình.

Đối với một chương trình được tải bởi HĐH, chương trình phải được liên kết động với các thư viện dùng chung mà nó phụ thuộc vào. HĐH phải tạo một không gian thực thi cho quá trình sẽ thực thi chương trình.

Nó sẽ đi qua kernel hoặc nói chuyện trực tiếp với bộ xử lý?

Mã máy được thực thi bởi CPU.
Họ không "đi qua kernel" , nhưng họ cũng không "nói chuyện với bộ xử lý" .
Mã máy (bao gồm mã op và toán hạng) là một lệnh cho CPU được giải mã và thao tác được thực hiện.

Có lẽ chủ đề tiếp theo bạn nên điều tra là chế độ CPU .


2
"Nếu bạn muốn thực hiện một chương trình độc lập (tức là không có HĐH), thì bạn không được khởi động máy tính để chạy HĐH." không hoàn toàn chính xác Nhiều chương trình DOS đã được tải sau DOS và sau đó hoàn toàn bỏ qua các dịch vụ DOS (bằng cách đập trực tiếp hoặc có thể gọi BIOS trực tiếp). Win3.x là một ví dụ tuyệt vời mà (ngoại trừ trong một số trường hợp góc thú vị) đã bỏ qua rằng DOS đã có mặt. Win95 / 98 / Me cũng đã làm điều này. Có nhiều ví dụ về các HĐH hỗ trợ các chương trình độc lập, nhiều ví dụ từ thời 8-16-bit.
Tháp Eric

8
@EricTowers - Bởi "DOS" có lẽ bạn có nghĩa là MS-DOS (vì tôi đã sử dụng DOS không liên quan đến MS hoặc Intel)? Bạn đang trích dẫn một "HĐH" thậm chí không phù hợp với tiêu chí của sách giáo khoa đại học năm 1970 của tôi về các khái niệm và thiết kế hệ điều hành. Nguồn gốc của MS-DOS truy nguyên (thông qua các sản phẩm máy tính của Seattle) thành CP / M, rõ ràng không được gọi là HĐH bởi tác giả Gary Kildall. FWIW một hệ điều hành cho phép một chương trình tiếp quản hệ thống đã thất bại trong chức năng cơ bản là quản lý tài nguyên hệ thống. "Có nhiều ví dụ về HĐH hỗ trợ các chương trình độc lập" - "Hỗ trợ" hay không thể ngăn chặn?
mùn cưa

5
... hoặc ProDOS hoặc PC-DOS hoặc DR-DOS hoặc CBM DOS hoặc TRS DOS hoặc FLEX ...
Eric Towers

3
Tôi thích thuật ngữ "tự do" của GCC. Từ tiếng Anh có tất cả các ý nghĩa đúng cho mã chạy mà không cần hệ điều hành, thậm chí có thể tốt hơn "độc lập". ví dụ: bạn có thể biên dịch gcc -O2 -ffreestanding my_kernel.c special_sauce.Sđể tạo một tệp thực thi mà không giả sử bất kỳ thư viện hoặc hệ điều hành bình thường nào sẽ ở đó. (Tất nhiên, thông thường bạn sẽ cần một tập lệnh liên kết để đưa nó vào liên kết hữu ích thành định dạng tệp mà bộ tải khởi động sẽ muốn tải!)
Peter Cordes

4
@PeterCordes "độc lập" là thuật ngữ được sử dụng trong tiêu chuẩn C mà IMO có thể được coi là có thẩm quyền. Ngoài ra, một thuật ngữ tốt cũng là "không được lưu trữ" (như được lưu trữ bởi HĐH)
Jan Dorniak

38

Hạt nhân là "chỉ" thêm mã. Chỉ có mã đó là một lớp nằm giữa các phần thấp nhất trong hệ thống của bạn và phần cứng thực tế.

Tất cả đều chạy trực tiếp trên CPU, bạn chỉ cần chuyển qua các lớp của nó để làm bất cứ điều gì.

Chương trình của bạn "cần" kernel giống như cách nó cần các thư viện C tiêu chuẩn để sử dụng printflệnh ở vị trí đầu tiên.

Mã thực tế của chương trình của bạn chạy trên CPU, nhưng các nhánh mà mã tạo ra để in một cái gì đó trên màn hình đi qua mã cho printfchức năng C , thông qua các hệ thống và trình thông dịch khác nhau, mỗi hệ thống sẽ tự xử lý để xử lý như thế nào hello world! thực sự được in trên màn hình của bạn.

Giả sử bạn có một chương trình đầu cuối đang chạy trên trình quản lý cửa sổ máy tính để bàn, chạy trên kernel của bạn, lần lượt nó đang chạy trên phần cứng của bạn.

Còn nhiều điều nữa đang diễn ra nhưng hãy làm cho nó đơn giản ...

  1. Trong chương trình thiết bị đầu cuối của bạn, bạn chạy chương trình của bạn để in hello world!
  2. Thiết bị đầu cuối thấy rằng chương trình đã được ghi (thông qua các thường trình đầu ra C) hello world!đến bàn điều khiển
  3. Chương trình thiết bị đầu cuối đi lên cho người quản lý cửa sổ máy tính để bàn nói: "Tôi đã hello world!viết vào tôi, bạn có thể đặt nó ở vị trí x, yxin vui lòng?"
  4. Trình quản lý cửa sổ máy tính để bàn đi lên kernel với "một trong những chương trình của tôi muốn thiết bị đồ họa của bạn đặt một số văn bản ở vị trí này, hãy đến với nó!"
  5. Hạt nhân chuyển yêu cầu ra trình điều khiển thiết bị đồ họa, định dạng nó theo cách mà card đồ họa có thể hiểu
  6. Tùy thuộc vào cách kết nối card đồ họa, các trình điều khiển thiết bị kernel khác cần được gọi để đẩy dữ liệu ra trên các bus thiết bị vật lý như PCIe, xử lý những việc như đảm bảo chọn đúng thiết bị và dữ liệu có thể đi qua cầu nối có liên quan hoặc bộ chuyển đổi
  7. Các phần cứng hiển thị công cụ.

Đây là một sự đơn giản hóa lớn chỉ để mô tả. Đây là những con rồng.

Một cách hiệu quả tất cả mọi thứ bạn làm điều đó cần truy cập phần cứng, có thể là hiển thị, các khối bộ nhớ, bit của file hoặc bất cứ điều gì như thế phải trải qua một số điều khiển thiết bị trong hạt nhân để làm việc ra chính xác như thế nào để nói chuyện với các thiết bị có liên quan. Có thể là trình điều khiển hệ thống tập tin bên trên trình điều khiển bộ điều khiển đĩa cứng SATA, chính nó đang ngồi trên thiết bị cầu PCIe.

Nhân biết cách kết nối tất cả các thiết bị này lại với nhau và trình bày một giao diện tương đối đơn giản để các chương trình thực hiện mọi việc mà không cần phải biết cách tự làm tất cả những điều này.

Trình quản lý cửa sổ máy tính để bàn cung cấp một lớp có nghĩa là các chương trình không phải biết cách vẽ các cửa sổ và chơi tốt với các chương trình khác đang cố gắng hiển thị mọi thứ cùng một lúc.

Cuối cùng, chương trình đầu cuối có nghĩa là chương trình của bạn không cần biết cách vẽ cửa sổ, cũng như cách nói chuyện với trình điều khiển card đồ họa kernel, cũng không phải tất cả sự phức tạp để xử lý bộ đệm màn hình và hiển thị thời gian và thực sự làm lung lay dòng dữ liệu để hiển thị.

Tất cả được xử lý bởi các lớp trên các lớp mã.


Không chỉ truy cập phần cứng , hầu hết giao tiếp giữa các chương trình cũng đi qua kernel; mà thường không liên quan đến ít nhất là kernel đang thiết lập một kênh trực tiếp hơn. Tuy nhiên, đối với mục đích của câu hỏi, cũng có thể và thực hành trong các trường hợp đơn giản hơn nhiều để cô đọng tất cả mã vào một chương trình.
Chris Stratton

Thật vậy, chương trình thiết bị đầu cuối của bạn thậm chí không phải chạy trên cùng một máy như chương trình đang viết nội dung đó.
jamesqf

Vì có thể cần phải được tuyên bố rõ ràng trong câu hỏi này - xin lưu ý rằng khi chúng ta nói về các chương trình "nói chuyện" với nhau, điều đó thật ẩn dụ.
dùng253751

21

Nó phụ thuộc vào môi trường. Trong nhiều máy tính cũ hơn (và đơn giản hơn!), Như IBM 1401, câu trả lời sẽ là "không". Trình biên dịch và trình liên kết của bạn đã phát ra một "nhị phân" độc lập chạy mà không cần bất kỳ hệ điều hành nào. Khi chương trình của bạn ngừng chạy, bạn đã tải một chương trình khác, cũng chạy không có HĐH.

Cần có một hệ điều hành trong các môi trường hiện đại vì bạn không chỉ chạy một chương trình một lần. Chia sẻ (các) lõi CPU, RAM, thiết bị lưu trữ dung lượng lớn, bàn phím, chuột và màn hình, giữa nhiều chương trình cùng một lúc cần có sự phối hợp. HĐH cung cấp điều đó. Vì vậy, trong một môi trường hiện đại, chương trình của bạn không thể chỉ đọc và ghi đĩa hoặc SSD, nó phải yêu cầu HĐH thực hiện việc đó thay mặt nó. HĐH nhận được các yêu cầu như vậy từ tất cả các chương trình muốn truy cập thiết bị lưu trữ, thực hiện về những thứ như điều khiển truy cập (không thể cho phép người dùng thông thường ghi vào tệp của HĐH), xếp hàng chúng vào thiết bị và sắp xếp thông tin trả về để các chương trình (quy trình) chính xác.

Ngoài ra, các máy tính hiện đại (không giống như, 1401) hỗ trợ kết nối rất nhiều thiết bị I / O, không chỉ các thiết bị IBM sẽ bán cho bạn trong những ngày xưa. Trình biên dịch và trình liên kết của bạn không thể biết về tất cả các khả năng. Ví dụ: bàn phím của bạn có thể được giao tiếp qua PS / 2 hoặc USB. HĐH cho phép bạn cài đặt các "trình điều khiển thiết bị" dành riêng cho thiết bị, biết cách nói chuyện với các thiết bị đó, nhưng trình bày một giao diện chung cho lớp thiết bị cho HĐH. Vì vậy, chương trình của bạn và thậm chí cả HĐH không phải làm bất cứ điều gì khác biệt khi nhận tổ hợp phím từ USB so với bàn phím PS / 2 hoặc để truy cập, giả sử, đĩa SATA cục bộ so với thiết bị lưu trữ USB so với thiết bị lưu trữ bị tắt trên NAS hoặc SAN. Những chi tiết này được xử lý bởi trình điều khiển thiết bị cho các bộ điều khiển thiết bị khác nhau.

Đối với các thiết bị lưu trữ dung lượng lớn, HĐH cung cấp trên tất cả các trình điều khiển hệ thống tệp có cùng giao diện với các thư mục và tệp bất kể vị trí và cách thức lưu trữ được thực hiện. Và một lần nữa, HĐH lo lắng về kiểm soát truy cập và tuần tự hóa. Nói chung, ví dụ, cùng một tệp không nên được mở để ghi bởi nhiều chương trình cùng một lúc mà không nhảy qua một số vòng (nhưng đọc đồng thời thường ổn).

Vì vậy, trong một môi trường đa năng hiện đại, vâng - bạn thực sự cần một hệ điều hành. Nhưng ngay cả ngày nay cũng có những máy tính như bộ điều khiển thời gian thực không đủ phức tạp để cần đến nó.

Trong môi trường Arduino, chẳng hạn, thực sự không có HĐH. Chắc chắn, có một loạt mã thư viện mà môi trường xây dựng kết hợp vào mọi "nhị phân" mà nó xây dựng. Nhưng vì không có sự tồn tại của mã đó từ chương trình này sang chương trình tiếp theo, nên nó không phải là một hệ điều hành.


10

Tôi nghĩ rằng nhiều câu trả lời hiểu sai câu hỏi, điều này dẫn đến vấn đề này:

Một trình biên dịch xuất mã máy. Là mã máy này được thực thi trực tiếp bởi CPU, hay nó được "giải thích" bởi kernel?

Về cơ bản, CPU trực tiếp thực thi mã máy . Nó sẽ chậm hơn đáng kể để kernel thực thi tất cả các ứng dụng. Tuy nhiên, có một vài cảnh báo.

  1. Khi có một hệ điều hành, các chương trình ứng dụng thường bị hạn chế thực hiện các hướng dẫn nhất định hoặc truy cập vào một số tài nguyên nhất định. Ví dụ, nếu một ứng dụng thực thi một lệnh sửa đổi bảng ngắt hệ thống, thay vào đó CPU sẽ chuyển sang một trình xử lý ngoại lệ của hệ điều hành để ứng dụng vi phạm bị chấm dứt. Ngoài ra, các ứng dụng thường không được phép đọc / ghi vào bộ nhớ thiết bị. (Tức là "nói chuyện với phần cứng".) Truy cập các vùng nhớ đặc biệt này là cách HĐH giao tiếp với các thiết bị như card đồ họa, giao diện mạng, đồng hồ hệ thống, v.v.

  2. Các hạn chế mà hệ điều hành đặt trên các ứng dụng đạt được bằng các tính năng đặc biệt của CPU, chẳng hạn như chế độ đặc quyền, bảo vệ bộ nhớ và ngắt. Mặc dù bất kỳ CPU nào bạn tìm thấy trong điện thoại thông minh hoặc PC đều có các tính năng này, một số CPU nhất định thì không. Những CPU này thực sự cần hạt nhân đặc biệt "diễn giải" mã ứng dụng để đạt được các tính năng mong muốn. Một ví dụ rất thú vị là Gigatron , đây là một máy tính 8 lệnh mà bạn có thể tạo ra từ các chip mô phỏng máy tính 34 lệnh.

  3. Một số ngôn ngữ như Java "biên dịch" thành thứ gọi là Bytecode, không thực sự là mã máy. Mặc dù trước đây, chúng được hiểu là chạy các chương trình, ngày nay, một thứ gọi là biên dịch đúng lúc thường được sử dụng để cuối cùng chúng chạy trực tiếp trên CPU dưới dạng mã máy.

  4. Chạy phần mềm trong Máy ảo được sử dụng để yêu cầu mã máy của nó được "diễn giải" bởi một chương trình có tên là Hypervisor . Do nhu cầu rất lớn về máy ảo, các nhà sản xuất CPU đã thêm các tính năng như VTx vào CPU của họ để cho phép hầu hết các hướng dẫn của hệ thống khách được CPU thực thi trực tiếp. Tuy nhiên, khi chạy phần mềm được thiết kế cho CPU không tương thích trong Máy ảo (ví dụ: mô phỏng NES), mã máy sẽ cần được giải thích.


1
Mặc dù mã byte của Java thường không phải là mã máy, nhưng vẫn tồn tại các bộ xử lý Java .
Ruslan

Hypervisors chưa bao giờ luôn là thông dịch viên. Tất nhiên, việc giải thích là cần thiết nếu máy ảo như một tập lệnh không tương thích với máy chủ của nó, nhưng để thực hiện cùng kiến ​​trúc, ngay cả các trình ảo hóa sớm cũng thực thi mã trực tiếp trên CPU (bạn có thể bị nhầm lẫn bởi sự cần thiết của các nhân bị ảo hóa, đối với CPU mà không có sự hỗ trợ của trình ảo hóa cần thiết).
Toby Speight

5

Khi bạn biên dịch mã của mình, bạn tạo mã được gọi là mã "đối tượng" (trong hầu hết các trường hợp) phụ thuộc vào thư viện hệ thống ( printfví dụ), sau đó mã của bạn được bọc bởi trình liên kết sẽ thêm loại trình tải chương trình mà hệ điều hành cụ thể của bạn có thể nhận ra (đó là lý do tại sao bạn không thể chạy chương trình được biên dịch cho Windows trên Linux chẳng hạn) và biết cách mở khóa mã của bạn và thực thi. Vì vậy, chương trình của bạn là một phần thịt bên trong bánh sandwich và chỉ có thể được ăn dưới dạng một bó.

Gần đây tôi đã đọc về Kernels và tôi phát hiện ra rằng các chương trình không thể truy cập trực tiếp vào phần cứng mà phải thông qua kernel.

Vâng, đó là một nửa sự thật; nếu chương trình của bạn là trình điều khiển chế độ kernel thì thực sự bạn có thể truy cập trực tiếp vào phần cứng nếu bạn biết cách "nói chuyện" với phần cứng, nhưng thông thường (đặc biệt đối với phần cứng không có giấy tờ hoặc phức tạp) mọi người sử dụng trình điều khiển là thư viện kernel. Bằng cách này, bạn có thể tìm thấy các hàm API biết cách nói chuyện với phần cứng theo cách gần như dễ đọc của con người mà không cần biết địa chỉ, thanh ghi, thời gian và hàng loạt thứ khác.

mỗi lệnh trong mã máy này sẽ được thực thi trực tiếp từ bộ nhớ (một khi mã được hệ điều hành nạp vào bộ nhớ) hoặc mỗi lệnh trong mã máy vẫn cần phải đi qua HĐH (kernel) để được thực thi

Chà, hạt nhân là một cô hầu bàn, có trách nhiệm dẫn bạn đến một cái bàn và phục vụ bạn. Điều duy nhất nó không thể làm - đó là ăn cho bạn, bạn nên tự làm điều đó. Tương tự với mã của bạn, kernel sẽ giải nén chương trình của bạn vào bộ nhớ và sẽ khởi động mã của bạn là mã máy được CPU thực thi trực tiếp. Một hạt nhân chỉ cần giám sát bạn - những gì bạn được phép và những gì bạn không được phép làm.

Nó không giải thích nếu mã máy được tạo sau khi biên dịch là lệnh trực tiếp cho CPU hay nó sẽ cần phải đi qua kernel để tạo hướng dẫn chính xác cho CPU?

Mã máy được tạo sau khi biên dịch là hướng dẫn trực tiếp tới CPU. Không có nghi ngờ về điều đó. Điều duy nhất bạn cần ghi nhớ, không phải tất cả mã trong tệp được biên dịch đều là mã CPU / máy thực tế. Trình liên kết bao bọc chương trình của bạn với một số dữ liệu meta mà chỉ kernel có thể hiểu, như một manh mối - phải làm gì với chương trình của bạn.

Điều gì xảy ra sau khi mã máy được tải vào bộ nhớ? Nó sẽ đi qua kernel hoặc nói chuyện trực tiếp với bộ xử lý.

Nếu mã của bạn chỉ là các mã đơn giản như thêm hai thanh ghi thì nó sẽ được CPU thực thi trực tiếp mà không cần hỗ trợ kernel, nhưng nếu mã của bạn sử dụng các hàm từ thư viện thì các cuộc gọi đó sẽ được hỗ trợ bởi kernel, ví dụ như với Waitress, nếu bạn muốn để ăn trong một nhà hàng họ sẽ cung cấp cho bạn một công cụ - nĩa, muỗng (và nó vẫn là tài sản của họ) nhưng bạn sẽ làm gì với nó, - đó là "mã" của bạn.

Chà, chỉ để ngăn chặn ngọn lửa trong các bình luận - đó là mô hình thực sự quá đơn giản mà tôi hy vọng sẽ giúp OP hiểu những điều cơ bản, nhưng những đề xuất tốt để cải thiện câu trả lời này rất đáng hoan nghênh.


3

Vì vậy, khi chúng tôi biên dịch mã nguồn đơn giản, chỉ bằng hàm printf () và quá trình biên dịch tạo ra mã máy thực thi, mỗi lệnh trong mã máy này sẽ được thực thi trực tiếp từ bộ nhớ (khi mã được nạp vào bộ nhớ bởi HĐH) hoặc mỗi lệnh trong mã máy vẫn cần phải đi qua HĐH (kernel) để được thực thi?

Về cơ bản, chỉ có các cuộc gọi hệ thống đi đến kernel. Bất cứ điều gì để làm với I / O hoặc phân bổ / giải quyết bộ nhớ thường dẫn đến một cuộc gọi hệ thống. Một số hướng dẫn chỉ có thể được thực thi trong chế độ kernel và sẽ khiến CPU kích hoạt ngoại lệ. Các ngoại lệ gây ra sự chuyển đổi sang chế độ kernel và chuyển sang mã kernel.

Nhân không xử lý mọi lệnh trong chương trình. Nó chỉ thực hiện hệ thống gọi và chuyển đổi giữa các chương trình đang chạy để chia sẻ CPU.

Không thể cấp phát bộ nhớ ở chế độ người dùng (không có kernel), nếu bạn truy cập bộ nhớ, bạn không có quyền truy cập, MMU, được lập trình trước bởi kernel, thông báo và gây ra ngoại lệ "lỗi phân đoạn" ở cấp độ CPU , kích hoạt kernel và kernel giết chương trình.

Không thể thực hiện I / O ở chế độ người dùng (không có kernel), nếu bạn truy cập các cổng I / O hoặc thanh ghi cho thiết bị hoặc địa chỉ được kết nối với thiết bị (một hoặc cả hai cần thiết để thực hiện bất kỳ I / O nào), những điều này sẽ kích hoạt ngoại lệ theo cùng một cách.


Một thực thi sẽ cần một nhân hệ điều hành để chạy?

Phụ thuộc vào loại thực thi.

Kernels, ngoài việc trung gian truy cập chia sẻ vào RAM và phần cứng, còn thực hiện chức năng tải.

Nhiều "định dạng thực thi", như ELF hoặc PE, có siêu dữ liệu trong tệp thực thi cùng với mã và công việc của trình tải để xử lý điều đó. Đọc thông tin chi tiết về định dạng PE của Microsoft để biết thêm thông tin.

Các tệp thực thi này cũng tham chiếu các thư viện ( tệp .dllđối tượng dùng chung Windows hoặc Linux .so) - mã của chúng phải được đưa vào.

Nếu trình biên dịch của bạn tạo ra một tệp có nghĩa là được xử lý bởi trình tải hệ điều hành và trình tải đó không có ở đó, thì nó sẽ không hoạt động.

  • Bạn có thể bao gồm mã làm công việc của trình tải không?

Chắc chắn rồi. Bạn cần thuyết phục HĐH bằng cách nào đó chạy mã thô của bạn mà không xử lý bất kỳ siêu dữ liệu nào. Nếu mã của bạn gọi API kernel, nó vẫn không hoạt động.

  • Điều gì xảy ra nếu nó không gọi API kernel?

Nếu bạn tải tệp thực thi này bằng cách nào đó từ một hệ điều hành bằng cách nào đó (nghĩa là nếu nó cho phép mã thô được tải và thực thi), thì nó vẫn sẽ ở chế độ người dùng. Nếu mã của bạn truy cập vào những thứ bị cấm trong chế độ người dùng, trái với chế độ kernel, chẳng hạn như bộ nhớ / địa chỉ / bộ đăng ký thiết bị I / O, nó sẽ gặp sự cố với vi phạm đặc quyền hoặc phân đoạn (một lần nữa, ngoại lệ chuyển sang chế độ kernel và được xử lý ở đó) và vẫn không hoạt động.

  • Điều gì nếu bạn chạy nó từ chế độ kernel.

Sau đó, nó sẽ làm việc.



Đây không phải là hoàn toàn chính xác. Yêu cầu truy cập phần cứng phải thông qua kernel, hoặc thậm chí kernel, là một quyết định thiết kế được đưa ra trong khẳng định trên nhiều hệ thống ngày nay, nhưng cũng được đưa ra theo cách tiêu cực (thậm chí cho đến ngày nay) trên nhiều hệ thống đơn giản.
Chris Stratton

Tôi đang giải thích mọi thứ sẽ thế nào nếu A) có kernel và B) nếu bạn đang chạy mã trên CPU với chế độ người dùng / người giám sát và MMU để giúp thực thi điều đó. Có, có CPU và bộ vi điều khiển không có MMU hoặc chế độ người dùng / người giám sát, và có một số hệ thống chạy mà không sử dụng toàn bộ cơ sở hạ tầng người dùng / người giám sát. Xbox đầu tiên của Microsoft là như thế này - mặc dù CPU x86 tiêu chuẩn có chế độ người dùng / người giám sát, từ những gì tôi hiểu nó không bao giờ rời khỏi chế độ kernel - trò chơi được tải có thể làm bất cứ điều gì nó muốn.
LawrenceC

1
Hệ thống Macintosh, trước MacOS X, là hệ điều hành của máy tính đa năng , chạy trên CPU đa năng (họ 68000, PowerPC) có hỗ trợ bảo vệ bộ nhớ trong nhiều thập kỷ (ngoại trừ 68000 máy tính dựa trên đầu tiên tôi nghĩ) không bao giờ sử dụng bảo vệ bộ nhớ : bất kỳ chương trình nào cũng có thể truy cập mọi thứ trong bộ nhớ.
tò mò

3

TL; DR số

Phát triển Arduino đến với tâm trí như một môi trường hiện tại nơi không có HĐH. Tin tôi đi, với một trong những đứa trẻ này bạn không có không gian cho một hệ điều hành.

Tương tự, các trò chơi cho Sega Genesis không có hệ điều hành do Sega cung cấp để gọi. Bạn chỉ cần tạo trò chơi của mình trong trình biên dịch 68K, viết trực tiếp lên kim loại trần.

Hoặc nơi tôi cắt răng, thực hiện công việc nhúng trên Intel 8051. Một lần nữa khi tất cả những gì bạn có là một eprom 2716 với dấu chân 2k * 8, bạn không có chỗ cho hệ điều hành.

Tất nhiên, điều này giả định việc sử dụng ứng dụng từ rất rộng. Là một câu hỏi tu từ, bạn nên tự hỏi liệu bản phác thảo Arduino có thực sự là một ứng dụng không.


3

Mặc dù tôi không muốn ám chỉ rằng các câu trả lời khác không đúng, nhưng chúng cung cấp quá nhiều chi tiết mà tôi sợ, vẫn còn rất mơ hồ đối với bạn.

Câu trả lời cơ bản là mã sẽ được thực thi trực tiếp trên bộ xử lý. Và không, mã máy sẽ không "nói chuyện" với bất kỳ ai, đó là cách khác. Bộ xử lý là thành phần hoạt động và mọi thứ bạn làm trong máy tính của bạn sẽ được bộ xử lý đó thực hiện (Tôi đang đơn giản hóa mọi thứ một chút ở đây nhưng hiện tại vẫn ổn). Bộ xử lý sẽ đọc mã và thực thi nó và đưa ra kết quả, mã máy chỉ là thức ăn cho bộ xử lý.

Sự nhầm lẫn của bạn bắt nguồn từ việc sử dụng phần cứng từ. Mặc dù sự phân chia không rõ ràng như trước đây, nhưng sẽ tốt hơn nếu bạn nghĩ về các thiết bị ngoại vi thay vì chỉ đơn giản gọi mọi thứ là phần cứng. Vì vậy, nếu có một hệ điều hành hoặc tương tự trên máy của bạn, chương trình của bạn phải sử dụng các dịch vụ của nó để truy cập các thiết bị ngoại vi nhưng bản thân bộ xử lý không phải là thiết bị ngoại vi, đó là bộ xử lý chính mà chương trình của bạn chạy trực tiếp.

Kernels, hệ điều hành và các lớp can thiệp tương tự thường chỉ được sử dụng trong các hệ thống lớn hơn, nơi có kỳ vọng rằng một số chương trình sẽ chạy và cần có hệ thống để quản lý cách các chương trình này có thể sử dụng các thiết bị ngoại vi của máy tính (khá thường xuyên tại cùng thời gian). Trong những trường hợp này, các chương trình đang chạy chỉ có thể truy cập các thiết bị ngoại vi này bằng hệ thống sẽ quyết định cách chia sẻ chúng và sẽ đảm bảo không có xung đột. Các hệ thống nhỏ không cần quản lý giữa các chương trình cạnh tranh vì không có hệ thống nào, thường không có hệ thống cơ bản nào cả và chương trình duy nhất thường chạy trên các hệ thống này ít nhiều có thể tự do làm bất cứ điều gì nó muốn với các thiết bị ngoại vi.


2

BIOS chạy trong máy tính của bạn khi bật nguồn là mã thực thi được lưu trữ trong ROM. Nó bao gồm các hướng dẫn máy cộng với dữ liệu. Có một trình biên dịch (hoặc trình biên dịch) lắp ráp BIOS này từ mã nguồn. Đây là một trường hợp đặc biệt.

Các trường hợp đặc biệt khác bao gồm chương trình bootstrap tải kernel và kernel. Những trường hợp đặc biệt này thường được mã hóa bằng một ngôn ngữ khác ngoài C ++.

Trong trường hợp chung, trình biên dịch sẽ tạo ra một số lệnh thực hiện các dịch vụ hệ thống được cung cấp bởi kernel hoặc theo thói quen của thư viện. Nó làm cho trình biên dịch nhẹ hơn nhiều. Nó cũng làm cho mã biên dịch nhẹ hơn.

Ở đầu kia của phổ là Java. Trong Java, trình biên dịch không dịch mã nguồn thành các lệnh máy, vì thuật ngữ này thường được hiểu. Thay vào đó, mã nguồn được dịch thành "hướng dẫn máy" cho một máy ảo, được gọi là Máy ảo Java. Trước khi một chương trình Java có thể chạy, nó phải được kết hợp với thời gian chạy Java, bao gồm một trình thông dịch cho Máy ảo Java.


2

Ngày xưa, chương trình của bạn chịu trách nhiệm thực hiện mọi việc cần làm trong quá trình thực thi chương trình của bạn, bằng cách bạn tự làm hoặc bằng cách thêm mã thư viện mà người khác đã viết vào chương trình của bạn. Điều duy nhất chạy bên cạnh đó trong máy tính là mã để đọc trong chương trình được biên dịch của bạn - nếu bạn may mắn. Một số máy tính phải nhập mã thông qua các công tắc trước khi có thể thực hiện nhiều hơn (quy trình "bootstrap" ban đầu) hoặc thậm chí toàn bộ chương trình của bạn đã nhập theo cách này.

Nó đã nhanh chóng nhận thấy rằng thật tuyệt khi có mã chạy có khả năng tải và thực thi chương trình. Sau đó, người ta thấy rằng các máy tính đủ mạnh để hỗ trợ chạy một số chương trình cùng một lúc bằng cách chuyển đổi CPU giữa chúng, đặc biệt là nếu phần cứng có thể giúp đỡ, nhưng với sự phức tạp thêm của các chương trình không phải là bước trên các ngón chân khác (ví dụ , làm thế nào để xử lý nhiều chương trình cố gắng gửi dữ liệu đến máy in cùng một lúc?).

Tất cả điều này dẫn đến một lượng lớn mã trình trợ giúp được chuyển ra khỏi các chương trình riêng lẻ và vào "hệ điều hành", với một cách tiêu chuẩn hóa để gọi mã trình trợ giúp từ các chương trình người dùng.

Và đó là nơi chúng ta có ngày hôm nay. Các chương trình của bạn chạy tốc độ tối đa nhưng bất cứ khi nào chúng cần thứ gì đó được quản lý bởi hệ điều hành, chúng gọi các thói quen của trình trợ giúp do hệ điều hành cung cấp và mã đó không cần thiết và không có trong chính các chương trình người dùng. Điều này bao gồm ghi vào màn hình, lưu tệp, truy cập mạng, v.v.

Microkernels đã được viết chỉ cung cấp những gì cần thiết cho một chương trình nhất định để chạy mà không cần hệ điều hành đầy đủ. Điều này có một số lợi thế cho người dùng có kinh nghiệm trong khi cho đi hầu hết những người khác. Bạn có thể muốn đọc trang Wikipedia về nó - https://en.wikipedia.org/wiki/Microkernel - nếu bạn muốn biết thêm.

Tôi đã thử nghiệm với một Microkernel có khả năng chạy Máy ảo Java, nhưng sau đó phát hiện ra rằng điểm ngọt ngào đó là Docker.


1

Trong hệ điều hành máy tính để bàn thông thường, các hạt nhân riêng của mình là một thực thi. (Windows có ntoskrnl.exe; Linux có vmlinux, v.v.) Nếu bạn cần một hạt nhân để có thể chạy được, thì những HĐH đó không thể tồn tại.

Những gì bạn cần một kernel là làm những việc mà kernel làm. Cho phép nhiều thực thi chạy cùng một lúc, trọng tài giữa chúng, trừu tượng hóa phần cứng, v.v. Hầu hết các chương trình không có khả năng tự thực hiện công cụ đó một cách thành thạo và bạn sẽ không muốn chúng ngay cả khi chúng có thể. Vào thời của DOS - thứ mà hầu như không thể gọi là hệ điều hành - các trò chơi thường sử dụng HĐH ít hơn một bộ tải và truy cập trực tiếp vào phần cứng giống như kernel. Nhưng bạn thường phải biết những thương hiệu và kiểu phần cứng nào trong máy của bạn trước khi bạn mua một trò chơi. Nhiều trò chơi chỉ hỗ trợ một số họ video và card âm thanh nhất định và hoạt động rất kém đối với các thương hiệu cạnh tranh nếu chúng hoạt động tốt. Cái đó'

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.