Những chủ đề chia sẻ chung?


20

Vâng, đây là câu hỏi chung. Và nếu bất cứ ai muốn làm cho nó thực hiện cụ thể thì tôi sẽ thích những thứ liên quan đến Unix. Nhưng trước tiên cần biết các vấn đề sau đây trong tổng quát:

Tôi đọc quá trình duy nhất có thể có nhiều chủ đề. Nhiều chủ đề của cùng một quá trình không chia sẻ những thứ giữa chúng. Tôi muốn biết những gì họ chia sẻ và những gì không. Xem xét quá trình bao gồm không gian địa chỉ, ngăn xếp, heap, biến toàn cục, mã, dữ liệu, tài nguyên hệ điều hành, những gì trong số chúng được chia sẻ bởi các chủ đề? Tôi có những phỏng đoán sau:

  1. Biến toàn cầu - Tôi đã đọc chủ đề chia sẻ biến toàn cầu. Ngoài ra, trong khi lập trình bằng Java và C #, tôi đã tạo các luồng để chia sẻ các biến cấp độ lớp. Vì vậy, tôi tin rằng các luồng chia sẻ các biến toàn cục (mặc dù không chắc liệu các khái niệm trong ngôn ngữ lập trình cấp cao có dịch như là các sự kiện ở cấp hệ điều hành thấp hay không).

  2. Heap - Vì biến toàn cục được lưu trữ trong heap, heap được chia sẻ giữa các luồng.

  3. Ngăn xếp - Vì mỗi luồng có thể có chuỗi / mã thực thi riêng, nên nó phải có ngăn xếp riêng mà trên đó nó có thể đẩy / bật nội dung bộ đếm chương trình của nó (khi nói hàm gọi và trả về xảy ra). Vì vậy, các chủ đề của cùng một quá trình không chia sẻ ngăn xếp.

Bây giờ tôi không chắc về việc chia sẻ những điều sau đây

  1. Không gian địa chỉ - Không chắc chắn chính xác những gì được tính trong không gian địa chỉ. Nhưng tôi đoán không gian địa chỉ thường được sử dụng trong bối cảnh của các quy trình, không phải các luồng. Và vì tất cả các luồng của cùng một tiến trình nằm trong cùng một không gian địa chỉ với tiến trình cha, nên người ta nói rằng các luồng chia sẻ không gian địa chỉ. (Nhưng sau đó họ duy trì ngăn xếp khác nhau trong cùng một không gian địa chỉ?)

  2. Tài nguyên hệ điều hành - Tôi đoán điều này có thể được thực hiện rất cụ thể. Ví dụ, quá trình cha mẹ có thể chọn lọc đưa ra xử lý cùng một tệp cho một số luồng của nó và không phải cho tất cả. Hoặc tôi đang nhầm lẫn và tài nguyên hệ điều hành có nghĩa là một cái gì đó khác với các tập tin?

  3. Mã - Chủ đề có thể có mã khác nhau, vì vậy mã chia sẻ không phải lúc nào cũng như vậy.

  4. Dữ liệu - Không chắc chắn về những gì cần xem xét theo dữ liệu. Nhưng chắc chắn rằng các biến toàn cục được chia sẻ giữa các chủ đề. Và chắc chắn rằng các biến cục bộ không được chia sẻ tương tự.

Nhìn chung, tôi rất bối rối do các điều khoản mơ hồ, các khái quát siêu thực được thực hiện trong sách Hệ điều hành và các chi tiết cụ thể được triển khai thêm được cung cấp trực tuyến. Vì vậy, tôi đang cố gắng tìm một số câu trả lời có thể đáp ứng cho tôi.

Câu trả lời:


13

Nói chung, mỗi luồng có các thanh ghi riêng (bao gồm bộ đếm chương trình riêng), con trỏ ngăn xếp riêng và ngăn xếp riêng. Mọi thứ khác được chia sẻ giữa các chủ đề chia sẻ một quá trình.

Cụ thể, một quy trình thường được coi là bao gồm một tập hợp các luồng chia sẻ một không gian địa chỉ, heap, dữ liệu tĩnh và các đoạn mã và mô tả tệp * .

Một không gian địa chỉ đơn giản là ánh xạ các địa chỉ logic tới các phần cụ thể của bộ nhớ vật lý. Vì vậy, khi chúng ta nói rằng tất cả các luồng trong một tiến trình chia sẻ cùng một không gian địa chỉ, chúng ta có nghĩa là khi truy cập vào một biến footrong phạm vi toàn cầu, tất cả các luồng sẽ thấy cùng một biến. Tương tự, tất cả các luồng có thể đang chạy một điểm khác nhau trong mã tại bất kỳ thời điểm cụ thể nào, nhưng tất cả chúng đều được phép gọi hàm toàn cục bar(), sẽ tương ứng với cùng một chức năng cho mọi luồng trong quy trình.

