viết lại tập tin hiện có để nó được thay thế bằng phiên bản mới về nguyên tử, chỉ một lần được viết đầy đủ


18

Tôi mơ hồ nhớ lại việc đọc ở đâu đó trước đây, trong một số Unice một cách để mở tệp hiện có để viết, với một cờ yêu cầu kernel sử dụng phiên bản cũ (cho các quá trình khác truy cập vào nó để đọc), cho đến khi "mới "Phiên bản đã được viết hoàn toàn (fd đã đóng), từ đó tệp xuất hiện dưới dạng phiên bản mới.

Nói cách khác, các quá trình khác hoặc thấy phiên bản cũ hoặc phiên bản mới, không bao giờ là phiên bản được viết không hoàn chỉnh.

Ai đó có thể hiểu biết chỉ cho tôi một tài liệu tham khảo?


Âm thanh giống như những gì Kế hoạch 9 có thể làm, nhưng không.
Gilles 'SO- ngừng trở nên xấu xa'

2
Âm thanh như Files-11 trên OpenVMS: "Mỗi khi tệp được lưu, thay vì ghi đè lên phiên bản hiện có, một tệp mới có cùng tên nhưng số phiên bản tăng dần được tạo ra."
Mat

Tại sao bạn hỏi? Bạn có cần chức năng đó không, hay chỉ là sự tò mò?
Nils

1
Tôi sẽ rất vui khi có chức năng đó, và tôi nhớ lại việc đọc ở đâu đó rằng nó tồn tại. Vì vậy, một hỗn hợp của cả nhu cầu và sự tò mò.
eudoxos

Tất cả các hệ thống Unix cho phép điều này theo cách khác - tạo tệp mới trong cùng thư mục, điền vào nội dung đã thay đổi và thực hiện đổi tên nguyên tử. Điều này là tốn kém hơn nhiều cho những thay đổi nhỏ nhưng làm việc.
Lấy

Câu trả lời:


14

Những gì bạn đang mô tả âm thanh chính xác như đổi tên cơ bản để ghi đè lên một tệp.

Khi bạn đổi tên / di chuyển một tệp lên trên một tệp khác, tệp cũ sẽ không được liên kết. Có nghĩa là tệp vẫn tồn tại, nhưng nó không còn trong cây hệ thống tệp nữa. Do đó, các ứng dụng cũ sẽ tiếp tục có thể truy cập tệp miễn là chúng vẫn mở. Khi tất cả các ứng dụng đã đóng tệp cũ, thì nó thực sự chưa được phân bổ trên đĩa.

Cuộc renamegọi hệ thống là một hoạt động nguyên tử. Vì vậy, để làm điều này, bạn sẽ tạo một tệp mới dưới một tên khác và sau đó gọi renameđể đổi tên tệp tạm thời thành tệp bạn muốn thay thế. Vì hoạt động là nguyên tử, hoàn toàn không có khoảng thời gian mà tệp bị thiếu. Nó ngay lập tức đi từ tập tin cũ sang tập tin mới.
Lưu ý rằng mặc dù tệp tạm thời và tệp được thay thế phải nằm trên cùng một điểm gắn kết.


Bạn chỉ có thể sử dụng nếu chương trình của bạn được viết cụ thể với chức năng trong tâm trí. Tuy nhiên, trong trường hợp này, đó là một tính năng của hệ điều hành, ngay cả các chương trình thông thường cũng được đưa ra ngữ nghĩa nguyên tử này một cách tự động.
eudoxos

1
@eudoxos bình luận của bạn không có ý nghĩa. Bạn đang nói rằng các chương trình sẽ phải được viết riêng để thực hiện việc renamehoán đổi. Ngay cả khi một 'tính năng hệ điều hành' như bạn đang nói về sự tồn tại, chương trình vẫn sẽ phải được viết để tận dụng lợi thế đó. Có gì khác biệt?
Patrick

Có một sự khác biệt nếu bạn chuyển một lá cờ (có thể không được hỗ trợ) cho tòa nhà openhoặc nếu bạn phải làm những gì bạn mô tả bằng tay.
eudoxos

Hãy nhớ rằng để giữ phiên bản cũ hoặc phiên bản mới được viết hoàn toàn trong trường hợp xảy ra sự cố, bạn cần phải đồng bộ hóa thêm tệp mới vào đĩa với fsync hoặc tương tự
texthell 24/07/2016

