2011-08-01 21 views
6

Tôi có hai quá trình mỗi bộ đệm lớn dữ liệu, và tôi muốn kiểm soát đồng bộ hóa các quy trình 'ghi vào một tập tin.Làm thế nào tôi có thể đồng bộ hóa - làm cho nguyên tử - ghi trên một tệp từ hai quy trình?

quy trình 1 bộ đệm ghi A bao gồm (A1, A2, A3) và xử lý 2 bộ đệm B bao gồm (B1, B2, B3). khi chúng tôi sử dụng write() gọi hệ thống để ghi các bộ đệm này vào đĩa đến cùng một tệp (toàn bộ bộ đệm cùng một lúc: write(fd, A, sizeof(A))), Lược đồ tệp là gì?

  • Có phải như sau: A, B hoặc B, A có thể?
  • hoặc nó có thể là như thế này: A1, A2, B1, A3, ...

tôi yêu cầu này bởi vì các cuộc gọi hệ thống là nguyên tử. điều gì sẽ xảy ra nếu bộ đệm dữ liệu mà chúng tôi đang viết quá lớn. Nó giống như đường ống cho các tập tin đĩa thông thường?

Trả lời

4

Nếu bạn muốn nội dung của cả hai bộ đệm để có mặt, bạn phải mở tệp có bộ cờ O_APPEND. Cờ chắp thêm tìm đến cuối tập tin trước khi viết. Nếu không có tập hợp này, có thể cả hai quy trình sẽ trỏ đến cùng một vùng hoặc chồng chéo của tệp và bất kỳ ai viết cuối sẽ ghi đè nội dung mà người khác đã viết.

Mỗi cuộc gọi đến write sẽ ghi tối đa số byte được yêu cầu. Nếu quá trình của bạn bị gián đoạn bởi một tín hiệu, sau đó bạn có thể kết thúc với một phần ghi - số lượng thực tế của byte bằng văn bản được trả về. Cho dù bạn nhận được tất cả các byte của bạn bằng văn bản hay không, bạn sẽ có viết một phần tiếp giáp của tập tin. Bạn không nhận được hiệu ứng xen kẽ mà bạn đã đề cập là khả năng thứ hai của bạn (ví dụ: A1, B1, A2, B2, ...).

Nếu bạn chỉ nhận được một phần viết, cách bạn tiến hành tùy thuộc vào bạn. Bạn có thể tiếp tục viết (bù đắp từ bộ đệm bắt đầu bằng số byte được viết trước đó), hoặc bạn có thể bỏ phần còn lại của bài viết của bạn. Chỉ bằng cách này bạn mới có khả năng có được hiệu ứng xen kẽ.

Nếu điều quan trọng là phải ghi nội dung của một lần ghi hoàn chỉnh trước khi quá trình ghi khác, thì bạn nên xem xét khóa tệp để truy cập ghi độc quyền (cả hai quy trình sẽ phải kiểm tra) trước khi thử viết bất kỳ dữ liệu nào.

+0

Vì vậy, chúng tôi không có bất kỳ tín hiệu nào và 'O_APPEND' được bật, chúng tôi phải có A, B hoặc B, A. tôi có đúng không –

+1

@Majid - Có, giả sử không có gì trên hệ thống ngắt bạn, bạn sẽ nhận được A, B hoặc B, A tùy thuộc vào người đầu tiên. – unpythonic

+0

Cần lưu ý rằng ghi trên các tệp bình thường trên hệ thống tệp cục bộ sẽ không bao giờ bị gián đoạn. NFS có một lá cờ để làm cho chúng bị gián đoạn, nhưng mặc định là tắt. –

2

Giả sử rằng bộ đệm có kích thước bằng nhau, kết quả sẽ là A hoặc B, tùy thuộc vào quy trình nào được lên lịch trước.

Cuộc gọi hệ thống ghi là nguyên tử, có, có nghĩa là kết quả sẽ là A hoặc B, không phải là hỗn hợp của cả hai.

Giả sử bạn muốn cả A và B trong tệp, bạn có thể mở tệp bằng O_APPEND; lưu ý rằng điều này sẽ không hoạt động trên NFS.

Một lựa chọn khác là mỗi quá trình theo dõi trong đó tập bù đắp nó nên sử dụng, và sử dụng lseek() hoặc pwrite()

2

Bạn chắc chắn cần một số hình thức đồng bộ hóa cho các chương trình của bạn truy cập tệp hoặc bạn kết thúc với nội dung tệp bị hỏng. Cuộc gọi hệ thống write có thể ghi ít byte hơn bạn yêu cầu, do đó, các khối A1, A2 hoặc B1, B2 của bạn chỉ có thể được viết một phần. Điều này có thể xảy ra thường xuyên, hoặc hiếm khi, tùy thuộc vào nhiều điều kiện. Nếu nó chỉ xảy ra một lần trong một tuần, bạn sẽ có một lỗi có thể rất khó phát hiện.

Là giải pháp, bạn có thể sử dụng khóa tệp (man 2 flock hoặc man fcntl và tìm khóa).Một khả năng khác là sử dụng các semaphores (man -k semaphore) để đồng bộ hóa các chương trình của bạn viết, hoặc một số dạng khác của IPC.

+0

+1 Khóa tập tin có lẽ là cách để đi, vì nó thường không hiệu quả (hoặc khó) để viết mọi thứ xuống một lần. –

Các vấn đề liên quan