Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Giới thiệu về hệ điều hành

Này Habr! Theo quan điểm của tôi, tôi muốn giới thiệu với các bạn một loạt bài viết-bản dịch của một nền văn học thú vị - OSTEP. Tài liệu này thảo luận khá sâu về công việc của các hệ điều hành giống unix, cụ thể là làm việc với các tiến trình, các bộ lập lịch khác nhau, bộ nhớ và các thành phần tương tự khác tạo nên một hệ điều hành hiện đại. Bạn có thể xem bản gốc của tất cả các tài liệu ở đây đây. Xin lưu ý rằng bản dịch được thực hiện không chuyên nghiệp (khá tự do), nhưng tôi hy vọng tôi vẫn giữ được ý nghĩa chung.

Phòng thí nghiệm về chủ đề này có thể được tìm thấy ở đây:
- nguyên bản: pages.cs.wisc.edu/~remzi/OSTEP/Homework/homework.html
- nguyên bản: github.com/remzi-arpcidusseau/ostep-code
- sự thích ứng cá nhân của tôi: github.com/bykvaadm/OS/tree/master/ostep

Bạn cũng có thể xem kênh của tôi tại điện tín =)

Vận hành chương trình

Điều gì xảy ra khi một chương trình đang chạy? Một chương trình đang chạy thực hiện một việc đơn giản - nó thực hiện các lệnh. Mỗi giây, hàng triệu và thậm chí có thể là hàng tỷ lệnh được bộ xử lý truy xuất từ ​​RAM, lần lượt nó giải mã chúng (ví dụ: nhận ra loại lệnh này thuộc về loại nào) và thực thi chúng. Điều này có thể là cộng hai số, truy cập bộ nhớ, kiểm tra một điều kiện, chuyển sang một hàm, v.v. Sau khi hoàn thành một lệnh, bộ xử lý sẽ chuyển sang thực hiện lệnh khác. Và cứ thế, hết lệnh này đến lệnh khác, chúng được thực thi cho đến khi chương trình kết thúc.
Ví dụ này đương nhiên được xem xét một cách đơn giản - trên thực tế, để tăng tốc bộ xử lý, phần cứng hiện đại cho phép bạn thực hiện các lệnh không theo trình tự, tính toán các kết quả có thể xảy ra, thực hiện các lệnh đồng thời và các thủ thuật tương tự.

Mô hình tính toán Von Neumann

Hình thức hoạt động đơn giản hóa mà chúng tôi đã mô tả tương tự như mô hình điện toán Von Neumann. Von Neumann là một trong những người tiên phong về hệ thống máy tính, ông cũng là một trong những tác giả của lý thuyết trò chơi.. Trong khi chương trình đang chạy, một loạt các sự kiện khác diễn ra, nhiều quy trình khác và logic của bên thứ ba hoạt động, mục đích chính là đơn giản hóa việc khởi chạy, vận hành và bảo trì hệ thống.
Có một bộ phần mềm chịu trách nhiệm làm cho các chương trình dễ chạy (hoặc thậm chí cho phép nhiều chương trình chạy cùng lúc), cho phép các chương trình chia sẻ cùng một bộ nhớ và giao tiếp với các thiết bị khác nhau. Một bộ phần mềm (phần mềm) như vậy về cơ bản được gọi là hệ điều hành và các nhiệm vụ của nó bao gồm giám sát xem hệ thống có hoạt động chính xác và hiệu quả hay không, cũng như đảm bảo sự dễ dàng quản lý hệ thống này.

Hệ điều hành

