Theo mặc định, bộ mô tả tệp vẫn mở trên các hàm exec. Lợi ích có lẽ dễ hiểu đối với người mô tả 0-2. Nhưng có một trường hợp sử dụng thực tế để giữ cho các mô tả khác mở? Có ứng dụng thực sự nào dựa vào thực tế này không?
Theo mặc định, bộ mô tả tệp vẫn mở trên các hàm exec. Lợi ích có lẽ dễ hiểu đối với người mô tả 0-2. Nhưng có một trường hợp sử dụng thực tế để giữ cho các mô tả khác mở? Có ứng dụng thực sự nào dựa vào thực tế này không?
Câu trả lời:
Có một cờ bạn có thể đặt trên một bộ mô tả tệp (theo open()
: O_CLOEXEC trở lên với fcntl()
: FD_CLOEXEC) nếu bạn không muốn fd đó được chuyển đến các lệnh được thực thi.
Đó là những gì bạn nên làm cho các mô tả tệp nội bộ của bạn nếu bạn sẽ thực thi các lệnh.
Trong shell, đó là những gì ksh93
khi bạn làm exec 3< some-file
chẳng hạn. Đối với các shell hoặc fds khác được mở bằng { cmd1; cmd2; } 3< file
, bạn cần phải đóng bằng tay nếu bạn không muốn cmd1
hoặc cmd2
truy cập vào fd đó : {cmd1 3<&-; cmd2; } 3< file
. Đó là cách thực hành tốt nhưng không phải lúc nào cũng tuân theo vì nó thường không quan trọng nếu bạn không thực hiện .
Bây giờ, cho dù tính năng này là hữu ích. Vâng, một số lệnh dựa vào nó.
Một vài lệnh lấy một bộ mô tả tệp làm đối số có nghĩa là đã được mở bởi một người gọi. Một vài ví dụ xuất hiện trong tâm trí:
xterm
với -S
tùy chọn của nóqemu
cho những thứ khác nhauflock
(để khóa một tập tin trên fd của người gọi)test
lệnh aka [
cho nó -t
lựa chọn (OK các test
tiện ích được xây dựng ở hầu hết các Bourne giống như vỏ hiện nay, nhưng vẫn còn là một test
lệnh có thể được thực hiện).dialog
cần mô tả tập tin cho đầu vào từ người dùng, đầu ra và lỗi cho người dùng và đầu vào và đầu ra cho người gọi, vì vậy bạn có thể sử dụng thêm fds cho điều đó.gpg
hoặc openssl
mà bạn có thể chỉ định một bộ mô tả tệp để truyền đạt cụm mật khẩu hoặc thông tin khác.Có một số tiện ích của trình trợ giúp (ví dụ, nhu cầu thực thi có thể là chạy một phần của lệnh với tư cách là một người dùng hoặc nhóm khác sử dụng tệp thực thi setuid / setgid) dựa vào đó.
Quá trình thay thế phụ thuộc vào nó:
Trong, diff <(cmd1) <(cmd2)
2 mô tả tệp (cho các đường ống) được truyền tới diff
và diff truy cập chúng bằng cách mở chúng thông qua đặc biệt / dev / fd / n được truyền dưới dạng đối số.
Đối với các shell không có quá trình thay thế, bạn cũng thực hiện tương tự với các thao tác như:
cm1 | { cmd2 | diff /dev/fd/3 -; } 3<&0
TinyMUSH và có lẽ nhiều bộ mã anh chị em và trẻ em của nó sử dụng chức năng này của exec để có hiệu quả tuyệt vời. Người ta có thể ra lệnh khởi động lại máy chủ, có thể nâng cấp lên nhị phân hoàn toàn mới, trong khi vẫn để người dùng kết nối.
Điều này được thực hiện bằng cách viết một db thông tin nhỏ về mỗi người dùng được kết nối, bao gồm cả mô tả tệp của họ. Bản sao TinyMUSH mới được thực thi đọc db khởi động lại để khôi phục kiến thức về người dùng được kết nối và chọn nơi nó rời đi.
Kết quả cuối cùng: các tính năng mới được phát hành chỉ với một khoảng dừng ngắn hiển thị cho người dùng.
Nginx làm một cái gì đó tương tự như để nâng cấp nhị phân mà không mất kết nối.
Ổ cắm được kết nối có thể được chuyển cho một tiến trình con theo cách này, vì vậy, ví dụ một máy chủ mạng chấp nhận các kết nối đến có thể chuyển hoàn toàn việc xử lý chúng sang quy trình khác.
Xem mã nguồn cho inetd , ví dụ phổ biến.
inetd
sử dụng file descriptor 0
, 1
và 2
với mục đích đi qua các ổ cắm mở là một quy ước rằng dòng lên với việc giữ những mở vì lý do khác.
main
và run_service
. Đây không phải là một ví dụ về việc chuyển fds ngoài 0,1,2, đó là câu hỏi.
Tôi không nghĩ có những chương trình thực tế, chung chung vượt qua mọi thứ ngoài mô tả 2. Nếu có, chương trình exec () ed sẽ phải giả sử số mô tả tệp được mã hóa cứng, vd
write(3, ...);
hoặc là
fp = fdopen(3, "r");
đó là thực hành mã hóa xấu. Chỉ trong trường hợp bạn kiểm soát chặt chẽ cả chương trình phụ huynh và trẻ em, và không ai khác có thể can thiệp, điều đó có thể có ý nghĩa.
closefrom(2)
cuộc gọi).