Cách chia sẻ bộ nhớ giữa các ứng dụng được viết bằng C / C ++


9

Tôi đang trải qua một chương trình được viết bằng C / C ++ để điều khiển robot. Về cơ bản, ba chương trình khác nhau chạy cùng một lúc và chúng giao tiếp qua bộ nhớ dùng chung. Google ling xung quanh tôi thấy tôi nghĩ như vxWorks và các tiêu đề tăng cường thư viện tăng cường ( Tài liệu tăng cường: Chia sẻ bộ nhớ giữa các quy trình ).

Bây giờ, tôi không muốn nhìn vào việc thực hiện, tôi có thể đọc liên kết ở trên. Nhưng tôi không thể hiểu được cách mà thư viện boost thực hiện điều này. Ý tôi là, một ứng dụng phân bổ bộ nhớ và truy cập bộ nhớ khác, nhưng làm thế nào để chúng giao tiếp? Nó không an toàn để làm điều này?


những gì có vẻ không rõ ràng trong các tài liệu bạn đề cập? "Khi đặt các đối tượng trong một vùng được ánh xạ và ánh xạ vùng đó ở các địa chỉ khác nhau trong mỗi quy trình, các con trỏ thô là một vấn đề vì chúng chỉ có giá trị cho quá trình đặt chúng ở đó. Để giải quyết điều này, Boost.Inter Process cung cấp một con trỏ thông minh đặc biệt mà có thể được sử dụng thay cho con trỏ thô. Vì vậy, các lớp người dùng chứa con trỏ thô (hoặc Boost con trỏ thông minh, sở hữu một con trỏ thô) không thể được đặt an toàn trong vùng ánh xạ được chia sẻ quy trình. Những con trỏ này phải được thay thế bằng ... "
gnat

Đừng quên hệ điều hành là quá trình thực sự chăm sóc bộ nhớ. Các quy trình phân bổ và sử dụng bộ nhớ vào cuối ngày sử dụng HĐH để thực hiện các yêu cầu của họ. HĐH quản lý đa xử lý và đảm bảo sẽ không có bất kỳ xung đột nào.
Rob Sedgwick

@gnat Việc thực hiện đã rõ ràng. Làm thế nào để Boost thực hiện việc triển khai đó không phải trên các tài liệu đó ... Tôi không muốn sao chép nó (điều đó thật vô lý) mà là để hiểu nó.
cauch

Câu trả lời:


11

Nhưng tôi không thể hiểu được cách mà thư viện boost thực hiện điều này.

Cơ chế tăng cường quá trình có ba thành phần cần thiết để hoạt động:

  1. tập tin ánh xạ bộ nhớ: một tập tin ánh xạ bộ nhớ cần phải được tạo và chuyển đến bộ cấp phát boost.inter Process. Bộ cấp phát này sẽ lấy các phần của tệp và sử dụng chúng như thể chúng được trả về bởi một bộ phân phối std ::, với ánh xạ được áp dụng để bộ nhớ tương thích với bộ nhớ cụ thể trong quá trình.

  2. container boost.inter Process; loại container này sẽ sử dụng bộ nhớ được cấp phát trả về và cung cấp giao diện std :: container like (start / end / size / push_back, v.v.).

  3. cơ chế đồng bộ hóa; đây có thể là bất kỳ mutex liên tiến trình nào và nên được sử dụng để ngăn chặn các điều kiện chạy truy cập dữ liệu.

Ý tôi là, một ứng dụng phân bổ bộ nhớ và truy cập bộ nhớ khác, nhưng làm thế nào để chúng giao tiếp? Nó không an toàn để làm điều này?

Bộ nhớ được phân bổ thực sự là một tệp ánh xạ bộ nhớ dùng chung Truyền thông là gián tiếp, với cả hai ứng dụng cài đặt hoặc đọc dữ liệu, khi chúng cần. Sự an toàn đến từ việc sử dụng các nguyên thủy đồng bộ hóa quá trình.


2
Đáng chú ý: Cả ba cơ chế IPC này đều yêu cầu hỗ trợ kernel, vì vậy đối với những người tò mò về cách thực hiện (như OP chỉ ra), các ứng dụng riêng lẻ không thể được thực hiện. Các ứng dụng phải yêu cầu kernel lập bản đồ các tập tin hoặc đồng bộ hóa với các tiến trình khác.
Cort Ammon