Hệ điều hành, viết tắt là OS, là một tập hợp các chương trình được kết nối với nhau được thiết kế để quản lý tài nguyên máy tính và tổ chức tương tác của người dùng với máy tính..
Hệ điều hành đạt được hiệu quả chủ yếu thông qua kỹ thuật quan trọng nhất - công nghệ ảo hóa. HĐH tương tác với tài nguyên vật lý (bộ xử lý, bộ nhớ, đĩa, v.v.) và biến nó thành một dạng tổng quát hơn, có khả năng hơn và dễ sử dụng hơn. Do đó, để hiểu chung, bạn có thể so sánh một cách đại khái hệ điều hành với máy ảo.
Để cho phép người dùng đưa ra lệnh cho hệ điều hành và do đó sử dụng các khả năng của máy ảo (chẳng hạn như: chạy chương trình, cấp phát bộ nhớ, truy cập tệp, v.v.), hệ điều hành cung cấp một giao diện có tên là API (giao diện lập trình ứng dụng) và cuộc gọi có thể được thực hiện. Một hệ điều hành thông thường cho phép bạn thực hiện hàng trăm cuộc gọi hệ thống.
Cuối cùng, vì ảo hóa cho phép nhiều chương trình chạy (do đó chia sẻ CPU) và truy cập đồng thời các hướng dẫn và dữ liệu của chúng (do đó chia sẻ bộ nhớ) và truy cập vào đĩa (do đó chia sẻ thiết bị I/O) nên hệ điều hành còn được gọi là tài nguyên. giám đốc. Mỗi bộ xử lý, đĩa và bộ nhớ là một tài nguyên hệ thống và do đó, một trong những vai trò của hệ điều hành trở thành nhiệm vụ quản lý các tài nguyên này, thực hiện nó một cách hiệu quả, công bằng hoặc ngược lại, tùy thuộc vào nhiệm vụ mà hệ điều hành được thiết kế. .

Ảo hóa CPU

Xét chương trình sau:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Nó không thực hiện bất kỳ hành động đặc biệt nào; trên thực tế, tất cả những gì nó làm chỉ là gọi một hàm quay(), có nhiệm vụ kiểm tra thời gian theo chu kỳ và quay lại sau khi một giây trôi qua. Do đó, nó lặp lại vô tận chuỗi mà người dùng đã truyền làm đối số.
Hãy chạy chương trình này và truyền cho nó ký hiệu “A” làm đối số. Kết quả không có gì đặc biệt thú vị - hệ thống chỉ thực hiện một chương trình hiển thị định kỳ ký hiệu “A” trên màn hình.
Bây giờ, hãy thử tùy chọn khi nhiều phiên bản của cùng một chương trình được khởi chạy nhưng hiển thị các chữ cái khác nhau để làm cho nó rõ ràng hơn. Trong trường hợp này, kết quả sẽ hơi khác một chút. Mặc dù thực tế là chúng ta có một bộ xử lý nhưng chương trình vẫn chạy đồng thời. Nó xảy ra như thế nào? Nhưng hóa ra hệ điều hành, không phải không có sự trợ giúp của khả năng phần cứng, đã tạo ra ảo ảnh. Ảo tưởng rằng có nhiều bộ xử lý ảo trong hệ thống, biến một bộ xử lý vật lý thành một số lượng vô hạn về mặt lý thuyết và do đó cho phép các chương trình dường như chạy đồng thời. Ảo tưởng này được gọi là Ảo hóa CPU.
Bức tranh này đặt ra nhiều câu hỏi, chẳng hạn, nếu nhiều chương trình muốn chạy cùng lúc thì chương trình nào sẽ được khởi chạy? Các “chính sách” hệ điều hành chịu trách nhiệm về vấn đề này. Các chính sách được sử dụng ở nhiều nơi trong HĐH và trả lời các câu hỏi như thế này, đồng thời cũng là cơ chế cơ bản mà HĐH thực hiện. Do đó vai trò của hệ điều hành như một người quản lý tài nguyên.

Ảo hóa bộ nhớ

Bây giờ chúng ta hãy nhìn vào bộ nhớ. Mô hình vật lý của bộ nhớ trong các hệ thống hiện đại được biểu diễn dưới dạng mảng byte. Để đọc từ bộ nhớ bạn cần chỉ định địa chỉ ôđể truy cập nó. Để ghi hoặc cập nhật dữ liệu, bạn cũng phải chỉ định dữ liệu và địa chỉ của ô nơi ghi dữ liệu.
Truy cập bộ nhớ xảy ra liên tục trong quá trình thực hiện chương trình. Một chương trình lưu trữ toàn bộ cấu trúc dữ liệu của nó trong bộ nhớ và truy cập nó bằng cách thực hiện các lệnh khác nhau. Trong khi đó, các lệnh cũng được lưu trữ trong bộ nhớ nên nó cũng được truy cập đối với mỗi yêu cầu cho lệnh tiếp theo.

cuộc gọi malloc()