Hầu hết các hệ điều hành hiện đại đã thêm một khái niệm về lưu trữ cục bộ luồng , là các biến có phạm vi toàn cầu không được chia sẻ. Ví dụ thông thường về việc sử dụng này là cho biến errno. Đó là một biến duy nhất của phạm vi toàn cầu, nhưng trong hầu hết các hệ điều hành hiện đại, mỗi luồng được cung cấp một bản sao cục bộ riêng của nó, do đó, lỗi trong một cuộc gọi thư viện trên một luồng sẽ không ảnh hưởng đến hành vi của các luồng khác.

* Có một số trạng thái quy trình bổ sung được chia sẻ bởi tất cả các luồng trong một quy trình, những thứ như id quá trình, xử lý tín hiệu và khóa tệp. Để có một danh sách đầy đủ về trạng thái quá trình được chia sẻ bởi các luồng, bạn cần xem tài liệu để thực hiện luồng cụ thể. Ví dụ, trang man pthreads .


4

Chủ đề xuất hiện trong hai quan điểm: hệ điều hành và ngôn ngữ lập trình. Trong cả hai trường hợp, có một số biến thể trong những thuộc tính mà một luồng có.

Một định nghĩa tối thiểu của một chủ đề là nó là thứ xảy ra theo trình tự, hết thứ này đến thứ khác.

Trong một mô hình thực thi máy điển hình, mỗi luồng có một bộ các thanh ghi mục đích chung và bộ đếm chương trình riêng. Nếu máy đặt ra một thanh ghi cụ thể dưới dạng con trỏ ngăn xếp, thì sẽ có một bản sao cho mỗi luồng.

