Điều gì xảy ra khi tôi đóng () một mô tả tập tin?


16

Tôi đang cố gắng để có được toàn bộ hình ảnh với mô tả tập tin. Nói rằng tôi có process1 mà ban đầu có các mô tả tệp này:

 _process1_
|          |
| 0 stdin  |
| 1 stdout |
| 2 stderr |
|__________|

Sau đó, tôi đóng mô tả tập tin 1:

close(1);

Bộ mô tả tệp 1 dịch (điểm) sang cấu trúc FILE xuất sắc trong Bảng tệp mở của kernel .

Với mã ở trên, bộ mô tả tệp 1 sẽ bị xóa khỏi bảng của quy trình, trở thành:

 _process1_
|          |
| 0 stdin  |
| 2 stderr |
|__________|

Nhưng những gì xảy ra trong kernel? Liệu stdoutcấu trúc FILE được deallocated? Làm thế nào là có thể nếu thiết bị xuất chuẩn là một tệp đặc biệt (màn hình) và có thể được sử dụng bởi các quy trình khác? Còn các cấu trúc FILE chỉ là các tệp bình thường (ví dụ .txt) thì sao? Điều gì nếu một tập tin như vậy đang được sử dụng bởi một quá trình khác?

Câu trả lời:


13

Bộ mô tả tệp 1 dịch sang cấu trúc FILE xuất sắc trong Bảng tệp mở của hạt nhân.

Đây là một sự hiểu lầm. Bảng tệp của kernel không liên quan gì đến cấu trúc tệp không gian người dùng.

Trong mọi trường hợp, kernel có hai cấp độ không xác định. Có cấu trúc bên trong đại diện cho chính tập tin, được tham chiếu tính. Có một "mô tả tệp mở" được tính tham chiếu. Và sau đó là xử lý tập tin, không được tham chiếu tính. Cấu trúc tệp chỉ đường đến chính nút inode. Mô tả tệp mở chứa những thứ như chế độ mở và con trỏ tệp.

Khi bạn gọi gần, bạn luôn đóng xử lý tệp. Khi đóng một tập tin xử lý, số tham chiếu trên mô tả tập tin mở của nó bị giảm. Nếu nó về 0, mô tả tệp mở cũng được phát hành và số tham chiếu trên chính tệp đó bị giảm. Chỉ khi điều đó về 0 thì cấu trúc tệp của kernel mới được giải phóng.

Không có cơ hội cho một quy trình phát hành tài nguyên mà quy trình khác đang sử dụng vì tài nguyên được chia sẻ được tính tham chiếu.


Tôi có một chút khó khăn với sự hiểu biết về thuật ngữ trong câu trả lời của bạn. Tôi đoán rằng con trỏ tập tin có nghĩa là "tập tin bù đắp". Đó có phải ý của bạn? Ngoài ra những gì bạn có nghĩa là xử lý tập tin ?
Geek

Điều đó đúng, bởi "tập tin bù", ý tôi là sự bù mà lần đọc hoặc ghi tiếp theo sẽ xảy ra. "Xử lý tệp" là một liên kết giữa một quy trình và mô tả tệp mở - đó là những gì bạn nhận lại khi openthành công.
David Schwartz

6

Trong trường hợp này sẽ không có nhiều xảy ra. stdin, stdout và stderr đều có xu hướng là bản sao của cùng một mô tả tập tin. Bộ đếm tham chiếu cho bộ mô tả tập tin sẽ được giảm bởi một. Bộ mô tả tệp giống nhau thường được giữ bởi trình bao mà chương trình được chạy, do đó bộ mô tả tệp cần được giữ.

Hạt nhân giữ số tham chiếu cho tất cả các tệp (inodes) đang mở. Miễn là số tham chiếu lớn hơn 0, tập tin sẽ được lưu giữ. Tôi sẽ mong đợi một bộ đếm riêng được giữ cho xử lý tập tin mở. Một khi điều này đạt đến 0, kernel có thể giải phóng bộ nhớ được sử dụng bởi tập tin xử lý.

Khi tất cả các tham chiếu đến tệp (mục nhập thư mục và xử lý tệp) đã bị xóa, mã hệ thống tệp sẽ đánh dấu nút để sử dụng lại. Bất kỳ khối nào tập tin đã có sẵn để phân bổ. Nhiều hệ thống tập tin sẽ xóa các con trỏ khối trong inode khi nó được phát hành. Điều này làm cho việc khôi phục một tập tin bị xóa khó khăn. Cập nhật vào đĩa có thể được đệm và hoàn thành sau đó.


1
Hai câu hỏi: (1) các mô tả tập tin thực sự được tính lại? Khi bạn điều khiển-a a cat > some.file, mèo nhận được EOF trên stdin, nhưng vỏ thì không. (2) Tại sao đếm tham chiếu? Tại sao không phải là một số hình thức thu gom rác? Không phải là tốt hơn nhiều trong không gian người dùng?
Bruce Ediger

Mở rộng dựa trên câu trả lời của BillThor: Trong trường hợp bình thường, stdin, stdout và stderr chỉ là các tệp xử lý mở cho thiết bị TTY. Vì vậy, nếu bạn đóng tay cầm tập tin, thiết bị TTY đó vẫn ở đó và thậm chí có thể được mở lại sau đó.
Patrick

1
@BruceEdiger: (1) khi shell chạy cat > some.filenhững gì nó thực sự đang làm, mở ra 'some.file' và gán nó cho mô tả tệp 1, sau đó nó thực hiện exec("cat"). Khi một tiến trình được thực thi () 'd, nó sẽ kế thừa các mô tả tệp đang mở.
Patrick

@BruceEdiger (2) Đếm tham chiếu là một hình thức thu gom rác hoàn toàn tốt khi nó được sử dụng trên các cấu trúc dữ liệu không chứa con trỏ tới (hoặc chuỗi con trỏ kết thúc) các cấu trúc dữ liệu khác cùng loại. Ngoài ra, điều này đang xảy ra trong không gian kernel (không phải là nó rất quan trọng).
Gilles 'SO- ngừng trở nên xấu xa'
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.