Làm thế nào để biết nếu một tập tin được ánh xạ bộ nhớ?


8

Tôi bối rối về các tập tin ánh xạ bộ nhớ, vì vậy tôi có một vài câu hỏi mà tôi sẽ rất vui nếu bạn có thể giúp tôi.

  1. Giả sử tôi duyệt đến một thư mục trong hệ thống tệp của mình và có một tệp trong thư mục này. Có thể tệp này trỏ đến một vùng trong bộ nhớ chính, thay vì chỉ vào một vùng trong đĩa?
  2. Nếu điều này là có thể, đây có phải là cái mà chúng ta gọi là 'tệp ánh xạ bộ nhớ' không?
  3. Ý nghĩa của việc di chuyển tệp như vậy xung quanh hệ thống tệp (nghĩa là lấy mvtệp đó từ thư mục này sang thư mục khác)? Điều tôi hiểu là, vì tệp được ánh xạ bộ nhớ, quá trình tương tác với tệp luôn ghi vào vùng được xác định trước của bộ nhớ chính và khi chúng tôi mở tệp đó (ví dụ như sử dụng vim), chúng tôi đọc vùng đó của chính bộ nhớ (vì vậy, không có đĩa liên quan). Do đó, bất kể chúng ta di chuyển tệp ở đâu, nó sẽ luôn hoạt động chính xác phải không? Nếu có, việc di chuyển tệp xung quanh hệ thống tệp có ý nghĩa gì không?
  4. Có một lệnh sẽ cho biết nếu một tập tin được ánh xạ bộ nhớ?
  5. Cuối cùng, nếu tôi mở một tệp ánh xạ bộ nhớ với vim, thực hiện một số thay đổi trên đó và lưu và đóng vim, điều gì sẽ xảy ra? Những thay đổi của tôi chỉ đơn giản sẽ được ghi vào bộ nhớ chính? Nếu đó là trường hợp, các quá trình khác sử dụng tệp này sẽ thấy những thay đổi tôi vừa thực hiện? Theo kinh nghiệm của tôi, các quy trình khác không thấy các thay đổi tôi đã thực hiện đối với tệp khi tôi thực hiện một số thay đổi trên tệp vim. Lý do cho điều này là gì?

12
Điều này nhắc nhở tôi về một người nào đó hỏi làm thế nào để biết nếu một tập tin là một liên kết cứng.
Dmitry Grigoryev

3
@DmitryGrigoryev Điều đó khá buồn cười, trên thực tế, nhưng mọi người đều học :)
con mèo

Câu trả lời:


24

Các tập tin ánh xạ bộ nhớ hoạt động theo cách khác. Ánh xạ bộ nhớ không phải là một thuộc tính của tệp, nhưng là một cách để truy cập tệp: một quy trình có thể ánh xạ nội dung của tệp (hoặc một tập hợp con) vào không gian địa chỉ của tệp. Điều này làm cho nó dễ đọc và ghi vào tệp hơn; làm như vậy đơn giản chỉ cần đọc và viết trong bộ nhớ. Bản thân tệp, trên đĩa, cũng giống như bất kỳ tệp nào khác.

Để thiết lập điều này, các quy trình sử dụng mmapchức năng. Điều này cũng có thể được sử dụng cho các mục đích khác, chẳng hạn như chia sẻ bộ nhớ giữa các quy trình.


14
@Utku Điều này không có gì để làm với các tập tin ánh xạ bộ nhớ.
Satō Katsura

12
Nếu bạn không tắt máy chủ MySQL, đó là hành vi bình thường: máy chủ có mô tả tệp mở trên tệp và điều đó vẫn hợp lệ ngay cả với mv.
Stephen Kitt

11
Bộ mô tả tập tin (cuối cùng) đến các nút trong hệ thống tập tin; đó là nơi tập tin thực sự sống Các mục nhập thư mục cũng trỏ đến các nút này và mvchỉ cần thay đổi các mục nhập thư mục, không phải các nút (khi nó di chuyển các tệp trên cùng một hệ thống tệp).
Stephen Kitt

