Điều này không phải là vô nghĩa, có một cách hợp pháp trong Linux để thực hiện điều này và kỳ vọng của bạn là sai lầm.
Chuỗi đối số và môi trường được truyền vào mã khởi động của chương trình bởi kernel được lưu trữ trong bộ nhớ ảo không gian ứng dụng thông thường, giống như bất kỳ dữ liệu chương trình nào khác; và, giống như bất kỳ biến dữ liệu chương trình nào khác, chúng có thể sửa đổi. Nó là khá hợp pháp cho các chương trình để sửa đổi chúng.
(Lưu ý rằng đây là từ quan điểm về những gì hạt nhân cung cấp và thi hành. Những tiêu chuẩn cho các ngôn ngữ lập trình cụ thể có thể nói không nhất thiết phải giống nhau. Nhưng theo như kernel, đó chỉ là một lĩnh vực của không gian ứng dụng bộ nhớ ảo cho dữ liệu chương trình có thể đọc và ghi được. Hạt nhân không quan tâm ngôn ngữ lập trình bạn đã biên dịch mã máy từ đâu.)
Các /proc/${PID}/environ
tập tin chỉ là một cửa sổ vào bộ nhớ ảo không gian ứng dụng này. Thay vì nhớ dữ liệu môi trường thực tế của quá trình, Linux chỉ nhớ các địa chỉ bắt đầu và kết thúc của khu vực môi trường mà nó đã bắt đầu quá trình và /proc/${PID}/environ
tệp chỉ đọc bất cứ thứ gì có trong bộ nhớ đó ngay bây giờ. Bạn không nên mong đợi rằng tệp này chứa danh sách các chuỗi kết thúc.. Đó là một kỳ vọng sai lầm.
Không có chức năng thư viện GNU C để sửa đổi bộ nhớ chứa các chuỗi này. Nhưng các chương trình khác nhau có chức năng riêng của họ để làm như vậy.
Ví dụ, xem xét OpenSSH. Máy chủ OpenSSH sửa đổi những gì ps
hiển thị cho vectơ đối số của nó, để đọc những thứ như sshd: JdeBP [priv]
.
Máy chủ OpenSSH chứa mã cố gắng bắt chước trên Linux những gì nó có thể làm với thư viện BSD C trên OpenBSD. Trên OpenBSD có một hàm thư viện BSD C có tên setproctitle()
là viết lại vectơ đối số quy trình như được báo cáo bởi ps
lệnh. Nó gọi sysctl()
để truyền một vectơ đối số mới cho kernel, ps
có thể đọc ra sysctl()
. FreeBSD có chức năng tương tự.
Trên Linux, như đã giải thích, kernel không nhớ các đối số và môi trường thực tế, chỉ đơn thuần là địa chỉ bắt đầu và kết thúc của các vùng nhớ nơi ban đầu đặt chúng khi bắt đầu quá trình. Vì vậy, cổng Linux của OpenSSH có setproctitle()
chức năng tương thích ghi đè lên vùng nhớ trên, thay vào đó.
Hàm tương thích này tính toán tổng kích thước của vùng môi trường và vùng đối số và ghi đè lên tất cả vùng đó bằng chuỗi đối số mới. Nó thực hiện điều này bởi vì trong các trường hợp thông thường, các chương trình gọi setproctitle()
muốn viết trong một tập hợp dữ liệu đối số dài hơn so với quy trình ban đầu. sshd
thường làm. Vì vậy, nó cho phép các đối số mới ghi đè lên vùng môi trường theo sau vùng đối số, giúp các chương trình có nhiều chỗ hơn cho các chuỗi đối số dài hơn.
Điều quan trọng, nó cũng đệm phần không sử dụng của khu vực mà nó không cần ghi đè lên, theo chiều dài ban đầu của tổng dữ liệu đối số và môi trường, với ␀s.
Và những gì bạn đang thấy là kết quả chính xác của điều này. Nếu bạn tìm thấy quy trình máy chủ OpenSSH trên hệ thống của mình, bạn cũng sẽ thấy rằng nó cũng có rất nhiều ␀ trong đó /proc/${PID}/environ
.
đọc thêm