Hãy xem xét chương trình sau, phân bổ một vùng bộ nhớ bằng lệnh gọi malloc () (https://youtu.be/jnlKRnoT1m0):

Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Chương trình thực hiện một số việc. Đầu tiên, nó phân bổ một số bộ nhớ (dòng 7), sau đó in địa chỉ của ô được phân bổ (dòng 9), ghi số XNUMX vào khe đầu tiên của bộ nhớ được phân bổ. Tiếp theo, chương trình đi vào một vòng lặp trong đó nó tăng giá trị được lưu trong bộ nhớ tại địa chỉ của biến “p”. Nó cũng hiển thị ID tiến trình của chính nó. ID tiến trình là duy nhất cho mỗi tiến trình đang chạy. Sau khi tung ra một số bản sao, chúng ta sẽ thấy một kết quả thú vị: Trong trường hợp đầu tiên, nếu chúng ta không làm gì và chỉ tung ra một số bản sao, địa chỉ sẽ khác nhau. Nhưng điều này không thuộc lý thuyết của chúng tôi! Đúng, bởi vì các bản phân phối hiện đại đã bật tính năng ngẫu nhiên hóa bộ nhớ theo mặc định. Nếu bạn tắt nó, chúng tôi sẽ nhận được kết quả như mong đợi - địa chỉ bộ nhớ của hai chương trình đang chạy đồng thời sẽ trùng khớp.

Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Kết quả là hai chương trình độc lập hoạt động với không gian địa chỉ riêng của chúng, lần lượt được hệ điều hành ánh xạ vào bộ nhớ vật lý.. Do đó, việc sử dụng địa chỉ bộ nhớ trong một chương trình sẽ không ảnh hưởng đến các chương trình khác theo bất kỳ cách nào và mỗi chương trình dường như có một phần bộ nhớ vật lý riêng, hoàn toàn tùy ý sử dụng. Tuy nhiên, thực tế là bộ nhớ vật lý là tài nguyên dùng chung được quản lý bởi hệ điều hành.

Tính nhất quán

Một chủ đề quan trọng khác trong hệ điều hành là − Tính nhất quán. Thuật ngữ này được sử dụng khi nói về các vấn đề hệ thống có thể xảy ra khi làm việc với nhiều thứ cùng lúc trong một chương trình. Các vấn đề về tính nhất quán thậm chí còn xảy ra ngay trong chính hệ điều hành. Trong các ví dụ trước về ảo hóa bộ nhớ và bộ xử lý, chúng tôi nhận ra rằng HĐH quản lý nhiều thứ cùng lúc - khởi chạy quy trình đầu tiên, sau đó là quy trình thứ hai, v.v. Hóa ra, hành vi này có thể dẫn đến một số vấn đề. Ví dụ, các chương trình đa luồng hiện đại gặp phải những khó khăn như vậy.

Xét chương trình sau:

Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Chương trình trong hàm main tạo hai luồng bằng lệnh gọi pthread_create(). Trong ví dụ này, một luồng có thể được coi là một hàm chạy trong cùng một không gian bộ nhớ bên cạnh các hàm khác, rõ ràng là có nhiều hơn một hàm chạy cùng lúc. Trong ví dụ này, mỗi luồng khởi động và thực thi một hàm worker() mà đến lượt nó chỉ đơn giản là tăng biến,.

Hãy chạy chương trình này với đối số là 1000. Như bạn có thể đoán, kết quả sẽ là 2000, vì mỗi luồng tăng biến lên 1000 lần. Tuy nhiên, mọi thứ không đơn giản như vậy. Hãy thử chạy chương trình với số lần lặp lại nhiều hơn.

Hệ điều hành: Ba phần dễ dàng. Phần 1: Giới thiệu (bản dịch)

Bằng cách nhập một số, ví dụ 100000, chúng ta mong đợi sẽ thấy số 200000 ở đầu ra. Tuy nhiên, khi chạy số 100000 nhiều lần, chúng ta không những không nhìn thấy câu trả lời đúng mà còn nhận được các câu trả lời sai khác nhau. Câu trả lời nằm ở chỗ việc tăng một số cần ba thao tác - lấy số đó từ bộ nhớ, tăng nó lên và sau đó viết lại số đó. Vì tất cả các hướng dẫn này không được thực thi một cách nguyên tử (tất cả cùng một lúc), nên những điều kỳ lạ như thế này có thể xảy ra. Vấn đề này được gọi trong lập trình điều kiện của cuộc đua. Khi các lực không xác định tại một thời điểm không xác định có thể ảnh hưởng đến việc thực hiện bất kỳ hoạt động nào của bạn.

Nguồn: www.habr.com

Thêm một lời nhận xét