1
Mô tả của bạn là một sự đơn giản hóa hữu ích, nhưng chỉ cho chính xác: Ánh xạ bộ nhớ về mặt kỹ thuật không giống với mô tả tệp, nhưng chúng hoạt động theo cùng một cách (bằng cách tham chiếu đến nút, không phải tên tệp). open (), mmap (), close () không có FD, chỉ là ánh xạ, sẽ hiển thị với lsof. Nó không biến mất cho đến khi quá trình gọi munmap () hoặc thoát (hoặc thay thế ánh xạ bằng một ánh xạ khác bằng mmap (MAP_FIXED) ...)
Peter Cordes

3
@Utku Bạn không thực sự di chuyển tập tin. Bạn vừa tạo một mục nhập thư mục mới đề cập đến cùng một tệp và sau đó loại bỏ mục cũ. Thay đổi trong cách đặt tên không ảnh hưởng đến quá trình đã mở tệp.
David Schwartz

11

Một tập tin ánh xạ bộ nhớ không (nhất thiết) được hỗ trợ bởi bộ nhớ. Nó hoàn toàn có thể sống trên một đĩa. Trên thực tế, nơi một tệp sống không phải là một thuộc tính của chính tệp đó mà là của hệ thống tệp mà nó cư trú.

Ánh xạ một tệp trong bộ nhớ là một thao tác mà một quá trình có thể làm để có một phần của tệp được tải trong bộ nhớ. Kết quả trông giống như một vùng bộ nhớ thông thường, ngoại trừ khi quá trình đọc từ hoặc ghi vào vùng này, nó thực sự đọc từ và ghi vào tệp. Nếu bạn mở một tệp, ánh xạ nó vào bộ nhớ, ghi vào tệp và lưu nó, việc sửa đổi sẽ được thực hiện trên tệp, trên đĩa (tất nhiên nếu nó nằm trên đĩa).

Điều này có thể được sử dụng ví dụ như khi bạn biết bạn có rất nhiều lượng truy cập thực hiện trên một tập tin, mà sẽ không được tuần tự, có nguyên nhân nó có thể được dễ dàng hơn và hiệu quả hơn để làm đọc và ghi trong bộ nhớ hơn đối với vấn đề read, write, và llseekcác cuộc gọi hệ thống. Vấn đề duy nhất với phương pháp này là bạn không thể thực sự sử dụng nó nếu tệp cần phải được đọc từ hoặc ghi vào một số quy trình cùng một lúc. Kết quả sẽ không thể đoán trước.

Tôi biết không có lệnh nào có thể cho bạn biết nếu một tệp hiện đang được ánh xạ. Tuy nhiên, bạn có thể kiểm tra ánh xạ của một quá trình /proc/<pid>/maps(nếu hệ thống của bạn có nó).

Để trả lời câu hỏi thứ hai của bạn, khi bạn mở một tệp, ngay cả khi bạn di chuyển nó trong hệ thống tệp, các quy trình đã mở nó vẫn có thể sử dụng tệp đó. Điều gì xảy ra là một tệp không phụ thuộc vào các mục trong tệp hệ thống. Miễn là bạn có một tệp được mở, bạn có một "tay cầm", một bộ mô tả tệp, cho phép bạn đọc và ghi vào nó, ngay cả khi đường dẫn của nó trong hệ thống tệp thay đổi. Một tệp chỉ biến mất khi nó không có mục trong hệ thống tệp và không có quá trình giữ mô tả tệp trên đó.


Vì vậy, khi chúng ta di chuyển một tệp, giá trị của bộ mô tả tệp không thay đổi. Có một ánh xạ mô tả đường dẫn đến tệp và chỉ phần đường dẫn của ánh xạ đó thay đổi. Điều này có đúng không?
Utku

1
Trong một số ý nghĩa có, nhưng tôi không chắc chắn để hiểu bạn vì vậy hãy để tôi viết lại nó. Về cơ bản, "một tập tin" là ba điều. Một mục thư mục là một đường dẫn trong hệ thống tập tin. Một inode là nội dung của một tập tin. Và một mô tả tập tin đại diện cho một tập tin mở. Cả hai mục nhập thư mục và bộ mô tả tệp đều chứa một con trỏ tới nút sao lưu của chúng. Khi bạn mở một tệp, bạn chuyển mục nhập thư mục và kernel trả về cho bạn một mô tả tệp. Vì vậy, ngay cả khi mục nhập thư mục gốc thay đổi, bộ mô tả tệp vẫn trỏ đến cùng một nút và bạn có thể truy cập tệp.
lgeorget

