Tại sao lscần một quy trình riêng để thực hiện? Tôi biết lý do tại sao các lệnh như cdkhông thể được thực thi bằng cơ chế forking nhưng có bất kỳ tác hại nào nếu lsđược thực thi mà không thực hiện không?
Tại sao lscần một quy trình riêng để thực hiện? Tôi biết lý do tại sao các lệnh như cdkhông thể được thực thi bằng cơ chế forking nhưng có bất kỳ tác hại nào nếu lsđược thực thi mà không thực hiện không?
Câu trả lời:
Câu trả lời ít nhiều lslà một thực thi bên ngoài. Bạn có thể thấy vị trí của nó bằng cách chạy type -p ls.
Tại sao không lsđược xây dựng vào vỏ? Vâng, tại sao nó phải như vậy? Công việc của shell không phải là bao gồm mọi lệnh có sẵn, mà là cung cấp một môi trường có khả năng chạy chúng. Một số hệ vỏ hiện đại có echo, printfvà ilk của chúng là các khối, về mặt kỹ thuật không phải là các khối, nhưng được tạo ra vì lý do hiệu suất khi chúng được chạy liên tục (chủ yếu trong các vòng lặp chặt chẽ). Nếu không tạo ra các nội trang, trình bao sẽ phải rẽ nhánh và thực hiện một quy trình mới cho mỗi cuộc gọi đến chúng, việc này có thể cực kỳ chậm.
Ít nhất, đang chạy ls, một thực thi bên ngoài, yêu cầu chạy một trong các nhóm thực thi của các cuộc gọi hệ thống. Bạn có thể làm điều này mà không cần gạt, nhưng nó sẽ thay thế lớp vỏ chính mà bạn đang sử dụng. Bạn có thể thấy những gì xảy ra trong trường hợp đó bằng cách làm như sau:
exec ls; echo "this never gets printed"
Vì hình ảnh quá trình của shell của bạn được thay thế, shell hiện tại không còn truy cập được sau khi thực hiện điều này. Để shell có thể tiếp tục chạy sau khi chạy ls, lệnh sẽ phải được tích hợp vào shell.
Forking cho phép thay thế một quá trình không phải là vỏ chính của bạn, điều đó có nghĩa là bạn có thể tiếp tục chạy vỏ của mình sau đó.
echo, printfvv
cdkhông phải là một thực thi bên ngoài?
cdthực thi trong hệ điều hành POSIX-compliant ( xem tại đây ). Tuy nhiên, nếu bạn muốn thực sự chdir () trong quy trình hiện tại, bạn cần phải tích hợp nó vào trình bao.
Các Bash Reference Manual trạng thái:
Các lệnh dựng sẵn là cần thiết để thực hiện chức năng không thể hoặc bất tiện để có được với các tiện ích riêng biệt.
Đó là, shell được thiết kế để chỉ bao gồm các lệnh tích hợp nếu:
Các lslệnh không phù hợp với bất kỳ của các requirments trên.
Tuy nhiên , ở đây không có ràng buộc lập trình nào có thể ngăn chặn lsviệc được cài đặt dưới dạng tích hợp, đang thực thi trong cùng một quy trình như trình thông dịch bash. Các lý do thiết kế cho các lệnh không được thực hiện dưới dạng shell dựng sẵn là:
Về lý do đầu tiên - Bạn muốn vỏ phải độc lập và đàn hồi nhất có thể. Bạn không muốn lớp vỏ bị kẹt trên giá lstreo NFS "không phản hồi vẫn đang thử".
Về lý do thứ hai - Trong nhiều trường hợp, bạn có thể muốn sử dụng hệ vỏ cho hệ thống sử dụng Busybox hoặc hệ thống tệp khác có lstriển khai khác . Hoặc thậm chí sử dụng cùng một nguồn shell trong các hệ điều hành có các lstriển khai khác nhau .
Về lý do thứ ba - Đối với một biểu thức như find . -type d | xargs ls -ladsẽ khó hoặc không thể thực hiện lsquy trình tương tự như trình thông dịch shell.
Về lý do thứ tư - Một số lslệnh có thể mất nhiều thời gian để hoàn thành. Bạn có thể muốn vỏ tiếp tục làm một cái gì đó khác trong thời gian đó.
Lưu ý: Xem bài đăng hữu ích này của Warren Young để trả lời một câu hỏi tương tự.
lsvào một quy trình bên ngoài. Nó có thể được thực hiện, nhưng nó sẽ phức tạp.
bashđầu ra alias | grep ls. đầu vàocat /etc/passwd | while read a; do echo "$a"; done
lskhông yêu cầu một quá trình riêng biệt. Rất ít lệnh thực sự yêu cầu một quy trình riêng: chỉ những lệnh cần thay đổi đặc quyền.
Theo quy định, shell chỉ thực hiện các lệnh dưới dạng nội trang khi các lệnh đó cần được triển khai dưới dạng nội trang. Lệnh như alias, cd, exit, export, jobs, ... cần phải đọc hoặc sửa đổi một số trạng thái nội bộ của vỏ, và do đó không thể là các chương trình riêng biệt. Các lệnh không có yêu cầu như vậy có thể là các lệnh riêng biệt; bằng cách này, chúng có thể được gọi từ bất kỳ shell hoặc chương trình khác.
Nhìn vào danh sách các nội dung trong bash, chỉ các nội dung sau có thể được triển khai dưới dạng các lệnh riêng biệt. Đối với một số người trong số họ, sẽ có một chút mất chức năng.
command- nhưng nó sẽ mất đi tính hữu dụng của nó trong các tình huống PATHcó thể không được thiết lập đúng và tập lệnh đang sử dụng commandnhư một phần của việc thiết lập nó.echo - đó là một nội dung cho hiệu quả.help - nó có thể sử dụng một cơ sở dữ liệu riêng biệt, nhưng việc nhúng văn bản trợ giúp vào trình thực thi shell có lợi thế là làm cho trình bao thực thi được khép kín.kill - có hai lợi thế trong việc tích hợp sẵn: nó có thể nhận ra các chỉ định công việc ngoài ID xử lý và nó có thể được sử dụng ngay cả khi không có đủ tài nguyên để bắt đầu một quy trình riêng biệt.printf- với cùng lý do echo, và cũng để hỗ trợ -vtùy chọn đặt đầu ra trong một biến.pwd - nội dung cung cấp khả năng bổ sung của theo dõi thư mục hiện tại hợp lý (giữ nguyên các liên kết tượng trưng thay vì mở rộng chúng).test- đó là một nội dung tích hợp cho hiệu quả (và bash cũng thực hiện một số phép thuật với các tệp được gọi /dev/fd/…trên một số hệ điều hành).Một vài shell cung cấp một số lượng đáng kể các nội dung bổ sung. Có sash , một lớp vỏ được thiết kế thành một nhị phân độc lập để sửa chữa khẩn cấp (khi một số lệnh bên ngoài có thể không sử dụng được). Nó có tích hợp ls, được gọi -ls, cũng như các công cụ khác như -grepvà -tar. Nội dung của Sash có ít khả năng hơn các lệnh chính thức. Zsh cung cấp một số nội dung tương tự trong mô-đun zsh / files . Nó không có ls, nhưng mở rộng ký tự đại diện ( echo *) và zstatcó thể phục vụ một chức năng tương tự.
Tôi nghĩ rằng một cái gì đó mà mọi người đang thiếu ở đây là sự phức tạp của lschương trình GNU trên Linux. So sánh kích thước thực thi của lsđến bashvà dashvỏ trên hệ thống Debian của tôi, chúng ta thấy rằng nó là khá lớn:
graeme@graeme:~$ ls -lh /bin/{ls,bash,dash}
-rwxr-xr-x 1 root root 953K Mar 30 2013 /bin/bash
-rwxr-xr-x 1 root root 115K Dec 25 20:25 /bin/dash
-rwxr-xr-x 1 root root 108K Jul 20 22:52 /bin/ls
Bao gồm một lstính năng đầy đủ như phiên bản GNU trong bashsẽ tăng kích thước thực thi lên 10%. Nó có kích thước gần giống như dashvỏ đầy đủ !
Hầu hết các nội dung shell được chọn vì chúng tích hợp với shell theo cách mà các thực thi bên ngoài không thể (câu hỏi chỉ ra cd, nhưng một ví dụ khác là phiên bản bash killtích hợp với điều khiển công việc bash) hoặc vì chúng là các lệnh rất đơn giản để thực hiện, đưa ra một tốc độ lớn so với mức chi trả kích thước ( truevà falseđơn giản như nó được).
GNU lsđã có một chu kỳ phát triển dài và thực hiện các tùy chọn có thể tùy chỉnh những gì / cách hiển thị kết quả. Sử dụng một ls theo mặc định sẽ làm mất chức năng này hoặc làm tăng đáng kể độ phức tạp và kích thước của vỏ.
Điều này làm những gì bạn đang tìm kiếm:
printf "%s\n" *
Ngoài ra, bạn có thể lưu trữ tên tệp trong mảng:
files=(`printf "%s\n" *`) #items are separated by whitespace
echo ${#files[*]} files
for index in ${!a[*]}
do printf "%d: %s\n" $index ${a[$index]};
done
Nhưng nó không quan tâm đến khoảng trắng trong tên
Điều này chuyển sang biến và quan tâm đến khoảng trắng:
printf "%s\n" * | while read a; do echo $a; done
lslà một chương trình bên ngoài,echo *hoặcecho * .*(tùy thuộc vào các tùy chọn shell) thực hiện khá tốt việc liệt kê các tệp mà không cần chuyển.