5

bộ nhớ chia sẻ không phải là bức tranh hoàn chỉnh cho IPC, đây là cơ chế truyền dữ liệu nhưng bạn vẫn cần một số cách để thông báo cho quá trình khác rằng một số dữ liệu đã được cập nhật và có sẵn để đọc. Cách bạn thực hiện việc này tùy thuộc vào bạn, thông thường bạn sẽ sử dụng một đối tượng sự kiện hoặc sự kiện của hệ điều hành, mỗi quy trình chờ đợi để thiết lập điều này, việc viết ứng dụng sẽ đặt nó sau khi viết xong. Sau đó, chủ đề trong các chương trình khác thức dậy và đọc.

Ngoài ra, bạn có thể thăm dò ý kiến, đọc dữ liệu thường xuyên để biết giá trị thay đổi khi dữ liệu được cập nhật (ví dụ: bộ đếm tăng).


4

Boost sử dụng ánh xạ bộ nhớ của một tập tin.

Cả unix và windows đều hỗ trợ tạo các tệp không tồn tại trên hệ thống tệp thông thường cho mục đích này.

Sau đó, bạn sẽ cần phải đồng bộ hóa quyền truy cập vào bộ nhớ đó như bạn muốn nếu các luồng khác nhau được truy cập. Có nghĩa là việc đọc đồng thời có thể xảy ra mà không cần đồng bộ hóa nhưng ngay khi một quá trình muốn viết, bạn sẽ cần ngăn những người khác truy cập vào nó.

Các hoạt động nguyên tử trên bộ nhớ dùng chung vẫn có thể nếu bạn muốn đồng bộ hóa không khóa.


Bạn có thể giải thích "Hoạt động nguyên tử trên bộ nhớ dùng chung vẫn có thể nếu bạn muốn đồng bộ hóa không khóa" không? Bạn muốn nói rằng nếu mỗi chương trình là C ++, bạn phải sử dụng std::atomiclớp mẫu C ++ 11 ( cplusplus.com/reference/atomic ) trong mỗi hai chương trình để chúng có thể ghi vào không gian chia sẻ mà không đồng bộ hóa thực thi thông qua khóa?
Gabriel Staples

@GabrielStaples yeah hoặc nội tại nguyên tử tương đương
ratchet freak

Xin lôi vi đa lam phiên bạn lân nưa; Tôi không quen thuộc với "nội tại nguyên tử." Bạn có thể vui lòng chỉ cho tôi một tài liệu tham khảo để nghiên cứu chúng nhiều hơn? Một tìm kiếm nhanh trên google là không rõ ràng.
Gabriel Staples

3

Bộ nhớ dùng chung vẫn chỉ là bộ nhớ. Bạn có thể đặt mutex, spinlock hoặc bất kỳ nguyên thủy đồng bộ hóa nào khác vào đó và sử dụng chúng để đồng bộ hóa quyền truy cập của bộ xử lý vào bộ nhớ dùng chung, giống như các luồng sử dụng các nguyên thủy đó để đồng bộ hóa quyền truy cập vào bộ nhớ hiển thị với chúng.

Sự khác biệt thực sự duy nhất là:

  1. chủ đề chia sẻ tất cả bộ nhớ và cùng một không gian địa chỉ, vì vậy con trỏ thô hoạt động cho chúng. Bộ nhớ được chia sẻ giữa các quy trình hoạt động giống hệt nhau, nhưng có thể được ánh xạ tại các địa chỉ khác nhau trong mỗi quy trình, vì vậy bạn không thể đơn giản chuyển các con trỏ thô giữa chúng.

    • Lưu ý điều này có tác dụng kích thích một số chi tiết triển khai của các phương thức ảo, thông tin loại thời gian chạy và một số cơ chế C ++ khác. Bám sát các loại có thể khởi tạo tầm thường (dữ liệu cũ đơn giản) không có phương thức ảo hoặc phôi động trong bộ nhớ dùng chung của bạn, không sử dụng kiểu chữ trên chúng và bạn sẽ ổn.
  2. một số nguyên hàm đồng bộ hóa có thể cần các cờ hoặc thuộc tính đặc biệt để hoạt động chính xác giữa các quy trình ( PTHREAD_PROCESS_SHAREDví dụ: xem thuộc tính cho các biến đổi luồng POSIX). Điều này thực sự không liên quan đến bộ nhớ và đồng bộ hóa bản thân, nhưng do tương tác kernel / trình lập lịch cần thiết để đánh thức người phục vụ đang ngủ.