1
Bạn có thể kiểm tra các ánh xạ của một quá trình, mặc dù, trong /proc/<pid>/maps. - Với điều kiện là quá trình nói trên sống trên một hệ thống /procphải bắt đầu. OpenBSD thì không, và FreeBSD đang loại bỏ dần. Ngoài ra, FreeBSD có /proc/<pid>/mapthay vì /proc/<pid>/maps.
Satō Katsura

@SatoKatsura Cảm ơn bạn đã chính xác. Tôi chỉ có một máy Linux trong tay, vì vậy tôi nghĩ tôi sẽ kể về trường hợp của mình và để mọi người kể về họ ... Hãy thoải mái chỉnh sửa câu trả lời nếu bạn có điều cần sửa / thêm vào đây.
lgeorget

Vì bạn hỏi: bạn giả sử OP thực sự hiểu những gì anh ta hỏi và giải thích chi tiết các tệp ánh xạ bộ nhớ là gì. Tôi không nghĩ bạn đã làm cho anh ấy một dịch vụ. IMO bình luận đầu tiên của bạn ở trên có liên quan nhiều hơn đến những gì OP thực sự hỏi sau đó là câu trả lời của bạn. FWIW.
Satō Katsura

9

Câu hỏi 4: Có lệnh nào cho biết tập tin có được ánh xạ bộ nhớ không?

Các lsoflệnh sẽ cho bạn thấy tất cả các file đang được sử dụng bởi hệ thống. Cột "FD" sẽ chứa "mem" nếu tệp được ánh xạ bộ nhớ. Vì vậy, bạn có thể grep đầu ra của lệnh này cho tên tệp mà bạn quan tâm.


3
Hoặc sử dụnglsof -ad mem /path/to/file
Stéphane Chazelas

5
Hay đúng hơn lsof -ad mem,txt /path/to/filelà các tệp đang được thực thi cũng có các phần của chúng được đặt trong không gian địa chỉ tiến trình nhưng xuất hiện như txttrong lsofđầu ra.
Stéphane Chazelas

7

Bạn dường như nhầm lẫn ánh xạ bộ nhớ với các tệp trong các hệ thống tệp nằm trong bộ nhớ, cùng với các khái niệm khác như cách các quy trình duy trì quyền truy cập vào các tệp ngay cả khi chúng di chuyển xung quanh.

Tôi sẽ đi từng câu hỏi để xem liệu tôi có thể làm sáng tỏ mọi thứ không.

  1. Giả sử tôi duyệt đến một thư mục trong hệ thống tệp của mình và có một tệp trong thư mục này. Có thể tệp này trỏ đến một vùng trong bộ nhớ chính, thay vì chỉ vào một vùng trong đĩa?

Nó chỉ vào bộ nhớ chính nếu nó nằm trên một hệ thống tệp nằm trong bộ nhớ, như các Procfs thường được gắn trên / Proc hoặc sysfs trên / sys hoặc tmpfs đôi khi trên / tmp.

  1. Nếu điều này là có thể, đây có phải là cái mà chúng ta gọi là 'tệp ánh xạ bộ nhớ' không?

Không giống như stephen-kitt đã nói, "ánh xạ bộ nhớ" đề cập đến một cách để truy cập một tệp bằng cách "ánh xạ" nó vào bộ nhớ chính và làm việc với nó ở đó thay vì đọc và viết các đoạn tại một thời điểm thông qua các hàm như read () và viết ().

  1. Ý nghĩa của việc di chuyển tệp như vậy xung quanh hệ thống tệp (nghĩa là chuyển tệp đó từ thư mục này sang thư mục khác)? Điều tôi hiểu là, vì tệp được ánh xạ bộ nhớ, quá trình tương tác với tệp luôn ghi vào vùng được xác định trước của bộ nhớ chính và khi chúng tôi mở tệp đó (ví dụ: sử dụng vim), chúng tôi đọc vùng đó bộ nhớ chính (vì vậy, không có đĩa liên quan). Do đó, bất kể chúng ta di chuyển tệp ở đâu, nó sẽ luôn hoạt động chính xác phải không? Nếu có, việc di chuyển tệp xung quanh hệ thống tệp có ý nghĩa gì không?

