Sự khác biệt giữa & 6 và / dev / fd / 6 là gì?


11

Để đọc từ mô tả tập tin 6 tôi có thể sử dụng <&6hoặc </dev/fd/6(aka /proc/self/fd/6). Thông thường cả hai đều làm việc tốt như nhau. Tuy nhiên, nếu mô tả tập tin đó là một ổ cắm, điều kỳ lạ xảy ra. Ví dụ:

$ bash -c 'ls -l /dev/fd/6;cat /dev/fd/6' 6</dev/tcp/localhost/12345
lrwx------ 1 michas michas 64 Jan 10 19:50 /dev/fd/6 -> socket:[315010]
cat: /dev/fd/6: No such device or address

Ở đây lscho thấy các mô tả là thực sự hiện diện. Nhưng truy cập dữ liệu là không thể theo cách này. Nếu tôi sử dụng cat <&6thay vì mọi thứ hoạt động tốt trở lại.

Sự khác biệt giữa cả hai cách truy cập mô tả tập tin là gì?

Có một cách tốt để truy cập một mô tả nếu số nếu được đưa ra trong một biến? ( </dev/fd/$fdsẽ làm việc, nhưng <&$fdkhông.)

(Tình huống trên có thể được quan sát trên linux, nhưng không phải trên OpenBSD. - Có vẻ như mô tả tệp đó là một thiết bị ký tự thông thường ở đó.)


1
Đây có phải là một bản sao unix.stackexchange.com/q/98958/38906
cuonglm

2
Cảm ơn. Nó liên quan nhưng không thực sự là một bản sao.
michas

Câu trả lời:


5

Đó là vì đọc từ /dev/fd/các mục đại diện cho các socket không được triển khai trên Linux. Bạn có thể tìm thấy một bài viết tốt về lý luận ở đây. Vì vậy, bạn có thể gọi statvào liên kết và đó là lý do tại sao bạn nhìn thấy nó ls, nhưng quyền truy cập không được phép.

Bây giờ cho phần thứ hai - tại sao không bash -c 'ls -l /dev/fd/6; cat <&6' 6</dev/tcp/localhost/12345hoạt động? Đó là bởi vì socket được đọc từ việc sử dụng API socket / file chứ không phải /prochệ thống tập tin. Đây là những gì tôi đã quan sát thấy xảy ra:

  1. bash Ví dụ chạy trong thiết bị đầu cuối của bạn tạo ổ cắm với fd 6.
  2. Con bashchạy và gọi điện thoại dup2(6, 0), để gắn ổ cắm của bạn như cat's stdin.
  3. Nếu dup2cuộc gọi không thành công, mèo đọc từ stdin.

Bạn có thể tái tạo và quan sát nó với:

netcat -lp 12345    # in another terminal session (GNU netcat)
strace -f -e trace=open,read,write,dup2 bash -c 'ls -l /dev/fd/6; cat <&6' \
 6</dev/tcp/localhost/12345

Nếu bạn đang tự hỏi tại sao bashtiến trình con có quyền truy cập vào fd 6 - mô tả tệp tồn tại forknếu chúng không được đánh dấu để đóng exec, chúng cũng không bị đóng ở đó.


3

Để trả lời câu hỏi trực tiếp của bạn, " sự khác biệt là gì?":

Khi bạn chuyển hướng từ <&6, shell sử dụng dup2()lệnh gọi hệ thống để sao chép bộ mô tả tệp. Khi bạn (cố gắng) chuyển hướng từ </dev/fd/6, nó sẽ sử dụng open().

Nhân không hỗ trợ open()ổ cắm trong /dev/fd; chúng có mặt trong thư mục để chỉ thông tin trang trí .

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.