2008-11-06 29 views
11

Khi chúng tôi thực hiện một ngã ba trong Unix, mở xử lý tập tin được thừa kế, và nếu chúng ta không cần phải sử dụng chúng, chúng ta nên đóng chúng. Tuy nhiên, khi chúng tôi sử dụng thư viện, có thể mở các tệp xử lý mà chúng tôi không có quyền truy cập vào trình xử lý. Làm cách nào để chúng tôi kiểm tra các tệp xử lý mở này?Làm cách nào để tìm tệp xử lý quá trình của tôi đã mở trong Linux?

Trả lời

14

Nếu thư viện đang mở các tệp mà bạn không biết, bạn biết chúng không cần chúng sau khi rẽ nhánh như thế nào? Các xử lý chưa được xuất hiện là một chi tiết thư viện nội bộ, nếu thư viện muốn chúng đóng, nó sẽ đăng ký một trình xử lý atfork() để đóng chúng lại. Đi vòng quanh phía sau một đoạn mã nào đó đóng lại các tập tin của nó sau lưng nó sẽ dẫn đến các vấn đề khó gỡ rối vì thư viện sẽ báo lỗi bất ngờ khi nó cố gắng làm việc với một tay cầm nó biết nó mở đúng cách, nhưng không đóng.

0

Thư viện hợp lý sẽ luôn có các chức năng miễn phí mọi tài nguyên (ví dụ: xử lý tệp) mà chúng đã phân bổ.

0

Chỉ cần một liên kết, nhưng có vẻ như hữu ích: How many open files? tại netadmintools.com. Dường như sử dụng/proc điều tra để tìm hiểu về một quá trình 'mở tập tin, không chắc chắn nếu đó là cách duy nhất hoặc nếu có một API. Phân tích tệp cho loại thông tin này có thể hơi ... lộn xộn. Ngoài ra,/proc cũng có thể bị phản đối, một thứ cần kiểm tra.

16

Trong Linux, bạn có thể kiểm tra /proc/<pid>/fd thư mục - cho mỗi fd mở sẽ có một tệp, được đặt tên là xử lý. Tôi gần như chắc chắn theo cách này là không di động.

Hoặc bạn có thể sử dụng lsof - có sẵn cho Linux, AIX, FreeBSD và NetBSD, theo số man lsof.

1

Tôi đồng ý với những gì người khác đã nói về việc đóng các tệp ngẫu nhiên là nguy hiểm. Bạn có thể sẽ gửi một số báo cáo lỗi khá thú vị cho tất cả các công cụ của bên thứ ba của bạn.

Điều đó nói rằng, nếu bạn biết bạn sẽ không cần mở các tệp đó, bạn luôn có thể xem tất cả các mô tả tệp hợp lệ (1 đến 65535, IIRC) và đóng mọi thứ bạn không nhận ra.

+0

Bạn có thể sử dụng lệnh getdtablesize (2) để nhận số lượng mục nhập trong bảng mô tả tệp của quy trình. –

0

Đây có phải là vấn đề thiết kế không? Có thể cho quá trình của bạn để ngã ba trước khi khởi tạo libs mở các tập tin đó?

2

Để bắt đầu, bạn không thực sự cần quan tâm nhiều đến các mô tả tệp mở mà bạn không biết. Nếu bạn biết bạn sẽ không viết lại cho họ nữa, việc đóng chúng lại là một ý tưởng hay và không đau - bạn chỉ cần làm một cái nĩa() sau khi tất cả, các fds được mở hai lần. Nhưng tương tự như vậy, nếu bạn để chúng mở, chúng sẽ không làm phiền bạn - dù sao thì, bạn cũng không biết về chúng, bạn có lẽ sẽ không viết ngẫu nhiên cho chúng.