@textshell không có đồng bộ hóa bạn vẫn nhận được tính nguyên tử mặc dù .... chỉ là không bền ... đúng không? Tôi không hiểu đối số tại goo.gl/qfQQfy trong trường hợp này. Trong trường hợp của tôi, tôi có một hệ thống chịu tải cực lớn và tôi muốn tránh các lần xóa hệ thống tệp và tôi không quan tâm nếu tệp đó sống sót khi gặp sự cố.
wcochran

6

Như Patrick viết , cách thông thường để làm điều này là viết phiên bản mới vào một tệp riêng biệt và khi hoàn thành đổi tên phiên bản mới thành tên tệp cũ, ghi đè lên nguyên tử. Hoạt động thứ hai này được gọi là ghi đè lên bằng cách đổi tên .

Bây giờ, một số tài liệu tham khảo:


man 3p renamenói với tôi rằng đó renamethực sự là nguyên tử và tôi đoán điều đó có nghĩa đối với tất cả các hệ thống tệp Linux. Và khi tôi đọc bài viết đầu tiên mà bạn liên kết, tôi vẫn nghĩ rằng các hoạt động đổi tên Btrfs là nguyên tử.
hagello

1

Điều này làm tôi nhớ đến Allocate On Flush . Khi một hệ thống tập tin sử dụng tính năng này, thay vì ghi dữ liệu trực tiếp vào đĩa, nó sẽ trừ đi kích thước của dữ liệu được ghi từ bộ đếm không gian trống của đĩa và giữ dữ liệu trong bộ nhớ cho đến khi thực hiện lệnh gọi hệ thống đồng bộ hoặc nhân quyết định để xả bộ đệm bẩn.

Trong trường hợp này, nếu tệp đang được sửa đổi bởi một quy trình và được mở bởi quy trình khác, quy trình sau sẽ "xem" phiên bản chưa sửa đổi ( hoặc "cũ" nếu bạn thích ) của tệp.

Tất nhiên, những điều trên là lý thuyết và phụ thuộc vào nhiều yếu tố khác nhau, và tôi sẽ nói một chút không thể đoán trước được - vì bạn không biết chính xác khi nào kernel sẽ xóa các trang bẩn. Chẳng hạn như trong Linux ( như bạn cũng có thể đọc trong phần 15.3 của Tìm hiểu về Hạt nhân Linux ), các trang bẩn được ghi vào đĩa theo các điều kiện sau:

  • Bộ đệm trang quá đầy và cần nhiều trang hơn hoặc số lượng trang bẩn trở nên quá lớn.

  • Quá nhiều thời gian đã trôi qua kể từ khi một trang bị bẩn.

  • Một quy trình yêu cầu tất cả các thay đổi đang chờ xử lý của một thiết bị khối hoặc của một tệp cụ thể sẽ bị xóa; nó thực hiện điều này bằng cách gọi một cuộc gọi hệ thống sync (), fsync () hoặc fdatasync ().

Tính năng này được biết là được triển khai trong các hệ thống tập tin HFS +, XFS, Reiser4, ZFS, Btrfs và ext4.


2
Những gì bạn mô tả là một kỹ thuật hệ thống tệp không thể nhìn thấy từ không gian người dùng (và do đó không làm những gì bạn chỉ ra) trên các hệ thống POSIX (tệp) (xem ghi : "Nếu dữ liệu tệp đọc () có thể được chứng minh (bằng mọi cách) xảy ra sau khi ghi () dữ liệu, nó phải phản ánh rằng write (), ngay cả khi các cuộc gọi được thực hiện bởi các quy trình khác nhau . "). Các quy trình khác sẽ không thấy dữ liệu cũ (trên POSIX).
Mat

Cảm ơn vì sự đúng đắn của bạn. Tôi đoán sự hiểu biết của tôi về kỹ thuật hệ thống tập tin này là sai.
dkaragasidis

Phải, cái này trông giống cái gì khác. Bây giờ tôi mơ hồ nhớ lại rằng trong một cuộc phỏng vấn với RMS rằng anh ấy đã đề cập đến tính năng này, có lẽ đó là một hệ thống phức tạp cũ không bao giờ sống bên ngoài giới hàn lâm ... Dù sao cũng cảm ơn.
eudoxos
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.