Vì thế:

Nhưng làm thế nào để họ giao tiếp?

Cùng một cách các chủ đề khác nhau giao tiếp, cho phép cảnh báo ở trên

Nó không an toàn để làm điều này?

Đúng, chính xác là không an toàn cho các quá trình giao tiếp qua bộ nhớ dùng chung vì nó là chủ đề để giao tiếp qua bộ nhớ dùng chung và chúng cần đồng bộ hóa (hoặc giống hệt nhau) để đảm bảo an toàn.


3

Lưu ý rằng C và C ++ là các ngôn ngữ khác nhau.

Bộ nhớ dùng chung không thể có trong C11 tiêu chuẩn hoặc C ++ 11 hoàn toàn (vì tiêu chuẩn không xác định điều đó), hoặc thậm chí C ++ 14 (có bản nháp n3690 và có lẽ là tiêu chuẩn chính thức, không đề cập đến bộ nhớ chia sẻ ngoài đa luồng ). Vì vậy, bạn cần thêm thư viện để có được bộ nhớ chia sẻ. Nhưng một số hệ điều hành có hỗ trợ cho bộ nhớ dùng chung. Vì vậy, một số thư viện cung cấp bộ nhớ chia sẻ, được xây dựng trên các dịch vụ hệ điều hành hiện có, tồn tại. Có lẽ bạn có thể cân nhắc sử dụng thư viện khung POCO (tóm tắt các chi tiết cụ thể của HĐH)

Đối với Linux (và có lẽ là POSIX), hãy xem shm_overview (7) . Bạn sẽ cần phải đồng bộ hóa, vì vậy hãy xem sem_overview (7)

VXWorks (mà tôi không biết, nhưng đã cho nó biết) có VxMP

Bạn cần phải cẩn thận hiểu những gì đang thực sự xảy ra. Bạn có thể chỉ muốn chia sẻ dữ liệu cũ đơn giản struct(không phải các lớp C ++!) Và bạn nên rất cẩn thận về các địa chỉ (mỗi quy trình có thể nhận địa chỉ khác nhau cho phân đoạn bộ nhớ dùng chung) và về đồng bộ hóa.

Ngoài ra, sử dụng chủ đề. Lưu ý rằng tiêu chuẩn C ++ 11 định nghĩa một thư viện luồng .


1
Tất nhiên bộ nhớ chia sẻ là có thể trong cả C ++ 11 và C11! thực tế nó không phải là một phần của tiêu chuẩn là vô nghĩa, GUI cũng không phải là một phần của tiêu chuẩn. Có nhiều thư viện một số nền tảng chéo cho phép một người sử dụng bộ nhớ dùng chung và các phương thức đồng bộ hóa khác nhau ...
AK_

1
Quan điểm của tôi là bộ nhớ dùng chung không được xác định theo tiêu chuẩn C ++ 11 (nhưng một số triển khai có các dịch vụ cụ thể của hệ điều hành)
Basile Starynkevitch

Tôi nghĩ bạn nên dành thời gian để hiểu thuật ngữ "tiêu chuẩn ngôn ngữ" thực sự có nghĩa là gì, triển khai tuân thủ tiêu chuẩn là gì và thư viện là gì.
AK_

Vui lòng chỉ cho tôi phần trong tiêu chuẩn C ++ 11 (hoặc trong bản nháp n3690 của C ++ 14) nói về bộ nhớ dùng chung.
Basile Starynkevitch

3
Tôi nghĩ rằng cả hai chúng tôi đều đồng ý, nhưng chúng tôi có thể không đồng ý về ý nghĩa của C ++ 11 tiêu chuẩn. Đối với tôi, nó chính xác (không quá) tiêu chuẩn ISO C ++ 11 (hoặc bản nháp miễn phí tương đương với nó). Các thư viện bên ngoài không được tính là tiêu chuẩn, ngay cả khi chúng là phổ biến và đa nền tảng.
Basile Starynkevitch
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.