Các tập tin được mở bởi các quá trình được tải vào RAM?


24

Các lệnh , ví dụ sed, các chương trình và chương trình được mã hóa logic bên trong một tệp và các tệp này nằm ở đâu đó trên đĩa cứng. Tuy nhiên, khi các lệnh đang được chạy, một bản sao các tệp của chúng từ đĩa cứng sẽ được đưa vào RAM , nơi chúng xuất hiện và có thể thực hiện công cụ và được gọi là các quy trình .

Các quy trình có thể sử dụng các tệp khác, đọc hoặc ghi vào chúng và nếu chúng làm các tệp đó được gọi là các tệp đang mở. Có một lệnh để liệt kê tất cả các tệp đang mở bởi tất cả các quy trình đang chạy : lsof.

OK, vì vậy điều tôi băn khoăn là nếu tuổi thọ của một lệnh, một trên đĩa cứng, thì cái kia trong RAM cũng đúng với các loại tệp khác, ví dụ như những người không có lập trình logic, nhưng chỉ đơn giản là các thùng chứa cho dữ liệu.

Giả định của tôi là, các tệp được mở bởi các tiến trình cũng được tải vào RAM. Tôi không biết nó có đúng không, nó chỉ là một trực giác.

Xin vui lòng, ai đó có thể có ý nghĩa của nó?


Câu trả lời:


27

Tuy nhiên, khi các lệnh đang được chạy, một bản sao các tệp của chúng từ đĩa cứng sẽ được đưa vào RAM,

Điều này là sai (nói chung). Khi một chương trình được thực thi (thông qua thực thi ( 2) ...), quá trình (chạy chương trình đó) sẽ thay đổi không gian địa chỉ ảo của nó và kernel đang cấu hình lại MMU cho mục đích đó. Đọc thêm về bộ nhớ ảo . Lưu ý rằng các chương trình ứng dụng có thể thay đổi không gian địa chỉ ảo của chúng bằng mmap (2) & munmap& mprotect (2) , cũng được sử dụng bởi trình liên kết động (xem ld-linux (8) ). Xem thêm madvise (2) & posix_fadvise (2) & mlock (2) .

Các lỗi trang trong tương lai sẽ được xử lý bởi kernel để tải các trang (một cách lười biếng) từ tệp thực thi. Đọc cũng về đập .

Nhân duy trì bộ đệm trang lớn . Đọc thêm về copy-on-write . Xem thêm bài đọc (2) .

OK, vì vậy điều tôi băn khoăn là nếu tuổi thọ của một lệnh, một trên đĩa cứng, thì cái kia trong RAM cũng đúng với các loại tệp khác, ví dụ như những người không có lập trình logic, nhưng chỉ đơn giản là các thùng chứa cho dữ liệu.

Đối với các cuộc gọi hệ thống như đọc (2)ghi (2) bộ đệm trang cũng được sử dụng. Nếu dữ liệu cần đọc nằm trong đó, sẽ không có IO nào được thực hiện. Nếu cần IO IO, dữ liệu đọc sẽ rất có thể được đặt trong bộ đệm của trang. Vì vậy, trong thực tế, nếu bạn chạy cùng một lệnh hai lần, có thể xảy ra rằng không có I / O vật lý nào được thực hiện vào đĩa lần thứ hai (nếu bạn có một đĩa cứng quay cũ - không phải là SSD - bạn có thể nghe thấy điều đó; hoặc quan sát cẩn thận đèn LED đĩa cứng của bạn).

Tôi khuyên bạn nên đọc một cuốn sách như Hệ điều hành: Ba phần dễ dàng (có thể tải xuống miễn phí, một tệp PDF cho mỗi chương) giải thích tất cả điều này.

Xem thêm Linux Ate RAM của tôi và chạy lệnh như xosview, top, htophoặc cat /proc/self/mapshoặc cat /proc/$$/maps(xem proc (5) ).

Tái bút Tôi đang tập trung vào Linux, nhưng các hệ điều hành khác cũng có bộ nhớ ảo và bộ đệm trang.


35

Không, một tập tin không được tự động đọc vào bộ nhớ bằng cách mở nó. Điều đó sẽ rất kém hiệu quả. sed, ví dụ, đọc từng dòng đầu vào của nó, cũng như nhiều công cụ Unix khác. Nó hiếm khi phải giữ nhiều hơn dòng hiện tại trong bộ nhớ.

