Tại sao sử dụng một ống có tên thay vì một tập tin?


42

Gần đây tôi đã đọc về các đường ống được đặt tên và tôi không thể hiểu tại sao chúng tồn tại.
Tôi đã đọc ở đâu đó rằng sử dụng một ống có tên ít tốn thời gian hơn so với sử dụng tệp.

Tại sao cái này rất?
Các ống được đặt tên cũng phải được lưu trữ trong bộ nhớ (và có thể hoán đổi, giống như các tệp).
Theo như tôi có thể thấy, họ phải có một nút inode phải được tham chiếu bởi thư mục hiện tại, giống như các tệp. Ngoài ra, chúng phải được gỡ bỏ bởi lập trình viên, giống như các tập tin.

Vậy lợi thế nằm ở đâu?


Đây không phải là một phần của bài tập trên lớp, phải không?
don.joey

6
không ... thực sự tôi đã xem qua một số ghi chú bài giảng khi tôi tìm thấy câu hỏi này và tôi không thể trả lời nó ... và nếu đó là một bài tập, tôi không thấy nó có liên quan như thế nào ... nó không giống như Tôi sẽ không tìm kiếm câu trả lời cho đến khi tôi tìm thấy nó
user3122885

Câu trả lời:


41

Hầu hết mọi thứ trong Linux đều có thể được coi là một tệp , nhưng sự khác biệt chính giữa tệp thông thườngống có tên là ống có tên là một phiên bản đặc biệt của tệp không có nội dung trên hệ thống tệp.

Đây là trích dẫn từ man fifo:

Một tệp đặc biệt của FIFO (một ống có tên) tương tự như một ống, ngoại trừ việc nó được truy cập như một phần của hệ thống tệp. Nó có thể được mở bằng nhiều quá trình để đọc hoặc viết. Khi các quá trình đang trao đổi dữ liệu thông qua FIFO, kernel sẽ chuyển tất cả dữ liệu bên trong mà không ghi nó vào hệ thống tập tin. Do đó, tệp đặc biệt FIFO không có nội dung trên hệ thống tệp; mục hệ thống tập tin chỉ đóng vai trò là điểm tham chiếu để các quy trình có thể truy cập vào đường ống bằng cách sử dụng tên trong hệ thống tập tin.

Hạt nhân duy trì chính xác một đối tượng ống cho mỗi tệp đặc biệt FIFO được mở bằng ít nhất một quy trình. FIFO phải được mở ở cả hai đầu (đọc và viết) trước khi dữ liệu có thể được thông qua. Thông thường, mở các khối FIFO cho đến khi đầu kia cũng được mở.

Vì vậy, thực sự một ống có tên không làm gì cho đến khi một số quá trình đọc và ghi vào nó. Nó không chiếm bất kỳ dung lượng nào trên đĩa cứng (ngoại trừ một chút thông tin meta), nó không sử dụng CPU.

Bạn có thể kiểm tra nó bằng cách làm điều này:

Tạo một đường ống có tên

$ mkfifo /tmp/testpipe

Đi đến một số thư mục, ví dụ /home/user/Documents, và gzip mọi thứ bên trong nó, sử dụng ống có tên.

$ cd /home/user/Documents
$ tar cvf - . | gzip > /tmp/testpipe &
[1] 28584

Ở đây bạn sẽ thấy PID của quá trình gzip. Trong ví dụ của chúng tôi, nó là 28584.

Bây giờ hãy kiểm tra xem PID này đang làm gì

$ ps u -P 28584
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
c0rp     28584  0.0  0.0  29276  7800 pts/8    S    00:08   0:00 bash

Bạn sẽ thấy rằng nó đang sử dụng không có tài nguyên . Sử dụng CPU 0%, sử dụng bộ nhớ 0%.

Xác minh linh cảm về việc sử dụng không gian tệp

$ du -h /tmp/testpipe
0   testpipe

Và một lần nữa 0, không có gì. Testpipe có thể được sử dụng lại nếu cần.

Đừng quên giết gzip, sử dụng kill -15 28584. Và loại bỏ đường ống được đặt tên của chúng tôi bằng cách sử dụngrm /tmp/testpipe

Ví dụ sử dụng

Bạn có thể chuyển hướng hầu hết mọi thứ bằng cách sử dụng ống có tên. Ví dụ, bạn có thể thấy proxy một dòng này .