Từ góc độ hệ điều hành, tối thiểu một hệ điều hành cần làm để hỗ trợ các luồng là cung cấp một cách để chuyển đổi giữa chúng. Điều này có thể xảy ra tự động ( đa nhiệm ưu tiên hoặc chỉ khi luồng đưa ra yêu cầu rõ ràng (đa nhiệm hợp tác; trong trường hợp đó, các luồng đôi khi được gọi là các sợi ). Ngoài ra còn có các mô hình lai với cả năng suất ưu tiên và hợp tác, ví dụ như giữa các luồng của các nhóm khác nhau hoặc các tác vụ nhưng mang lại năng suất rõ ràng giữa các luồng của cùng một nhóm / tác vụ. Chuyển đổi giữa các luồng liên quan đến việc lưu tối thiểu các giá trị thanh ghi của luồng cũ và khôi phục các giá trị thanh ghi của luồng mới.

Trong một hệ điều hành đa nhiệm cung cấp sự tách biệt giữa các tác vụ (hoặc các quy trình , bạn có thể coi các thuật ngữ này là từ đồng nghĩa trong ngữ cảnh HĐH), mỗi tác vụ có tài nguyên riêng, trong không gian địa chỉ cụ thể, nhưng cũng có tệp mở, đặc quyền, v.v. được cung cấp bởi nhân hệ điều hành , một thực thể nằm trên các quy trình. Mỗi tác vụ thường có ít nhất một luồng - một tác vụ không thực thi mã sẽ không được sử dụng nhiều. Hệ điều hành có thể hoặc không thể hỗ trợ nhiều luồng trong cùng một tác vụ; ví dụ như Unix ban đầu thì không. Một tác vụ vẫn có thể chạy nhiều luồng bằng cách sắp xếp để chuyển đổi giữa chúng - điều này không yêu cầu bất kỳ đặc quyền đặc biệt nào. Đây được gọi là chủ đề người dùngĐặc biệt, trong một bối cảnh Unix. Ngày nay, hầu hết các hệ thống Unix đều cung cấp các luồng nhân, đặc biệt bởi vì đó là cách duy nhất để có nhiều luồng của cùng một tiến trình chạy trên các bộ xử lý khác nhau.

Hầu hết các tài nguyên hệ điều hành ngoài thời gian tính toán được gắn vào các tác vụ, không phải các luồng. Một số hệ điều hành (ví dụ: Linux) phân định rõ ràng các ngăn xếp, trong trường hợp đó, mỗi luồng có một luồng riêng; nhưng có những hệ điều hành mà hạt nhân không biết gì về ngăn xếp, chúng chỉ là một phần của đống dữ liệu có liên quan. Kernel cũng thường quản lý bối cảnh kernel cho mỗi luồng, đó là cấu trúc dữ liệu chứa thông tin về những gì luồng đang làm; điều này cho phép kernel xử lý nhiều luồng bị chặn trong một cuộc gọi hệ thống cùng một lúc.

Theo như hệ điều hành, các luồng của một tác vụ chạy cùng một mã, nhưng ở các vị trí khác nhau trong mã đó (các giá trị bộ đếm chương trình khác nhau). Có thể hoặc không thể xảy ra rằng một số phần nhất định của mã chương trình luôn được thực thi trong một luồng cụ thể, nhưng thường có mã chung (ví dụ: các hàm tiện ích) có thể được gọi từ bất kỳ luồng nào. Tất cả các luồng nhìn thấy cùng một dữ liệu, nếu không, chúng sẽ được coi là các nhiệm vụ khác nhau; nếu một số dữ liệu chỉ có thể được truy cập bởi một luồng cụ thể, thì đó thường chỉ là mục đích của ngôn ngữ lập trình, không phải của hệ điều hành.

Trong hầu hết các ngôn ngữ lập trình, lưu trữ được chia sẻ giữa các luồng của cùng một chương trình. Đây là một mô hình bộ nhớ chia sẻ của lập trình đồng thời; nó rất phổ biến, nhưng cũng rất dễ bị lỗi, bởi vì lập trình viên cần cẩn thận khi cùng một dữ liệu có thể được truy cập bởi nhiều luồng vì điều kiện cuộc đua có thể xảy ra. Lưu ý rằng ngay cả các biến cục bộ cũng có thể được chia sẻ giữa các luồng: Biến cục bộ của người dùng (thường) có nghĩa là một biến có tên chỉ hợp lệ trong một lần thực hiện hàm, nhưng một luồng khác có thể lấy một con trỏ tới biến đó và truy cập vào nó.

Ngoài ra còn có các ngôn ngữ lập trình trong đó mỗi luồng có lưu trữ riêng và giao tiếp giữa chúng diễn ra bằng cách gửi tin nhắn qua các kênh liên lạc. Đây là mô hình truyền thông điệp của lập trình đồng thời. Erlanglà ngôn ngữ lập trình chính tập trung vào việc truyền thông điệp; môi trường thực thi của nó có xử lý các luồng rất nhẹ và nó khuyến khích các chương trình được viết bằng nhiều luồng ngắn, ngược lại với hầu hết các ngôn ngữ lập trình khác, nơi tạo ra một luồng là một hoạt động tương đối tốn kém và môi trường thời gian chạy không thể hỗ trợ rất lớn số lượng chủ đề cùng một lúc. Tập hợp con tuần tự của Erlang (một phần của ngôn ngữ xảy ra trong một luồng, đặc biệt là thao tác dữ liệu) (phần lớn) hoàn toàn là chức năng; do đó, một luồng có thể gửi tin nhắn đến một luồng khác chứa một số dữ liệu và không luồng nào cần phải lo lắng về việc dữ liệu bị luồng khác sửa đổi trong khi nó đang sử dụng nó.

Một số ngôn ngữ pha trộn hai mô hình bằng cách cung cấp lưu trữ cục bộ luồng, có hoặc không có hệ thống loại để phân biệt vị trí lưu trữ luồng cục bộ với vị trí toàn cầu. Lưu trữ cục bộ thường là một tính năng tiện lợi cho phép một tên biến để chỉ định các vị trí lưu trữ khác nhau trong các luồng khác nhau.

Một số theo dõi (khó) có thể được quan tâm để hiểu chủ đề là gì:

  • Mức tối thiểu mà kernel cần làm để hỗ trợ nhiều luồng là gì?
  • Trong môi trường đa bộ xử lý, cần gì để di chuyển một luồng từ bộ xử lý này sang bộ xử lý khác?
  • Điều gì sẽ xảy ra để triển khai đa luồng ( coroutines ) hợp tác trong ngôn ngữ lập trình yêu thích của bạn mà không có sự hỗ trợ từ hệ điều hành và không sử dụng hỗ trợ tích hợp nếu có? (Xin lưu ý rằng hầu hết các ngôn ngữ lập trình đều thiếu các nguyên hàm cần thiết để triển khai coroutines bên trong một luồng.)
  • Một ngôn ngữ lập trình có thể trông như thế nào nếu nó có sự tương tranh nhưng không có khái niệm (rõ ràng) về các luồng? (Ví dụ chính: phép tính pi .)

Đây là điều thú vị nhất tôi đã đọc trong nhiều tháng.
JSON

2

Mà phụ thuộc. Nếu bạn xem xét các luồng như được định nghĩa, ví dụ như POSIX (và được cung cấp bởi các hệ thống Unix) hoặc bởi Windows (không quen thuộc với sau này, bạn phải hỏi cụ thể), thì điều đó sẽ đưa ra câu trả lời của bạn (về cơ bản là câu trả lời @WanderingLogic giải thích). Linux có ý tưởng rất riêng về các luồng, sử dụng clone(2)lệnh gọi hệ thống không chuẩn . Nó cung cấp kiểm soát khá chi tiết về những gì cha mẹ và con cái chia sẻ. Nó đi xa như có fork(2)vfork(2)về cơ bản là bao bọc xung quanh nội bộ clone(2), gọi nó bằng các cờ cụ thể, tức là bạn có thể tạo ra các "chủ đề" chia sẻ bên cạnh không có gì với cha mẹ. Tra cứu trang hướng dẫn của nó để biết chi tiết, chúng có sẵn trên mạng, ví dụ ở đây . Có, Linux không cung cấp các luồng kiểu POSIX, nhưng nhiều hơn thế nữa.


0

Chủ đề chia sẻ:

  • Không gian địa chỉ
  • Đống
  • Dữ liệu tĩnh
  • Đoạn mã
  • Mô tả tập tin
  • Biến toàn cầu
  • Quá trình con
  • Báo động đang chờ xử lý
  • Tín hiệu và xử lý tín hiệu
  • Thông tin kế toán

Chủ đề có riêng của họ:

  • Chương trình truy cập
  • Đăng ký
  • Cây rơm
  • Tiểu bang
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.