Nếu bạn di chuyển nó trong cùng một hệ thống tập tin, bạn thực sự chỉ di chuyển xung quanh một tham chiếu, một nút từ thư mục này sang thư mục khác. Nếu có các chương trình đã mở tệp này, chúng vẫn sẽ truy cập vào cùng một tệp vì chúng đã có sẵn nút inode thông qua bộ mô tả tệp. Đây là những gì đã xảy ra với tệp table_name.idb mà bạn đã đề cập trong một nhận xét.

  1. Có một lệnh sẽ cho biết nếu một tập tin được ánh xạ bộ nhớ?

Wossname đã trả lời điều này cho các tệp ánh xạ bộ nhớ. lsofsẽ cho bạn biết các quá trình có ánh xạ bộ nhớ tập tin.

Để biết nếu một tệp nằm trong hệ thống tệp nằm trong bộ nhớ, bạn có thể sử dụng dfhoặc mountliệt kê các hệ thống tệp và các điểm gắn kết của chúng. Bạn chỉ cần biết loại hệ thống tập tin nào nằm trong bộ nhớ bằng cách tìm kiếm chúng (ví dụ như trong wikipedia).

  1. Cuối cùng, nếu tôi mở tệp ánh xạ bộ nhớ bằng vim, hãy thực hiện một số thay đổi trên đó và lưu và đóng vim, điều gì sẽ xảy ra? Những thay đổi của tôi chỉ đơn giản sẽ được ghi vào bộ nhớ chính? Nếu đó là trường hợp, các quá trình khác sử dụng tệp này sẽ thấy những thay đổi tôi vừa thực hiện? Theo kinh nghiệm của tôi, các quy trình khác không thấy các thay đổi tôi đã thực hiện đối với tệp khi tôi thực hiện một số thay đổi trên tệp bằng vim. Lý do cho điều này là gì?

Cá nhân, tôi đã không sử dụng mmapchức năng này trong một chương trình C, nhưng theo tôi hiểu nó từ việc lướt qua man mmapinfo mmap, không có phép thuật nào liên quan đến việc duy trì đồng bộ hóa trong bộ nhớ. Ở dạng cơ bản, gọi mmap sao chép nội dung tệp vào bộ nhớ và msyncđược sử dụng để ghi lại từ bộ nhớ vào đĩa. Nếu tệp trên đĩa thay đổi, không có gì để phát hiện điều đó và tự động sửa đổi biểu diễn trong bộ nhớ trong tất cả các quy trình ánh xạ tệp.

EDIT: Hóa ra mmap () thực sự cố gắng giữ đồng bộ hóa trong bộ nhớ trong một số điều kiện. Nếu bản đồ chỉ được đọc từ, nó sẽ được giữ đồng bộ ngay cả khi các quá trình khác ghi vào tệp. Nếu nó được ghi vào (bằng cách gán cho vùng nhớ), điều gì xảy ra tùy thuộc vào cờ nào trong số các cờ MAP_SHARED hoặc MAP_PRIVATE bắt buộc được cung cấp cho mmap (). Nếu MAP_PRIVATE được cung cấp, bản đồ sẽ chuyển từ biểu diễn trên đĩa và dừng đồng bộ hóa cho đến khi bạn sử dụng msync (). Nếu MAP_SHARED được cung cấp, thì các bản cập nhật sẽ được hiển thị cho các quy trình khác có tệp được ánh xạ, cũng như (mặc dù điều này không ngay lập tức) đại diện trên đĩa.

Tôi vừa mở vim trên một tệp hiện có e, và chạy lệnh :w, trong khi inotifywait -m .chạy trong một thiết bị đầu cuối khác. Trong số một số bit lạ, đây là phần quan trọng tôi nhận được inotifywait.

./ MOVED_FROM e
./ MOVED_TO e~
./ CREATE e
./ OPEN e
./ MODIFY e
./ CLOSE_WRITE,CLOSE e
./ ATTRIB e
./ ATTRIB e
./ DELETE e~

