Tôi nghi ngờ lý do tại sao có nhiều liên quan đến tầm nhìn / thiết kế hình thành Unix (và do đó là Linux), và những lợi thế bắt nguồn từ nó.
Không nghi ngờ gì có một lợi ích hiệu suất không đáng kể để không tạo ra một quy trình bổ sung, nhưng tôi nghĩ có nhiều hơn thế: Unix ban đầu có một phép ẩn dụ "mọi thứ là một tập tin", có một lợi thế không rõ ràng nhưng thanh lịch nếu bạn nhìn vào nó từ góc độ hệ thống, thay vì quan điểm kịch bản shell.
Giả sử bạn có null
chương trình dòng lệnh và /dev/null
nút thiết bị. Từ góc độ shell-script, foo | null
chương trình thực sự hữu ích và tiện lợi , và foo >/dev/null
mất một chút thời gian để gõ và có vẻ kỳ lạ.
Nhưng đây là hai bài tập:
Hãy thực hiện chương trình null
bằng các công cụ Unix hiện có và /dev/null
- dễ dàng : cat >/dev/null
. Làm xong.
Bạn có thể thực hiện /dev/null
trong điều khoản null
?
Bạn hoàn toàn đúng khi mã C chỉ loại bỏ đầu vào là không đáng kể, vì vậy có thể chưa rõ lý do tại sao có sẵn một tệp ảo cho tác vụ.
Hãy xem xét: hầu hết mọi ngôn ngữ lập trình đã cần để làm việc với các tệp, mô tả tệp và đường dẫn tệp, bởi vì chúng là một phần của mô hình "mọi thứ là một tệp" của Unix ngay từ đầu.
Nếu tất cả những gì bạn có là các chương trình ghi vào thiết bị xuất chuẩn, thì chương trình sẽ không quan tâm nếu bạn chuyển hướng chúng thành một tệp ảo nuốt tất cả ghi hoặc một đường dẫn vào một chương trình nuốt tất cả ghi.
Bây giờ nếu bạn có các chương trình lấy đường dẫn tệp để đọc hoặc ghi dữ liệu (hầu hết các chương trình đều làm như vậy) - và bạn muốn thêm chức năng "đầu vào trống" hoặc "loại bỏ đầu ra này" cho các chương trình đó - tốt, /dev/null
miễn phí.
Lưu ý rằng tính thanh lịch của nó là làm giảm độ phức tạp mã của tất cả các chương trình có liên quan - đối với mỗi usecase phổ biến nhưng đặc biệt mà hệ thống của bạn có thể cung cấp dưới dạng "tệp" với "tên tệp" thực tế, mã của bạn có thể tránh thêm lệnh tùy chỉnh tùy chọn -line và đường dẫn mã tùy chỉnh để xử lý.
Kỹ thuật phần mềm tốt thường phụ thuộc vào việc tìm các ẩn dụ tốt hoặc "tự nhiên" để trừu tượng hóa một số yếu tố của vấn đề theo cách dễ suy nghĩ hơn nhưng vẫn linh hoạt , để bạn có thể giải quyết cơ bản cùng một loạt các vấn đề cấp cao hơn mà không cần phải dành thời gian và năng lượng tinh thần để thực hiện lại các giải pháp cho các vấn đề cấp thấp hơn liên tục.
"Tất cả mọi thứ là một tập tin" có vẻ là một phép ẩn dụ đó để truy cập vào các nguồn tài nguyên: Bạn gọi open
của một con đường được đưa ra trong một không gian tên heirarchical, nhận được một tài liệu tham khảo (mô tả tập tin) cho các đối tượng, và bạn có thể read
và write
, vv trên file descriptor. Stdin / stdout / stderr của bạn cũng là các mô tả tập tin vừa được mở trước cho bạn. Các đường ống của bạn chỉ là các tập tin và mô tả tập tin, và chuyển hướng tập tin cho phép bạn dán tất cả các phần này lại với nhau.
Unix đã thành công nhiều như nó đã làm một phần vì các trừu tượng này hoạt động tốt như thế nào và /dev/null
được hiểu rõ nhất như là một phần của toàn bộ.
PS Thật đáng để xem phiên bản Unix của "mọi thứ là một tập tin" và những thứ như /dev/null
bước đầu tiên hướng tới sự khái quát hóa linh hoạt và mạnh mẽ hơn của phép ẩn dụ đã được triển khai trong nhiều hệ thống tiếp theo.
Ví dụ, trong các đối tượng giống như tệp đặc biệt của Unix /dev/null
phải được triển khai trong chính kernel, nhưng hóa ra nó đủ hữu ích để hiển thị chức năng ở dạng tệp / thư mục mà từ đó nhiều hệ thống đã được tạo ra để cung cấp một cách cho các chương trình Để làm việc đó.
Một trong những cái đầu tiên là hệ điều hành Plan 9, được tạo ra bởi một số người đã tạo ra Unix. Sau đó, GNU Hurd đã làm một cái gì đó tương tự với "dịch giả" của nó. Trong khi đó, Linux cuối cùng cũng đã nhận được FUSE (hiện đã lan sang các hệ thống chính thống khác).
cat foo | bar
là lý do tại sao tồi tệ hơn nhiều (ở quy mô) hơnbar <foo
.cat
là một chương trình tầm thường, nhưng ngay cả một chương trình tầm thường cũng tạo ra chi phí (một số trong số đó cụ thể theo ngữ nghĩa của FIFO - vì các chương trình không thểseek()
bên trong FIFO, ví dụ, một chương trình có thể được thực hiện hiệu quả với việc tìm kiếm có thể thực hiện các hoạt động tốn kém hơn nhiều khi được cung cấp một đường ống dẫn, với một thiết bị ký tự như/dev/null
nó có thể giả mạo các hoạt động đó hoặc với một tệp thực sự, nó có thể thực hiện chúng, nhưng một FIFO không cho phép bất kỳ loại xử lý theo ngữ cảnh nào).