2011-12-13 15 views
8

Tôi đang ở trong tình huống cần đọc một cây tìm kiếm nhị phân (BST) bên trong bộ xử lý tín hiệu (SIGSEGV bộ xử lý tín hiệu, theo kiến ​​thức của tôi là trên cơ sở luồng). BST có thể được sửa đổi bởi các chủ đề khác trong ứng dụng.Đọc dữ liệu được chia sẻ bên trong bộ xử lý tín hiệu

Giờ đây, vì trình xử lý tín hiệu không thể sử dụng các ẩn dụ, mutex vv, do đó không thể truy cập dữ liệu được chia sẻ, Làm cách nào để giải quyết vấn đề này? Lưu ý rằng ứng dụng của tôi đa luồng và chạy trên một hệ thống đa lõi.

+5

Tôi sẽ cố gắng thực sự, thực sự khó khăn, để nghĩ ra một cách để không đọc dữ liệu được chia sẻ trong trình xử lý tín hiệu đó. – dbeer

+1

Để nhấn mạnh điểm của @dbeer, trong trình xử lý tín hiệu, bạn thường không nên làm bất cứ điều gì sẽ chặn hoặc tăng các tín hiệu khác hoặc bất kỳ thao tác dài nào. Bộ xử lý tín hiệu phải nhỏ, nhanh và ngắn. –

+1

Có lẽ tôi đang thiếu một cái gì đó, nhưng nếu chỉ có các chủ đề của chương trình của bạn truy cập vào bộ nhớ chia sẻ (không có ngắt và ngoại lệ khác), tại sao bạn không thể sử dụng một semaphore (cho dù đó là phong cách tốt là một câu hỏi khác nhau)? Nếu một luồng truy cập vùng quan trọng, chặn nó, được đặt vào giấc ngủ bởi một luồng khác, semaphore vẫn bị khóa cho luồng khác, và cuối cùng luồng ban đầu của bạn sẽ được lên lịch để truy cập lại nó. Lý do hiệu suất sang một bên, tôi thấy không phải là một mối nguy hiểm của dữ liệu tham nhũng cũng không trì hoãn hệ thống. – gnometorule

Trả lời

3

Giả sử SH không thể truy cập các dữ liệu chia sẻ trực tiếp, thì có lẽ bạn có thể làm điều đó một cách gián tiếp:

  1. Có một số biến toàn cầu mà chỉ có bộ xử lý tín hiệu có thể viết thư cho, nhưng có thể được đọc từ các nơi khác (thậm chí nếu chỉ trong cùng một chủ đề).
  2. SH đặt cờ khi được gọi
  3. Chủ đề thăm dò ý kiến ​​cờ này khi chúng không ở giữa sửa đổi BST; khi tìm thấy thiết lập, chúng xử lý được yêu cầu bởi tín hiệu ban đầu (sử dụng bất kỳ đồng bộ hóa nào là cần thiết), sau đó tăng tín hiệu khác (như SIGUSR1) để cho biết rằng quá trình xử lý được thực hiện
  4. SH cho tín hiệu đó đặt lại cờ

Nếu bạn lo lắng về SIGSEGV, hãy thêm bộ đếm vào danh sách kết hợp để theo dõi. (Hey! Bạn vừa xây dựng semaphore của riêng mình!)

Liên kết yếu ở đây rõ ràng là cuộc thăm dò ý kiến, nhưng đó là sự bắt đầu.

+0

Tôi đã suy nghĩ chính xác điều tương tự :-p! Nhưng điều gì sẽ xảy ra khi một luồng đang sửa đổi BST khi tín hiệu xảy ra. Đó là một chút đáng lo ngại. – MetallicPriest

+0

Tôi nghĩ rằng đó sẽ không phải là một vấn đề: tín hiệu sẽ bị bắt, thiết lập cờ & trả lại; thread sẽ tiếp tục sửa đổi BST, và sẽ không cố gắng "xử lý" tín hiệu cho đến khi nó được thực hiện w/sửa đổi của nó. Giả sử rằng những thay đổi đó là nguyên tử, có vẻ như là một kết quả hợp lý. –

1

Bạn có thể xem xét mmap -ing a fuse hệ thống tệp (trong không gian người dùng).

Trên thực tế, bạn sẽ được hạnh phúc thêm về Gnu Hurd trong đó có hỗ trợ cho external pagers

Và có lẽ hack của bạn đọc một cây tìm kiếm nhị phân trong xử lý tín hiệu của bạn thường có thể làm việc trong thực tế, không portably và trong một hạt nhân cách phụ thuộc phiên bản. Có thể truy cập tuần tự hóa bằng các thủ thuật không di động cấp thấp (ví dụ: futexesatomic gcc builtins) có thể hoạt động. Đọc mã nguồn (máy cụ thể) của NPTL tức là các thói quen Linux hiện tại sẽ giúp ích.

Có thể là trường hợp pthread_mutex_lock v.v. trong thực tế có thể sử dụng từ bên trong trình xử lý tín hiệu Linux ... (vì có thể chỉ futex và hướng dẫn nguyên tử).

+0

Tôi đã đề cập đến một số thủ thuật không di động & Gnu hurd ... –

3

tôi có thể thấy hai giải pháp khá sạch:

  1. Linux cụ thể: Tạo một chuyên dụng tín hiệu xử lý chủ đề. Bắt tín hiệu bằng cách sử dụng signalfd(). Bằng cách này, bạn sẽ xử lý các tín hiệu trong một luồng thông thường, không phải bất kỳ trình xử lý hạn chế nào.
  2. Di động: Cũng sử dụng một chuỗi chuyên dụng cho đến khi nhận được tín hiệu. Bạn có thể sử dụng đường ống để tạo cặp mô tả tệp. Chủ đề có thể đọc (2) từ bộ mô tả đầu tiên và trong bộ xử lý tín hiệu bạn có thể viết (2) cho bộ mô tả thứ hai. Việc sử dụng write() trong trình xử lý tín hiệu là hợp pháp theo POSIX. Khi chủ đề đọc một cái gì đó từ ống nó biết nó phải thực hiện một số hành động.