Với awknó cũng vậy. Nó đọc một bản ghi tại một thời điểm, theo mặc định là một dòng. Nếu bạn lưu trữ các phần của dữ liệu đầu vào trong các biến, đó sẽ là phần phụ, tất nhiên là 1 .

Một số người có thói quen làm những việc như

for line in $(cat file); do ...; done

Vì shell sẽ phải mở rộng $(cat file)hoàn toàn thay thế lệnh trước khi chạy ngay cả lần lặp đầu tiên của forvòng lặp, điều này sẽ đọc toàn bộ filevào bộ nhớ (vào bộ nhớ được sử dụng bởi shell thực thi forvòng lặp). Điều này là một chút ngớ ngẩn và cũng không hay. Thay vào đó, người ta nên làm

while IFS= read -r line; do ...; done <file

Điều này sẽ xử lý filetừng dòng (nhưng đọc Đọc "IFS = read -r line" ).

Mặc dù vậy, việc xử lý các tệp theo từng dòng trong trình bao chỉ hiếm khi cần thiết, vì hầu hết các tiện ích đều được định hướng theo dòng (xem Tại sao sử dụng vòng lặp shell để xử lý văn bản được coi là thực tiễn xấu? ).

Tôi đang làm việc trong tin sinh học, và khi xử lý một lượng lớn dữ liệu gen, tôi sẽ không thể làm được gì trừ khi tôi chỉ giữ các bit dữ liệu thực sự cần thiết trong bộ nhớ. Ví dụ: khi tôi cần loại bỏ các bit dữ liệu có thể được sử dụng để xác định các cá nhân từ bộ dữ liệu 1 terabyte chứa các biến thể DNA trong tệp VCF (vì loại dữ liệu đó không thể được công khai), tôi thực hiện theo từng dòng xử lý với một awkchương trình đơn giản (điều này là có thể vì định dạng VCF là định hướng theo dòng). Tôi không đọc tệp vào bộ nhớ, xử lý nó ở đó và viết lại ra! Nếu tệp được nén, tôi sẽ cung cấp cho nó thông qua zcathoặc gzip -d -c, do gzipxử lý luồng dữ liệu, cũng sẽ không đọc toàn bộ tệp vào bộ nhớ.

Ngay cả với các định dạng tệp không được định hướng theo dòng, như JSON hoặc XML, vẫn có các trình phân tích cú pháp luồng giúp xử lý các tệp lớn mà không lưu trữ tất cả trong RAM.

Với các tệp thực thi, sẽ phức tạp hơn một chút vì các thư viện dùng chung có thể được tải theo yêu cầu và / hoặc được chia sẻ giữa các quy trình ( ví dụ như Tải thư viện dùng chung và sử dụng RAM ).

Bộ nhớ đệm là thứ tôi chưa đề cập ở đây. Đây là hành động sử dụng RAM để giữ các phần dữ liệu được truy cập thường xuyên. Các tệp nhỏ hơn (ví dụ: tệp thực thi) có thể được HĐH lưu vào bộ nhớ cache với hy vọng rằng người dùng sẽ thực hiện nhiều tham chiếu đến chúng. Ngoài lần đọc tệp đầu tiên, các lần truy cập tiếp theo sẽ được thực hiện vào RAM thay vì vào đĩa. Bộ nhớ đệm, như bộ đệm của đầu vào và đầu ra thường phần lớn trong suốt đối với người dùng và dung lượng bộ nhớ được sử dụng để lưu trữ mọi thứ có thể thay đổi linh hoạt tùy thuộc vào lượng RAM được phân bổ bởi các ứng dụng, v.v.


1 Về mặt kỹ thuật, hầu hết các chương trình có thể đọc một đoạn của dữ liệu đầu vào tại một thời điểm, hoặc sử dụng đệm rõ ràng, hoặc ngầm thông qua các đệm rằng I / O thư viện tiêu chuẩn làm, và sau đó hiện dòng đoạn bởi dòng mã của người dùng. Việc đọc nhiều kích thước khối của đĩa sẽ hiệu quả hơn nhiều so với một ký tự tại một thời điểm. Kích thước chunk này sẽ hiếm khi lớn hơn một số kilobyte.


bạn nói, có thể tải các thư viện chia sẻ vào RAM, cũng có thể tải một tệp thông thường, chỉ chứa dữ liệu vào RAM, ngay cả khi nó không có ý nghĩa?
cá mập