Vim tạo một tệp mới và xóa tệp cũ. Tại sao nó làm điều này thay vì sửa đổi tệp nằm ngoài phạm vi của câu hỏi này, nhưng vấn đề là đây là một tệp mới và do đó có một nút mới.

Bây giờ, ý nghĩa của các quá trình khác khi sử dụng tệp này là gì? Nếu bạn có nghĩa là các quy trình đã mở tệp trong khi bạn đang thực hiện việc này, thì họ sẽ không thấy các thay đổi. Điều này là do, mặc dù họ đã mở một tệp có cùng đường dẫn, nhưng chúng không phải là cùng một tệp. Nếu bạn có nghĩa là các quy trình có thể mở tệp sau khi bạn thực hiện việc này, thì có, họ sẽ thấy các thay đổi. Họ sẽ mở tệp mới mà bạn đã tạo.

Điều quan trọng cần lưu ý là mặc dù các chương trình dường như có một tệp được mở trên giao diện người dùng, nhưng điều đó không có nghĩa là chúng sẽ giữ tệp mở trong quá trình này. Vim là một ví dụ về điều này, như được hiển thị ở trên.


3
" Nếu tệp trên đĩa thay đổi, không có gì để phát hiện điều đó và tự động sửa đổi biểu diễn trong bộ nhớ trong tất cả các quy trình ánh xạ tệp. " Điều gì sẽ thay đổi hệ thống tệp trên đĩa phía sau ánh xạ trang của hệ điều hành hệ thống? Bạn đang tưởng tượng một số quyền truy cập thô vào thiết bị khối hoặc thiết bị khối được chia sẻ qua iSCSI hoặc một cái gì đó?
David Schwartz

@ david-schwartz Không. Tôi đang tưởng tượng hai quá trình có tệp mở () 'ed. Quá trình 1 sử dụng mmap () để sao chép / ánh xạ nội dung tệp vào bộ nhớ. Sau đó, quy trình 2 sử dụng write () (và có thể fsync ()) để thay đổi nội dung trên đĩa. Tại thời điểm này, nội dung tệp quy trình 1 có trong bộ nhớ không phản ánh những thay đổi mà quy trình 2 đã làm, phải không?
JoL

Tất nhiên là không rồi. Mục đích của writechức năng là thay đổi dữ liệu tệp. Điều đó có thể hoặc không có nghĩa là thay đổi nội dung trên đĩa, nhưng bất cứ điều gì nó liên quan, đó là trách nhiệm của hệ thống tệp để làm cho đúng. Trong trường hợp này, nó sẽ liên quan đến việc sửa đổi trang bộ nhớ được ánh xạ và đánh dấu nó bị bẩn.
David Schwartz

@ david-schwartz Tôi đã thử nghiệm với mmap () và bạn là người đúng. Trong kịch bản tôi đã trình bày trong nhận xét trước đây, quy trình nội dung 1 có trong bộ nhớ (trong bản đồ) thực sự đã phản ánh các thay đổi trừ khi quy trình 1 đã ghi vào bộ nhớ trong ánh xạ trước. Điều này đúng ngay cả khi quy trình thay đổi 1 đã thực hiện ở một địa điểm khác với thay đổi được thực hiện bởi quy trình 2. Tôi đã cập nhật câu trả lời bỏ qua những gì không chính xác và thêm những gì tôi tìm thấy.
JoL

1
@ david-schwartz Xin lỗi, tôi không có ý ám chỉ rằng mmap hành xử khác với những gì tài liệu đã chỉ định, nhưng vâng tôi nghĩ rằng tôi đã đưa ra câu trả lời quá khó hiểu. Tôi nghĩ rằng nó vẫn còn trong phạm vi, nhưng câu hỏi, "liệu các quy trình khác sử dụng tệp này sẽ thấy những thay đổi tôi vừa thực hiện?", Dường như quá rộng. Có quá nhiều "nó phụ thuộc". Bởi vì nhu cầu của OP dường như hoàn toàn tự động, tôi đã cố gắng đưa ra một câu trả lời chính xác và bao quát hết mức có thể, nhưng tôi có thể đã sử dụng nó quá mức. Mặc dù vậy, tôi vẫn vui vì tôi đã học được một chút công bằng.
JoL
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.