Nếu bạn sử dụng, strace
bạn có thể thấy tập lệnh shell được thực thi khi chạy.
Thí dụ
Nói rằng tôi có kịch bản shell này.
$ cat hello_ul.bash
#!/bin/bash
echo "Hello Unix & Linux!"
Chạy nó bằng cách sử dụng strace
:
$ strace -s 2000 -o strace.log ./hello_ul.bash
Hello Unix & Linux!
$
Nhìn vào bên trong các strace.log
tập tin cho thấy sau đây.
...
open("./hello_ul.bash", O_RDONLY) = 3
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7fff0b6e3330) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
read(3, "#!/bin/bash\n\necho \"Hello Unix & Linux!\"\n", 80) = 40
lseek(3, 0, SEEK_SET) = 0
getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=4*1024}) = 0
fcntl(255, F_GETFD) = -1 EBADF (Bad file descriptor)
dup2(3, 255) = 255
close(3)
...
Khi tệp đã được đọc, nó sẽ được thực thi:
...
read(255, "#!/bin/bash\n\necho \"Hello Unix & Linux!\"\n", 40) = 40
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 3), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc0b38ba000
write(1, "Hello Unix & Linux!\n", 20) = 20
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(255, "", 40) = 0
exit_group(0) = ?
Ở trên chúng ta có thể thấy rõ rằng toàn bộ tập lệnh dường như được đọc trong một thực thể duy nhất, và sau đó được thực thi ở đó sau đó. Vì vậy, nó sẽ "xuất hiện" ít nhất là trong trường hợp của Bash rằng nó đọc tệp trong đó, và sau đó thực thi nó. Vì vậy, bạn nghĩ rằng bạn có thể chỉnh sửa tập lệnh trong khi nó đang chạy?
LƯU Ý: Đừng, mặc dù! Đọc tiếp để hiểu lý do tại sao bạn không nên lộn xộn với tệp tập lệnh đang chạy.
Những người phiên dịch khác thì sao?
Nhưng câu hỏi của bạn hơi tắt. Không phải Linux nhất thiết phải tải nội dung của tệp, đó là trình thông dịch đang tải nội dung, vì vậy nó thực sự phụ thuộc vào cách trình thông dịch thực hiện cho dù tải toàn bộ tệp hoặc theo khối hoặc dòng tại một thời điểm.
Vậy tại sao chúng ta không thể chỉnh sửa tập tin?
Tuy nhiên, nếu bạn sử dụng tập lệnh lớn hơn nhiều, bạn sẽ nhận thấy rằng bài kiểm tra trên có một chút sai lệch. Trong thực tế, hầu hết các thông dịch viên tải các tập tin của họ trong các khối. Điều này là khá chuẩn với nhiều công cụ Unix nơi họ tải các khối của một tệp, xử lý nó và sau đó tải một khối khác. Bạn có thể thấy hành vi này với Hỏi & Đáp về U & L mà tôi đã viết cách đây một thời gian liên quan grep
, có tiêu đề: grep / egrep tiêu thụ bao nhiêu văn bản mỗi lần? .
Thí dụ
Nói rằng chúng tôi thực hiện các kịch bản shell sau đây.
$ (
echo '#!/bin/bash';
for i in {1..100000}; do printf "%s\n" "echo \"$i\""; done
) > ascript.bash;
$ chmod +x ascript.bash
Kết quả trong tập tin này:
$ ll ascript.bash
-rwxrwxr-x. 1 saml saml 1288907 Mar 23 18:59 ascript.bash
Trong đó có chứa loại nội dung sau:
$ head -3 ascript.bash ; echo "..."; tail -3 ascript.bash
#!/bin/bash
echo "1"
echo "2"
...
echo "99998"
echo "99999"
echo "100000"
Bây giờ khi bạn chạy nó bằng cách sử dụng kỹ thuật tương tự ở trên với strace
:
$ strace -s 2000 -o strace_ascript.log ./ascript.bash
...
read(255, "#!/bin/bash\necho \"1\"\necho \"2\"\necho \"3\"\necho \"4\"\necho \"5\"\necho \"6\"\necho \"7\"\necho \"8\"\necho \"9\"\necho \"10\"\necho
...
...
\"181\"\necho \"182\"\necho \"183\"\necho \"184\"\necho \"185\"\necho \"186\"\necho \"187\"\necho \"188\"\necho \"189\"\necho \"190\"\necho \""..., 8192) = 8192
Bạn sẽ nhận thấy rằng tệp đang được đọc với gia số 8KB, vì vậy Bash và các shell khác có thể sẽ không tải toàn bộ tệp, thay vào đó chúng đọc chúng theo khối.
Tài liệu tham khảo