1
@sharkant Tất nhiên rồi. Đó chỉ là vấn đề thêm dữ liệu vào một biến (hoặc mảng, hoặc hàm băm hoặc bất kỳ cấu trúc dữ liệu nào mà ngôn ngữ trong câu hỏi cung cấp) cho đến khi tất cả các tệp được lưu trữ. Với awk, { a[i++] = $0 }sẽ thêm tất cả các dòng của tệp đầu vào vào mảng a. Bạn cũng có thể muốn tìm kiếm chức năng C mmap(), nhưng việc sử dụng nó có thể hơi lạc đề ở đây.
Kusalananda

6
sed, awkvà các chương trình định hướng dòng khác không đọc một dòng vào bộ nhớ, vì các tệp văn bản thuần không chứa chỉ mục dòng và API hệ thống tệp và phần cứng lưu trữ cấp thấp đọc một hoặc nhiều "cung" (thường là 512 hoặc 1024 byte) tại một thời điểm. Tôi sẽ ngạc nhiên nếu hệ điều hành đọc được ít hơn 8KB trước khi dòng đầu tiên được xử lý.
Russell Borogove

5
Mặc dù một tiện ích như sedsẽ chỉ đọc một dòng tại một thời điểm vào bộ nhớ, nhưng điều đáng nói là hệ điều hành sẽ sử dụng ram miễn phí để lưu các tệp để chúng có thể được truy cập nhanh chóng. Nếu bạn đang chạy sedtrên một tệp nhỏ hơn, có khả năng HĐH sẽ lưu toàn bộ tệp trong bộ nhớ và thao tác sẽ được thực hiện hoàn toàn trong RAM. Xem: vi.wikipedia.org/wiki/Page_cache
Sean Dawson

5
@sharkant Có một tập tin hoàn toàn có thể truy cập trong bộ nhớ (xem câu trả lời khác, mmap là từ khóa hệ thống gọi ở đây). Ví dụ, một hệ thống cơ sở dữ liệu thường muốn có, để dễ dàng và tốc độ truy cập, toàn bộ cơ sở dữ liệu hoặc ít nhất một số chỉ mục được ánh xạ vào bộ nhớ. Điều này không nhất thiết có nghĩa là toàn bộ thực sự nằm trong bộ nhớ. HĐH có thể tự do "giả vờ" rằng tệp nằm trong bộ nhớ. Nó nói với ứng dụng "ở đây, trong phạm vi bộ nhớ này là tệp của bạn" và chỉ khi đọc xong (giống như khi quá trình được hoán đổi), dữ liệu thực sự được đọc.
Jonas Schäfer

5

Không. Mặc dù có nhiều RAM trong những ngày này thật tuyệt vời, đã có lúc RAM là một nguồn tài nguyên rất hạn chế (tôi đã học lập trình trên VAX 11/750 với 2 MB RAM) và điều duy nhất trong RAM là các trang dữ liệu và có thể thực thi được của các quy trình hoạt động và dữ liệu tệp trong bộ đệm bộ đệm.
Bộ đệm bộ đệm đã bị xóa và các trang dữ liệu bị tráo đổi. Và thường xuyên có lúc. Các trang thực thi chỉ đọc đã được ghi trên bảng và trang được đánh dấu để nếu chương trình chạm vào các trang đó một lần nữa, chúng sẽ được phân trang từ hệ thống tệp. Dữ liệu được phân trang từ trao đổi. Như đã lưu ý ở trên, thư viện STDIO lấy dữ liệu theo khối và được chương trình thu được khi cần: fgetc, fget, fread, v.v. Với mmap, một tệp có thể được ánh xạ vào không gian địa chỉ của một quá trình, như được thực hiện với đối tượng thư viện chia sẻ hoặc thậm chí các tập tin thông thường. Có, bạn có thể có một số mức độ kiểm soát nếu nó có trong RAM hay không (mlock), nhưng nó chỉ đi xa hơn (xem phần mã lỗi của mlock).


1
Câu lệnh "RAM của bạn sẽ quá nhỏ so với các tệp của bạn" hiện tại là đúng như thời kỳ cũ của VAX.
Federico Poloni

1
@Federico_Poloni Hôm nay không hoàn toàn đúng như vậy. Ở nhà tuyển dụng cuối cùng của chúng tôi, chúng tôi đã có một PC loại máy trạm với 1Tb RAM và chỉ 0,5Tb đĩa cứng. (Lớp vấn đề: đầu vào nhỏ, đầu ra trung bình, mảng truy cập ngẫu nhiên lớn trong quá trình tính toán).
nigel 222
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.