Ngoài ra đây là một lời giải thích tốt hơn về việc sử dụng đường ống được đặt tên. Bạn có thể định cấu hình hai quy trình trên một máy chủ để liên lạc bằng cách sử dụng đường ống có tên thay vì ngăn xếp TCP / IP. Nó nhanh hơn nhiều và không tải tài nguyên mạng. Ví dụ: Máy chủ Web của bạn có thể giao tiếp với cơ sở dữ liệu trực tiếp bằng cách sử dụng một đường ống có tên, thay vì sử dụng localhostđịa chỉ hoặc nghe một số cổng.


14

Đúng là bạn sẽ không sử dụng bộ nhớ hệ thống nhưng thực tế bạn không sử dụng cpu trong ví dụ của mình chỉ vì bạn không đọc đường ống nên quá trình đang chờ.

Xem xét ví dụ sau:

mkfifo /tmp/testpipe
tar cvf - / | gzip > /tmp/testpipe

Bây giờ hãy mở một giao diện điều khiển mới và chạy:

watch -n 1 'ps u -P $(pidof tar)

Và trong giao diện điều khiển thứ ba:

cat /tmp/testpipe > /dev/null

Nếu bạn nhìn vào đồng hồ cmd (nhiệm kỳ 2), nó sẽ cho thấy mức tăng tiêu thụ cpu!


1
Câu trả lời này là về câu trả lời của
c0rp

2

Dưới đây là trường hợp sử dụng trong đó các đường ống có tên có thể giúp bạn tiết kiệm rất nhiều thời gian bằng cách loại bỏ I / O.

Giả sử bạn có BigFile, ví dụ 10G.

Bạn cũng có các phần tách BigFile này thành các phần từ 1G, BigFileSplit_01 đến BigFile_Split_10.

Bây giờ bạn có nghi ngờ về tính chính xác của BigFileSplit_05

Chắc chắn, không có đường ống được đặt tên, bạn sẽ tạo một phần mới từ BigFile và so sánh:

dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Với các ống được đặt tên, bạn sẽ làm

mkfifo BigFileSplitOrig_05
dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 &
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

Điều đó thoạt nhìn có vẻ không phải là một sự khác biệt lớn ... nhưng về mặt thời gian, sự khác biệt là rất lớn!

Lựa chọn 1:

  • đ: đọc 1G / viết 1G (1)
  • khác biệt: đọc 2G
  • rm: cụm phân bổ miễn phí / xóa mục nhập thư mục

Tùy chọn 2:

  • đd: không có gì (đi đến ống có tên)
  • khác biệt: đọc 2G
  • rm: không có cụm được phân bổ để quản lý (chúng tôi không thực sự ghi bất cứ điều gì vào hệ thống tập tin) / xóa mục nhập thư mục

Vì vậy, về cơ bản, đường ống có tên giúp bạn đọc và ghi 1G cộng với việc dọn dẹp hệ thống tập tin (vì chúng tôi không viết gì cho hệ thống tập tin ngoại trừ nút fifo trống).

Không làm I / O, đặc biệt là ghi, cũng tốt để tránh sự hao mòn của đĩa của bạn. Thậm chí còn thú vị hơn khi bạn làm việc với SSD vì chúng có số lần ghi hạn chế trước khi các tế bào chết.

(1) Rõ ràng, một tùy chọn khác sẽ là tạo tệp tạm thời đó vào RAM, ví dụ nếu / tmp được gắn vào RAM (tmpfs). Tuy nhiên, bạn sẽ bị giới hạn bởi kích thước của đĩa RAM, trong khi "thủ thuật đường ống có tên" không có giới hạn.


0

Bạn có thể để một chương trình nằm yên và lắng nghe một đường ống được đặt tên cho một số sự kiện bên ngoài. Ngay khi sự kiện bên ngoài xảy ra (ví dụ: sự xuất hiện của một số dữ liệu mới), điều này có thể được phát hiện bởi một số chương trình khác, lần lượt mở đường ống để ghi, ghi dữ liệu sự kiện có liên quan vào đường ống. Khi câu lệnh đóng được phát ra, chương trình nghe sẽ nhận được luồng dữ liệu qua đường ống thông qua câu lệnh đọc và sẵn sàng xử lý những gì nó có. Đừng quên tor đóng ống sau khi đọc nội dung. Chương trình nghe cũng có thể trả về kết quả xử lý của nó thông qua cùng hoặc thông qua một ống có tên khác. Thông tin liên chương trình như vậy đôi khi rất thuận tiện.

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.