Đối với những gì thư viện của bên thứ ba của bạn sẽ làm, đó là một chút của một quăng lên một trong hai cách. Một số có thể không mong đợi để chạy vào một tình huống với một ngã ba(), và có thể kết thúc vô tình bằng văn bản cho cùng một fd từ hai quá trình mà không cần bất kỳ đồng bộ hóa. Những người khác có lẽ không mong đợi để có bạn đóng fds của họ trên chúng. Bạn sẽ phải kiểm tra. Đây là lý do tại sao bạn nên mở ngẫu nhiên một bộ mô tả tệp trong thư viện và không đưa nó cho người gọi để quản lý.

Tất cả những gì đã nói, theo tinh thần trả lời câu hỏi ban đầu, không có cách nào đặc biệt tốt. Bạn có thể gọi dup() hoặc dup2() trên bộ mô tả tệp; nếu đã đóng, cuộc gọi sẽ không thành công với EBADF.Vì vậy, bạn có thể nói:

int newfd = dup(oldfd); 
if (newfd > 0) 
{ 
    close(newfd); 
    close(oldfd); 
} 

nhưng tại thời điểm đó bạn cũng giống như sung túc nói close(oldfd) ở nơi đầu tiên và bỏ qua bất kỳ EBADFs.

Giả sử bạn vẫn muốn chọn tùy chọn hạt nhân để đóng mọi thứ, bạn cần phải tìm số lượng tối đa các bộ mô tả tệp đang mở có thể. Giả sử 1 đến 65.535 không phải là một ý tưởng tốt. Trước hết, fds bắt đầu ở 0, tất nhiên, nhưng cũng không có giới hạn trên cụ thể được xác định. Để có thể di chuyển, số sysconf(_SC_OPEN_MAX) của POSIX sẽ cho bạn biết, trên bất kỳ hệ thống POSIX lành mạnh nào, mặc dù nói đúng là tùy chọn. Nếu bạn cảm thấy hoang tưởng, hãy kiểm tra giá trị trả về cho -1, mặc dù tại thời điểm đó bạn chủ yếu phải giảm giá trị hardcoded anyway (1024 sẽ là tốt trừ khi bạn đang làm một cái gì đó cực kỳ kỳ lạ). Hoặc nếu bạn tốt với Linux cụ thể, bạn có thể đào sâu trong/proc.

Đừng quên không đóng các fds 0, 1 và 2 - điều đó thực sự có thể gây nhầm lẫn cho mọi thứ.

+0

Vâng, nói chung bạn không quan tâm cho đến khi bạn đạt đến mức độ hạn chế và bắt đầu nhận được quá nhiều lỗi mở tệp. – philant

5

Như đã đề cập trong câu trả lời của @Louis Gerbarg, các thư viện có thể chờ xử lý tệp được giữ mở trên fork() (được cho là, sau khi tất cả, một bản sao gần giống hệt của quy trình gốc).

Sự cố mà hầu hết mọi người gặp phải là trên exec() thường theo sau fork(). Ở đây, giải pháp chính xác là cho thư viện đã tạo các chốt để đánh dấu chúng là close-on-exec (FD_CLOEXEC).

Trên thư viện được sử dụng bởi các chương trình đa luồng, có một điều kiện chủng tộc giữa thư viện tạo bộ xử lý tệp và đặt FD_CLOEXEC trên đó (một chủ đề khác có thể fork() giữa cả hai thao tác). Để khắc phục sự cố đó, O_CLOEXEC đã được giới thiệu trong hạt nhân Linux.

14

Bạn có thể làm từ vỏ:

lsof -P -n -p _PID_

đâu PID là quá trình pid của bạn.

+0

Điểm làm việc trên vỏ là gì? Làm thế nào tôi có thể nhận được vào quá trình con chia tay của tôi để đóng nó? – sep

+1

@sep: câu trả lời này có lẽ không phải là tốt nhất khi xem xét mô tả vấn đề của bạn, nhưng nó chắc chắn sẽ đặt câu hỏi thực tế. Vì vậy, cảm ơn bạn Felipe đã giúp tôi tìm thấy các xử lý của quá trình của tôi :) – Superole

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