How Linux Works Chương 8 · A Closer Look at Processes and Resource Utilization

Chương 8 · Nhìn kỹ tiến trình và tài nguyên Chapter 8 · A Closer Look at Processes and Resource Utilization

Ba loại tài nguyên, một trọng tài, và những công cụ cho bạn nhìn thấy cuộc phân chia Máy chỉ có ba thứ để chia: CPU, bộ nhớ, và đĩa Three kinds of resource, one arbiter, and the tools that let you watch the division

Ward mở chương này bằng một khung rất gọn: có ba loại tài nguyên phần cứng cơ bản — CPU, bộ nhớ, và I/O. Các tiến trình tranh giành chúng, và việc của nhân là phân bổ tài nguyên một cách công bằng.1 Nhưng ông bổ sung ngay một vế thứ hai mà người mới hay bỏ qua: bản thân nhân cũng là một tài nguyên — một tài nguyên phần mềm mà tiến trình dùng để làm những việc như tạo tiến trình mới và liên lạc với tiến trình khác.1

Trong máy tính chỉ có ba thứ đáng tranh nhau: bộ xử lý (CPU), bộ nhớ, và việc đọc ghi đĩa. Các chương trình giành nhau ba thứ đó, còn nhân là người chia sao cho công bằng. Và nhân cũng là một thứ để dùng: chương trình phải nhờ nhân thì mới tạo được chương trình con. Nhớ nhé: CPU, bộ nhớ, đĩa — ba thứ, một trọng tài.

Ward opens the chapter with a compact frame: there are three basic kinds of hardware resource — CPU, memory, and I/O. Processes vie for them, and the kernel's job is to allocate resources fairly.1 He immediately adds a second clause newcomers tend to skip: the kernel itself is also a resource — a software resource that processes use to perform tasks such as creating new processes and communicating with other processes.1

Ngay đầu chương ông cũng đặt một cảnh báo về thái độ, và nó định hình cách nên đọc cả chương: phần lớn công cụ ở đây được coi là công cụ theo dõi hiệu năng, đặc biệt hữu ích khi hệ thống đang chậm như rùa và bạn đang cố tìm ra vì sao. Nhưng “đừng để hiệu năng làm bạn phân tâm” — cố tối ưu một hệ thống vốn đã chạy đúng là phí thời gian, vì thiết lập mặc định trên hầu hết hệ thống đã được chọn tốt, và bạn chỉ nên đổi chúng khi có nhu cầu rất bất thường.1 Thay vào đó, hãy tập trung hiểu các công cụ thật sự đo cái gì — làm thế bạn sẽ có cái nhìn sâu vào cách nhân hoạt động và cách nó tương tác với tiến trình.1

Luận đề của chương: các công cụ trong chương này không phải để “tăng tốc máy”, mà để nhìn thấy nhân đang chia tài nguyên. Mỗi công cụ mở một cửa sổ khác nhau — ps/top nhìn tiến trình, lsof nhìn tệp đang mở, strace nhìn lời gọi hệ thống, vmstat/iostat/pidstat nhìn dòng tài nguyên theo thời gian, và cgroups là nơi bạn giới hạn phần chia đó.1

Ý chính: mấy lệnh trong chương này giống như các ô cửa sổ khác nhau nhìn vào cùng một căn phòng. Cửa nào cho bạn thấy gì thì bạn nên biết. Nhớ nhé: học để nhìn, chứ không phải để chỉnh.

The chapter's thesis: the tools here are not for "making the machine faster" but for seeing the kernel divide resources. Each opens a different window — ps/top onto processes, lsof onto open files, strace onto system calls, vmstat/iostat/pidstat onto resource flow over time, and cgroups is where you limit the share.1

Cụm khái niệm 01 Concept cluster 01

Theo dấu tiến trình: từ ảnh chụp tĩnh sang thước phim Xem cái gì đang chạy trong máy Tracking processes: from a still photo to a moving picture

Ward nhắc lại rằng ps — đã học ở Mục 2.16 — liệt kê các tiến trình hiện có cùng thống kê sử dụng của chúng, nhưng nó gần như không cho bạn biết tiến trình thay đổi theo thời gian ra sao; vì vậy nó không giúp bạn xác định ngay tiến trình nào đang ngốn quá nhiều thời gian CPU hay bộ nhớ.12 Chương trình top cung cấp một giao diện tương tác cho chính những thông tin ps hiển thị: nó cho thấy trạng thái hệ thống hiện thời, cập nhật mỗi giây, và — quan trọng nhất — xếp các tiến trình hoạt động mạnh nhất lên đầu màn hình (mặc định là những tiến trình đang chiếm nhiều thời gian CPU nhất).13

Lệnh ps giống như chụp một tấm ảnh: bạn thấy lúc này có ai đang chạy. Nhưng ảnh không cho biết ai đang chạy ngày càng nhanh hay ai đang ngốn máy. Lệnh top thì giống một đoạn phim: nó tự cập nhật, và ai ngốn nhiều nhất thì bị đẩy lên đầu danh sách. Nhớ nhé: ps là ảnh chụp, top là phim.

Ward recalls that ps — covered in Section 2.16 — lists current processes and their usage statistics, but does little to tell you how processes change over time; so it won't immediately help you determine which process is using too much CPU time or memory.12 The top program gives an interactive interface to the same information ps displays: it shows the current system status, updates every second, and — perhaps most importantly — lists the most active processes at the top of its display (by default, those currently taking up the most CPU time).13

Điểm sư phạm ẩn ở đây là chiều thời gian. Gần như mọi công cụ còn lại trong chương chỉ là các cách khác nhau để thêm trục thời gian vào một phép đo: top làm mới tại chỗ, vmstat 2 in một dòng mới mỗi hai giây, pidstat -p 1329 1 in một dòng mỗi giây cho riêng một tiến trình, và sar thì ghi lại để bạn xem lại quá khứ.1 Khi gặp một công cụ mới, câu hỏi đầu tiên nên là: nó làm mới tại chỗ, in nối tiếp, hay ghi ra lịch sử?

Định nghĩa. lsof (viết tắt của list open files) liệt kê các tệp đang mở và các tiến trình đang dùng chúng. Vì Unix đặt rất nhiều trọng tâm lên tệp, lsof nằm trong số những công cụ hữu dụng nhất để tìm điểm trục trặc. Nhưng nó không dừng ở tệp thường — nó liệt kê được cả tài nguyên mạng, thư viện động, đường ống (pipe) và hơn thế.14

Nói đơn giản. lsof trả lời câu hỏi “ai đang mở cái gì”. Trong Unix, gần như mọi thứ đều được coi là tệp — nên danh sách đó cũng cho bạn thấy cả kết nối mạng và đường ống nối giữa các chương trình. Nhớ nhé: hỏng ở đâu thì thường có một tệp đang mở ở đó.

Definition. lsof (list open files) lists open files and the processes using them. Because Unix places a lot of emphasis on files, lsof is among the most useful tools for finding trouble spots. But it doesn't stop at regular files — it can list network resources, dynamic libraries, pipes, and more.14

ps    → ảnh chụp tiến trình
top   → ảnh chụp, làm mới 1 s
lsof  → tiến trình × tệp đang mở
strace → tiến trình × lời gọi hệ thống

ps   → ai đang chạy
top  → ai đang ngốn máy
lsof → ai đang mở gì
strace → nó đang nhờ nhân làm gì

ps    → snapshot of processes
top   → snapshot, refreshed 1 s
lsof  → processes × open files
strace → process × system calls

  1. top keystrokes

    Phím tắt của top — đổi thứ tự sắp xếp, đổi bộ lọc Mấy phím bấm trong top top's keystrokes — change the sort order, change the filter

    Bạn gửi lệnh cho top bằng phím bấm; những lệnh hay dùng nhất liên quan tới việc đổi thứ tự sắp xếp hoặc lọc danh sách tiến trình: Spacebar cập nhật màn hình ngay lập tức, M sắp theo bộ nhớ thường trú hiện thời, T sắp theo tổng thời gian CPU tích luỹ, P sắp theo CPU hiện thời (mặc định), u chỉ hiện tiến trình của một người dùng, f chọn các thống kê khác để hiển thị, và ? hiện bản tóm tắt cách dùng cho mọi lệnh của top.1 Ward ghi chú riêng một dòng: các phím lệnh của top phân biệt chữ hoa chữ thường.1

    Trong top, bạn bấm phím để ra lệnh. Bấm M để xếp theo bộ nhớ, P để xếp theo CPU, ? để xem bảng trợ giúp. Nhớ bấm đúng chữ hoa hay chữ thường, vì hai cái khác nhau. Nhớ nhé: M cho bộ nhớ, P cho CPU, ? khi bí.

    You send commands to top with keystrokes; the most frequently used ones deal with changing the sort order or filtering the list: Spacebar updates the display immediately, M sorts by current resident memory usage, T by total (cumulative) CPU usage, P by current CPU usage (the default), u displays only one user's processes, f selects different statistics to display, and ? displays a usage summary for all top commands.1 Ward notes separately that top's keystroke commands are case-sensitive.1

    Bạn gặp nó ở đâuWhere you meet it Khi máy chậm bất thường: mở top, bấm P nếu nghi CPU, bấm M nếu nghi bộ nhớ — thủ phạm thường nổi lên dòng đầu.1 Lúc máy ì ạch mà bạn không biết vì ai. When the machine is unusually slow: open top, press P if you suspect CPU, M if you suspect memory — the culprit usually rises to the first line.1

    atop và htop

    Hai tiện ích tương tự, atop và htop, cung cấp một tập hợp khung nhìn và tính năng phong phú hơn. Ward lưu ý rằng phần lớn tính năng thêm của chúng thật ra là lặp lại chức năng có ở công cụ khác — ví dụ htop chia sẻ nhiều khả năng của lsof được mô tả ngay ở mục kế tiếp.1

    Theo dõi riêng vài tiến trình

    Để theo dõi một hoặc vài tiến trình cụ thể theo thời gian, dùng tuỳ chọn -p của top theo cú pháp top -p pid1 [-p pid2 ...].13

  2. lsof output

    Đọc kết xuất lsof — tám cột, hai loại nội dung trong cột FD Bảng của lsof có tám cột Reading lsof output — eight columns, two kinds of content in FD

    Chạy lsof trần thường sinh ra một lượng kết xuất khổng lồ. Hàng tiêu đề liệt kê các cột: COMMAND (tên lệnh của tiến trình đang giữ bộ mô tả tệp), PID, USER, FD, TYPE (kiểu tệp: tệp thường, thư mục, socket…), DEVICE (số hiệu chính và phụ của thiết bị chứa tệp), SIZE/OFF (kích thước tệp), NODE (số inode), và NAME (tên tệp).14

    Bảng lsof có tám cột. Cột quan trọng nhất là: lệnh nào, của ai, và đang mở tệp nào. Bảng rất dài, đừng cố đọc hết. Nhớ nhé: đọc ba cột COMMAND, PID, NAME là đủ dùng.

    Running plain lsof usually produces a tremendous amount of output. The header row lists the fields: COMMAND (the command name of the process holding the file descriptor), PID, USER, FD, TYPE (regular file, directory, socket, and so on), DEVICE (major and minor number of the device holding the file), SIZE/OFF (the file's size), NODE (the inode number), and NAME (the filename).14

    Bạn gặp nó ở đâuWhere you meet it Các dòng có cwd ở cột FD chỉ ra thư mục làm việc hiện thời của tiến trình; trong ví dụ của sách, dòng cuối cho thấy một tệp tạm mà tiến trình vi của người dùng (PID 1994) đang dùng.1 Khi bạn muốn biết một chương trình đang ngồi ở thư mục nào. Lines with cwd in the FD field indicate processes' current working directories; in the book's example the last line shows a temporary file a user's vi process (PID 1994) is using.1

    Cột FD chứa hai loại thứ

    Đây là chỗ hay gây bối rối. Trong phần lớn kết xuất, cột FD cho biết mục đích của tệp (cwd, rtd, txt, mem…). Nhưng cột FD cũng có thể liệt kê bộ mô tả tệp của tệp đang mở — một con số mà tiến trình dùng cùng với thư viện hệ thống và nhân để định danh và thao tác trên tệp; trong ví dụ của sách, dòng cuối cho thấy bộ mô tả tệp là 3.1

    Chạy với quyền nào

    Bạn chạy lsof được cả với tư cách root lẫn người dùng thường, nhưng sẽ nhận được nhiều thông tin hơn khi chạy với quyền root.1 Trang lsof(8) chứa danh sách đầy đủ những gì bạn có thể thấy ở mỗi cột.14

  3. using lsof

    Dùng lsof — hai lối tiếp cận, và một cái bẫy về nhân Dùng lsof cho gọn Using lsof — two approaches, and one kernel trap

    Ward nêu hai lối cơ bản: (1) liệt kê tất cả rồi đẩy qua một lệnh như less và tìm thứ bạn cần — cách này có thể mất một lúc vì lượng kết xuất quá lớn; hoặc (2) thu hẹp danh sách bằng tuỳ chọn dòng lệnh.1 Hai ví dụ cụ thể: lsof +D /usr hiển thị các mục cho tệp đang mở trong /usr và mọi thư mục con; lsof -p pid liệt kê tệp đang mở của một mã tiến trình cụ thể. Để xem tóm tắt ngắn các tuỳ chọn, chạy lsof -h.14

    Có hai cách dùng: xem hết rồi tìm, hoặc hỏi thẳng cái mình cần. Cách hai nhanh hơn nhiều: lsof -p số_tiến_trình để hỏi một chương trình, lsof +D /usr để hỏi một thư mục. Nhớ nhé: hỏi hẹp thì trả lời nhanh.

    Ward gives two basic approaches: (1) list everything and pipe the output to a command like less, then search — which can take a while given the volume; or (2) narrow the list with command-line options.1 Two concrete examples: lsof +D /usr displays entries for open files in /usr and all its subdirectories; lsof -p pid lists the open files of one process ID. For a brief summary of the many options, run lsof -h.14

    Bạn gặp nó ở đâuWhere you meet it Khi không tháo được một phân vùng vì “thiết bị đang bận”: lsof +D trên điểm gắn kết cho bạn biết tiến trình nào còn đang giữ tệp ở đó. Khi máy báo “đang bận” mà bạn không biết ai đang bận. When a partition won't unmount because the "device is busy": lsof +D on the mount point shows which process still holds a file there.

    Cái bẫy sau khi cập nhật nhân

    Ward cảnh báo: lsof phụ thuộc rất nhiều vào thông tin của nhân. Nếu bạn cập nhật bản phân phối và nâng cấp cả nhân lẫn lsof, bản lsof mới có thể không chạy được cho tới khi bạn khởi động lại với nhân mới.1

    Phần mạng để dành cho Chương 10

    Phần lớn tuỳ chọn còn lại của lsof liên quan tới định dạng kết xuất; các tính năng mạng của nó được bàn riêng ở Chương 10 của sách.1

Cụm khái niệm 02 Concept cluster 02

Truy vết lời gọi, và chia tiến trình thành luồng Nhìn vào bên trong một chương trình Tracing calls, and splitting processes into threads

strace (system call trace) và ltrace (library trace) giúp bạn khám phá xem một chương trình định làm gì. Ward nói thẳng rằng hai công cụ này sinh ra lượng kết xuất lớn đến mức phi thường, nhưng một khi bạn biết cần tìm gì, bạn sẽ có nhiều thông tin hơn hẳn để lần ra vấn đề.15

Hai lệnh strace và ltrace giống như đặt máy ghi âm bên trong chương trình: mọi lời nó nhờ người khác làm đều được ghi lại. Ghi ra rất nhiều, nên phải biết mình đang tìm gì. Nhớ nhé: ghi âm thì dễ, nghe lại mới khó.

strace (system call trace) and ltrace (library trace) help you discover what a program attempts to do. Ward says plainly that these tools produce extraordinarily large amounts of output, but once you know what to look for you have far more information for tracking down problems.15

Cần giữ đúng ranh giới giữa hai công cụ, vì chúng nhìn vào hai tầng khác nhau đã dựng ở Chương 1. strace in ra mọi lời gọi hệ thống mà tiến trình thực hiện — tức là các phép toán đặc quyền mà tiến trình không gian người dùng nhờ nhân làm hộ, chẳng hạn mở và đọc dữ liệu từ một tệp.15 ltrace thì theo dõi các lời gọi thư viện chia sẻ: kết xuất trông tương tự, nhưng nó không theo dõi bất cứ thứ gì ở mức nhân.16 Nói cách khác, strace đứng ở đường ranh giới nhân/người dùng; ltrace đứng hoàn toàn bên trong không gian người dùng.

Định nghĩa. Một luồng (thread) rất giống một tiến trình: nó có một định danh riêng (thread ID, hay TID), và nhân lập lịch rồi chạy luồng y như chạy tiến trình. Khác biệt then chốt: các tiến trình riêng biệt thường không chia sẻ tài nguyên hệ thống như bộ nhớ và kết nối vào/ra với nhau, còn mọi luồng bên trong một tiến trình đều chia sẻ tài nguyên hệ thống và một phần bộ nhớ của tiến trình đó.17

Nói đơn giản. Một tiến trình giống một căn phòng; luồng là những người cùng làm việc trong căn phòng đó. Hai căn phòng khác nhau thì đồ đạc riêng, nhưng người trong cùng phòng thì dùng chung bàn ghế. Nhớ nhé: cùng phòng thì dùng chung đồ.

Definition. A thread is very similar to a process: it has an identifier (thread ID, or TID), and the kernel schedules and runs threads just like processes. The key difference: separate processes usually don't share system resources such as memory and I/O connections, whereas all threads inside a single process share their system resources and some memory.17

strace → lời gọi hệ thống (nhân)
ltrace → lời gọi thư viện (người dùng)
tiến trình = 1..n luồng
TID(luồng chính) == PID

strace → nhờ nhân làm gì
ltrace → nhờ thư viện làm gì
một chương trình = nhiều luồng
luồng đầu tiên mang số của chương trình

strace → system calls (kernel)
ltrace → library calls (user space)
process = 1..n threads
TID(main thread) == PID

  1. strace

    strace — đọc một vệt truy vết từ đầu đến cuối strace — xem chương trình nhờ nhân làm gì strace — reading a trace from beginning to end

    Ví dụ mở đầu của Ward là strace cat /dev/null.1 Vì strace bắt đầu làm việc trên tiến trình mới — bản sao của tiến trình gốc — ngay sau lời gọi fork(), nên những dòng đầu tiên phải cho thấy execve() đang hoạt động, theo sau là một lời gọi khởi tạo bộ nhớ, brk().18 Phần tiếp theo chủ yếu là nạp thư viện chia sẻ và có thể bỏ qua. Ở gần cuối, lời gọi openat() — một biến thể nhỏ của open() — mở tệp, và kết quả 3 nghĩa là thành công (3 là bộ mô tả tệp mà nhân trả về sau khi mở tệp); rồi read() cũng trên bộ mô tả 3, không còn gì để đọc, nên chương trình đóng bộ mô tả và thoát bằng exit_group().1

    Gõ strace cat /dev/null rồi xem: chương trình mở tệp, đọc, thấy rỗng, đóng lại, rồi thoát. Mỗi dòng là một lần nó nhờ nhân làm một việc. Nếu một dòng trả về số âm, tức là việc đó thất bại. Nhớ nhé: số dương là xong, số âm là hỏng.

    Ward's opening example is strace cat /dev/null.1 Because strace begins working on the new process — the copy of the original — just after the fork() call, the first lines show execve() in action, followed by a memory initialization call, brk().18 The next part is mostly shared-library loading and can be ignored. Near the end, openat() — a slight variant of open() — opens the file, and the result 3 means success (3 being the file descriptor the kernel returns); then read() on descriptor 3 has nothing more to read, so the program closes the descriptor and exits with exit_group().1

    Bạn gặp nó ở đâuWhere you meet it Tệp thiếu là vấn đề phổ biến nhất với chương trình Unix; khi nhật ký hệ thống không giúp được gì và bạn không còn chỗ nào để tra, strace rất hữu dụng để lần ra một tệp bị thiếu.1 Khi chương trình báo lỗi mà không nói thiếu tệp nào. Missing files are the most common problem with Unix programs; when the system log doesn't help and you have nowhere else to turn, strace is of great use for tracking one down.1

    Khi lệnh gặp lỗi

    Thử strace cat not_a_file: vì không mở được tệp, lời gọi trả về -1 để báo lỗi, và strace in ra đúng mã lỗi (ENOENT) kèm một mô tả ngắn về lỗi đó.1

    Lưu kết xuất và bám theo tiến trình con

    Mặc định strace gửi kết xuất tới standard error; dùng -o save_file để lưu vào tệp. Với một daemon tự tách khỏi terminal, strace -o crummyd_strace -ff crummyd ghi hành động của mọi tiến trình con mà nó sinh ra vào crummyd_strace.pid, trong đó pid là mã tiến trình của tiến trình con.15

  2. ltrace

    ltrace — cùng hình thức, khác tầng ltrace — nhìn lời gọi thư viện ltrace — same form, different layer

    ltrace theo dõi các lời gọi thư viện chia sẻ. Kết xuất giống strace — đó là lý do nó được nhắc ở đây — nhưng nó không theo dõi bất cứ thứ gì ở mức nhân. Ward cảnh báo rằng số lời gọi thư viện chia sẻ nhiều hơn hẳn số lời gọi hệ thống: bạn chắc chắn sẽ phải lọc kết xuất, và bản thân ltrace có nhiều tuỳ chọn sẵn có để hỗ trợ việc đó.16

    ltrace giống strace, nhưng nghe ở một tầng khác — tầng thư viện, không phải tầng nhân. Nó ghi ra nhiều hơn rất nhiều, nên phải lọc. Nhớ nhé: cùng kiểu ghi âm, khác cái micro.

    ltrace tracks shared library calls. The output is similar to strace's — which is why it's mentioned here — but it doesn't track anything at the kernel level. Ward warns that there are many more shared library calls than system calls: you'll definitely need to filter the output, and ltrace has many built-in options to assist.16

    Bạn gặp nó ở đâuWhere you meet it Khi lỗi nằm ở tầng thư viện chứ không ở tầng nhân — ví dụ một hàm phân tích cấu hình trả về giá trị lạ trước khi bất kỳ lời gọi hệ thống nào xảy ra. Khi lỗi xảy ra trước cả lúc chương trình chạm vào đĩa. When the fault lies in the library layer rather than the kernel — say a config-parsing function returning something odd before any system call happens.

    Giới hạn: nhị phân liên kết tĩnh

    Ward ghi chú rõ: ltrace không hoạt động trên các nhị phân liên kết tĩnh — hợp lý, vì khi đó không còn lời gọi thư viện chia sẻ nào để chặn. Phần bàn sâu hơn về thư viện chia sẻ nằm ở Mục 15.1.3 của sách.1

    Vì sao hai công cụ chứ không một

    Vì một lời gọi thư viện có thể dẫn tới một lời gọi hệ thống, nhưng phần lớn thì không. Khi vệt strace im lặng ở đúng chỗ chương trình hỏng, lỗi hầu như chắc chắn nằm trong không gian người dùng — và đó là lúc chuyển sang ltrace.

  3. threads

    Luồng — vì sao chúng tồn tại, và giá phải trả khi đo đạc Luồng — nhiều tay cùng làm trong một phòng Threads — why they exist, and what they cost when measuring

    Mọi tiến trình đều bắt đầu ở trạng thái đơn luồng; luồng khởi đầu đó thường được gọi là luồng chính (main thread). Luồng chính có thể khởi tạo luồng mới, biến tiến trình thành đa luồng — tương tự cách một tiến trình gọi fork() để tạo tiến trình mới.17 Lợi thế chính của tiến trình đa luồng: khi có nhiều việc phải làm, các luồng có thể chạy đồng thời trên nhiều bộ xử lý, có tiềm năng rút ngắn thời gian tính toán. Bạn cũng đạt được tính toán đồng thời bằng nhiều tiến trình, nhưng luồng khởi động nhanh hơn tiến trình, và việc các luồng liên lạc với nhau qua bộ nhớ dùng chung thường dễ hoặc hiệu quả hơn so với việc các tiến trình liên lạc qua một kênh như kết nối mạng hay đường ống.1

    Chương trình nào cũng bắt đầu với một luồng — một “người làm”. Người đó có thể gọi thêm người vào cùng phòng. Nhiều người thì làm nhanh hơn, và họ nói chuyện với nhau dễ hơn vì ngồi chung bàn. Nhớ nhé: gọi thêm người cùng phòng nhanh hơn mở phòng mới.

    All processes start out single-threaded; that starting thread is usually called the main thread. The main thread may start new threads, making the process multithreaded — similar to the way a process can call fork() to start a new process.17 The primary advantage: when a process has a lot to do, threads can run simultaneously on multiple processors, potentially speeding up computation. You can also get simultaneous computation with multiple processes, but threads start faster than processes, and it's often easier or more efficient for threads to intercommunicate through shared memory than for processes to communicate over a channel such as a network connection or a pipe.1

    Bạn gặp nó ở đâuWhere you meet it Một số chương trình dùng luồng để vượt qua khó khăn khi quản lý nhiều tài nguyên vào/ra: theo lối truyền thống, tiến trình đôi khi dùng fork() để tạo tiến trình con xử lý một luồng dữ liệu vào hoặc ra mới; luồng cho cơ chế tương tự mà không phải trả chi phí khởi động một tiến trình mới.1 Trong các máy chủ phải tiếp nhiều khách cùng lúc. Some programs use threads to overcome problems managing multiple I/O resources: traditionally a process would use fork() to start a subprocess for a new input or output stream; threads offer a similar mechanism without the overhead of starting a new process.1

    Xem luồng bằng ps m

    Mặc định ps và top chỉ hiện tiến trình; thêm tuỳ chọn m để ps hiện thông tin luồng.12 Trong Listing 8-1 của sách, mỗi dòng có số ở cột PID là một tiến trình, còn các dòng có dấu gạch ở cột PID là các luồng thuộc tiến trình đó; hai tiến trình bash mỗi cái chỉ có một luồng, còn tiến trình 12534 (Xorg) là đa luồng với bốn luồng.1

    TID và luồng chính

    Muốn thấy TID, dùng định dạng kết xuất tuỳ biến: ps m -o pid,tid,command. Trong ví dụ của sách, TID của các tiến trình đơn luồng trùng khít với PID — đó chính là luồng chính; với tiến trình đa luồng 12534, luồng 12534 cũng là luồng chính.12

    Giá phải trả khi đo đạc

    Luồng làm rối việc theo dõi tài nguyên, vì các luồng riêng lẻ trong một tiến trình đa luồng có thể tiêu thụ tài nguyên đồng thời. Ví dụ, top mặc định không hiện luồng — bạn phải bấm H để bật. Với phần lớn công cụ theo dõi tài nguyên trong chương, bạn phải làm thêm một thao tác nữa mới bật được chế độ hiển thị luồng.13

Cụm khái niệm 03 Concept cluster 03

Thời gian CPU, độ ưu tiên, tải trung bình, và trang nhớ CPU và bộ nhớ được chia thế nào CPU time, priority, load average, and memory pages

Ward dẫn vào phần theo dõi tài nguyên bằng một lời nhắc về thái độ lặp lại lần thứ hai: hầu hết hệ thống Linux chạy tốt với thiết lập mặc định của bản phân phối, và bạn có thể tốn nhiều ngày tinh chỉnh hiệu năng mà không thu được kết quả có ý nghĩa — đặc biệt nếu bạn chưa biết mình đang tìm gì. Vì vậy, thay vì nghĩ về hiệu năng khi thử các công cụ này, hãy nghĩ về việc nhìn thấy nhân đang hành động trong lúc nó chia tài nguyên cho các tiến trình.1

Máy Linux mặc định đã chạy khá tốt rồi. Bạn học mấy lệnh này không phải để chỉnh máy, mà để nhìn thấy máy đang chia phần cho ai. Nhớ nhé: nhìn trước đã, đừng vội vặn.

Ward introduces resource monitoring with an attitude reminder repeated a second time: most Linux systems perform well under a distribution's default settings, and you can spend days tuning without meaningful results, especially if you don't know what to look for. So rather than thinking about performance as you experiment, think about seeing the kernel in action as it divides resources among processes.1

Về ba con số của time. Chỗ này có một nhập nhằng mà sách nêu thẳng: hầu hết shell đều có một lệnh time dựng sẵn không cung cấp thống kê phong phú, trong khi còn có một tiện ích hệ thống ở /usr/bin/time. Bạn nhiều khả năng sẽ gặp bản dựng sẵn của bash trước.19 Sự khác biệt này quay lại ngay ở phần lỗi trang: để thấy số lỗi trang, bạn phải dùng bản hệ thống /usr/bin/time chứ không dùng bản dựng sẵn.1

Ba loại thời gian. Thời gian người dùng (user) là số giây CPU dành để chạy mã của chính chương trình. Thời gian hệ thống (sys) là lượng thời gian nhân bỏ ra để làm việc cho tiến trình — ví dụ đọc tệp và thư mục. Thời gian thực (real, còn gọi là thời gian trôi qua) là tổng thời gian chạy tiến trình từ đầu đến cuối, bao gồm cả thời gian CPU làm việc khác.19

Nói đơn giản. user là thời gian chương trình tự làm. sys là thời gian nó nhờ nhân làm hộ. real là thời gian bạn thật sự ngồi chờ, kể cả lúc máy đi làm chuyện khác. Nhớ nhé: chờ lâu chưa chắc vì máy bận — có khi nó đang đợi.

Three kinds of time. User time (user) is the number of seconds the CPU spent running the program's own code. System time (sys) is how much time the kernel spends doing the process's work — for example reading files and directories. Real time (real, also called elapsed time) is the total time to run the process from start to finish, including the time the CPU spent on other tasks.19

real − (user + sys) ≈ thời gian chờ
ưu tiên lập lịch ∈ [−20, 20]
nice mặc định = 0
kích thước trang thường = 4096 B

chờ = tổng − (tự làm + nhờ làm)
ưu tiên: −20 là gấp nhất
nice mặc định = 0
một trang nhớ = 4096 byte

real − (user + sys) ≈ time spent waiting
schedule priority ∈ [−20, 20]
default nice = 0
typical page size = 4096 B

  1. nice value

    Độ ưu tiên và giá trị nice — một gợi ý, không phải một mệnh lệnh nice — xin nhường lượt cho người khác Priority and the nice value — a hint, not an order

    Nhân chạy mỗi tiến trình theo độ ưu tiên lập lịch của nó — một con số giữa −20 và 20, với −20 là ưu tiên cao nhất. Ward chêm luôn một câu trong ngoặc: “Vâng, chuyện này dễ gây nhầm lẫn.”1 Lệnh ps -l liệt kê độ ưu tiên hiện thời của một tiến trình, nhưng dễ thấy hơn là qua top: cột PR liệt kê độ ưu tiên lập lịch hiện thời của nhân, và số càng cao thì nhân càng ít có khả năng lập lịch cho tiến trình đó nếu tiến trình khác cần CPU.13

    Mỗi chương trình có một con số ưu tiên. Số càng nhỏ thì càng được chạy trước. Bạn có thể tự xin xuống hạng để nhường người khác. Nhớ nhé: số nhỏ là được ưu tiên, số lớn là chịu nhường.

    The kernel runs each process according to its scheduling priority, a number between −20 and 20, with −20 being the foremost priority. Ward adds in parentheses: "Yes, this can be confusing."1 ps -l lists a process's current priority, but it's easier to see in top: the PR column lists the kernel's current schedule priority, and the higher the number, the less likely the kernel is to schedule the process if others need CPU time.13

    Bạn gặp nó ở đâuWhere you meet it Khi bạn chạy một phép tính lớn ở nền mà không muốn nó làm ì phiên làm việc tương tác: đổi giá trị nice thành 20 bằng renice 20 pid để tiến trình đó lùi xuống hàng sau và chỉ chạy khi các việc khác đã rảnh.110 Khi bạn chạy một việc nặng mà vẫn muốn máy mượt. When you run a big background computation and don't want it to bog down your interactive session: set the nice value to 20 with renice 20 pid so the process takes a back seat and runs only when other tasks have nothing to do.110

    Nice chỉ là một gợi ý

    Cột NI bên cạnh cột ưu tiên là giá trị nice, và nó đưa một gợi ý cho bộ lập lịch của nhân — đây mới là thứ bạn quan tâm khi muốn tác động tới quyết định của nhân. Nhân cộng giá trị nice vào độ ưu tiên hiện thời để xác định lượt kế tiếp cho tiến trình. Đặt nice cao hơn nghĩa là bạn đang “tử tế” hơn với các tiến trình khác, vì nhân sẽ ưu tiên chúng.110 Riêng độ ưu tiên lập lịch không quyết định trọn vẹn việc nhân cấp CPU cho tiến trình, và nhân cũng có thể tự đổi độ ưu tiên trong lúc chương trình chạy, tuỳ theo lượng thời gian CPU mà tiến trình tiêu thụ.1

    Về khoảng giá trị: −20 tới 20 hay −20 tới 19?

    Sách viết độ ưu tiên lập lịch là “một con số giữa −20 và 20”.1 Giao diện nhân thì chặt hơn một chút: getpriority(2) nói giá trị nằm trong khoảng −20 tới 19, với −20 là ưu tiên cao nhất và 19 là thấp nhất, và mọi nỗ lực đặt ngoài khoảng đó bị kẹp lại trong khoảng một cách âm thầm.24 Trang này theo cách diễn đạt của Ward ở phần chính và ghi chú sự khác biệt ở đây, thay vì lặng lẽ chọn một bên. Trong thực tế điều đó không đổi gì: renice 20 pid mà sách nêu vẫn cho bạn tiến trình “nhường nhịn” nhất, vì 20 bị kẹp về 19.124

    Nice âm: gần như luôn là ý tồi

    Nếu là siêu người dùng, bạn có thể đặt giá trị nice âm, nhưng làm vậy gần như luôn là một ý tồi vì các tiến trình hệ thống có thể không nhận đủ thời gian CPU. Ward còn nói thẳng: bạn có lẽ sẽ không cần sửa giá trị nice nhiều, vì nhiều hệ thống Linux chỉ có một người dùng và người đó không thực hiện nhiều tính toán thật sự — giá trị nice quan trọng hơn hẳn ở thời còn nhiều người dùng chung một máy.1

  2. load average

    Tải trung bình — số tiến trình sẵn sàng chạy, không phải số tiến trình đang mở Tải trung bình — bao nhiêu việc đang xếp hàng Load average — how many processes are ready to run

    Tải trung bình là số tiến trình trung bình hiện đang sẵn sàng chạy — một ước lượng cho số tiến trình có khả năng dùng CPU tại một thời điểm bất kỳ, bao gồm cả tiến trình đang chạy lẫn tiến trình đang chờ tới lượt dùng CPU.1 Điểm mấu chốt để khỏi hiểu sai: phần lớn tiến trình trên máy bạn thường đang chờ đầu vào (từ bàn phím, chuột, hay mạng), nghĩa là chúng không sẵn sàng chạy và không đóng góp gì vào tải trung bình. Chỉ những tiến trình đang thật sự làm gì đó mới ảnh hưởng tới tải trung bình.1

    Tải trung bình đếm xem có bao nhiêu việc đang chờ tới lượt làm. Mở mười cửa sổ mà cả mười đều đứng im thì tải vẫn gần 0. Nhớ nhé: đếm việc đang làm, không đếm cửa sổ đang mở.

    The load average is the average number of processes currently ready to run — an estimate of how many processes are capable of using the CPU at any given time, including those running and those waiting for a chance.1 The key to not misreading it: most processes on your system are usually waiting for input (keyboard, mouse, network), meaning they aren't ready to run and contribute nothing. Only processes actually doing something affect the load average.1

    Bạn gặp nó ở đâuWhere you meet it Lệnh uptime cho bạn ba tải trung bình cùng với thời gian nhân đã chạy; ba con số đó lần lượt là tải trung bình của 1 phút, 5 phút và 15 phút vừa qua.111 Gõ uptime là thấy ba con số: 1 phút, 5 phút, 15 phút. The uptime command gives you three load averages along with how long the kernel has been running; the three numbers are for the past 1, 5, and 15 minutes respectively.111

    Đọc con số theo số lõi

    Trong ví dụ của sách, một hệ thống báo load average: 0.08, 0.03, 0.01 — trung bình chỉ 0,01 tiến trình chạy trên tất cả bộ xử lý trong 15 phút qua; nói cách khác, nếu chỉ có một bộ xử lý thì nó chạy ứng dụng không gian người dùng đúng 1 phần trăm của 15 phút vừa rồi.1 Nếu tải lên khoảng 1, nhiều khả năng một tiến trình duy nhất đang dùng CPU gần như toàn bộ thời gian; dùng top để nhận diện nó, vì nó thường nổi lên đầu màn hình.1 Trên máy nhiều lõi, tải 1 với hai lõi nghĩa là chỉ một lõi có việc tại một thời điểm, còn tải 2 nghĩa là cả hai lõi đều vừa đủ việc suốt.1

    Tải cao mà máy vẫn mượt

    Tải trung bình cao không đồng nghĩa hệ thống đang gặp rắc rối: một hệ thống đủ bộ nhớ và tài nguyên vào/ra hoàn toàn có thể gánh nhiều tiến trình đang chạy. Nếu tải cao mà máy vẫn phản hồi tốt, đừng hoảng — chỉ là nhiều tiến trình đang chia nhau CPU, nên mỗi việc mất lâu hơn so với khi được độc chiếm CPU.1 Một trường hợp khác mà tải cao là bình thường: máy chủ web hoặc máy chủ tính toán, nơi tiến trình sinh ra và kết thúc nhanh đến mức cơ chế đo tải trung bình không hoạt động hiệu quả.1

    Tải rất cao kèm cảm giác chậm

    Nhưng nếu tải rất cao và bạn cảm thấy hệ thống đang chậm lại, có thể bạn đang gặp vấn đề hiệu năng bộ nhớ. Khi hệ thống cạn bộ nhớ, nhân có thể bắt đầu thrash — hoán đổi bộ nhớ ra đĩa và về lại liên tục. Khi đó nhiều tiến trình trở nên sẵn sàng chạy nhưng bộ nhớ của chúng lại không có sẵn, nên chúng nằm ở trạng thái sẵn-sàng-chạy (và đóng góp vào tải trung bình) lâu hơn bình thường rất nhiều.1

  3. demand paging

    Trang, bảng trang, và cấp phát theo nhu cầu Bộ nhớ được chia thành các trang Pages, page tables, and demand paging

    CPU có một đơn vị quản lý bộ nhớ (MMU) để tăng độ linh hoạt khi truy cập bộ nhớ. Nhân hỗ trợ MMU bằng cách chia bộ nhớ mà các tiến trình dùng thành những mẩu nhỏ hơn gọi là trang (page), và duy trì một cấu trúc dữ liệu gọi là bảng trang (page table) ánh xạ địa chỉ trang ảo của tiến trình sang địa chỉ trang thật trong bộ nhớ. Khi tiến trình truy cập bộ nhớ, MMU dịch địa chỉ ảo sang địa chỉ thật dựa trên bảng trang của nhân.112

    Bộ nhớ được cắt thành nhiều ô bằng nhau gọi là trang. Nhân giữ một quyển sổ ghi trang nào của ai nằm ở đâu. Chương trình đọc địa chỉ giả, còn phần cứng tra sổ để đổi ra địa chỉ thật. Nhớ nhé: bộ nhớ chia ô, nhân giữ sổ.

    The CPU has a memory management unit (MMU) to add flexibility in memory access. The kernel assists it by breaking the memory processes use into smaller chunks called pages, and maintaining a data structure called a page table that maps a process's virtual page addresses to real page addresses in memory. As a process accesses memory, the MMU translates virtual into real addresses based on the kernel's page table.112

    Bạn gặp nó ở đâuWhere you meet it Bạn lấy kích thước trang của hệ thống từ cấu hình nhân bằng getconf PAGE_SIZE; con số trả về tính bằng byte, và 4k là điển hình cho hầu hết hệ thống Linux.1 Gõ getconf PAGE_SIZE là biết mỗi ô to bao nhiêu — thường là 4096. You get a system's page size from the kernel configuration with getconf PAGE_SIZE; the number is in bytes, and 4k is typical for most Linux systems.1

    Bốn bước của cấp phát theo nhu cầu

    Một tiến trình người dùng không cần mọi trang bộ nhớ của nó có mặt ngay lập tức mới chạy được; nhân thường nạp và cấp phát trang khi tiến trình cần — hệ thống này gọi là cấp phát trang theo nhu cầu (on-demand paging, hay gọn hơn là demand paging).1 Bốn bước sách liệt kê: (1) nhân nạp phần đầu mã lệnh của chương trình vào các trang bộ nhớ; (2) nhân có thể cấp một ít trang bộ nhớ làm việc cho tiến trình mới; (3) khi chạy, tiến trình có thể tới chỗ mà lệnh kế tiếp không nằm trong trang nào đã nạp — lúc đó nhân tiếp quản, nạp trang cần thiết vào bộ nhớ, rồi cho chương trình chạy tiếp; (4) tương tự, nếu chương trình cần nhiều bộ nhớ làm việc hơn phần đã cấp ban đầu, nhân xử lý bằng cách tìm trang trống (hoặc dọn chỗ) và gán cho tiến trình.1

    Bộ nhớ thật không phải một cái hồ chung

    Nhân không ánh xạ trang bộ nhớ thật sang địa chỉ ảo một cách tuỳ tiện: nó không gom mọi trang khả dụng vào một hồ lớn rồi cấp phát từ đó. Bộ nhớ thật có nhiều phân chia phụ thuộc vào giới hạn phần cứng, việc nhân tối ưu các trang liền kề, và các yếu tố khác — nhưng Ward nói rõ rằng bạn không cần bận tâm chuyện này khi mới bắt đầu.113

  4. page fault

    Lỗi trang nhỏ và lớn — một loại vô hại, một loại tốn đĩa Lỗi trang — khi ô nhớ chưa sẵn sàng Minor and major page faults — one harmless, one costly

    Nếu một trang bộ nhớ chưa sẵn sàng khi tiến trình muốn dùng, tiến trình kích hoạt một lỗi trang (page fault); khi đó nhân giành quyền kiểm soát CPU từ tiến trình để chuẩn bị trang đó. Có hai loại: nhỏ (minor) và lớn (major).1 Lỗi trang nhỏ xảy ra khi trang cần thiết thật ra đang ở trong bộ nhớ chính, nhưng MMU không biết nó ở đâu — nhân chỉ việc mách cho MMU biết và cho tiến trình chạy tiếp; lỗi trang nhỏ không có gì phải lo, và rất nhiều lỗi loại này xảy ra trong lúc một tiến trình chạy.1

    Khi chương trình với tay lấy một ô nhớ mà ô đó chưa sẵn sàng, ta gọi đó là lỗi trang. Loại nhỏ: ô vẫn ở trong nhà, chỉ là tìm chưa ra — rất nhanh, không đáng lo. Loại lớn: ô nằm ngoài đĩa, phải đi lấy về — chậm. Nhớ nhé: nhỏ thì tìm trong nhà, lớn thì phải ra kho.

    If a memory page isn't ready when a process wants it, the process triggers a page fault; the kernel then takes control of the CPU from the process to get the page ready. There are two kinds: minor and major.1 A minor fault happens when the desired page is actually in main memory but the MMU doesn't know where — the kernel simply tells the MMU about the page and lets the process continue; minor page faults are nothing to worry about, and many occur as a process runs.1

    Bạn gặp nó ở đâuWhere you meet it Trong ví dụ của sách, /usr/bin/time cal > /dev/null báo (2major+254minor)pagefaults — 2 lỗi trang lớn và 254 lỗi nhỏ. Các lỗi lớn xảy ra khi nhân cần nạp chương trình từ đĩa lần đầu; chạy lại lệnh đó, bạn có lẽ sẽ không còn lỗi trang lớn nào vì nhân đã đệm các trang từ đĩa.19 Chạy lần đầu thì chậm, chạy lần hai thì nhanh — vì lần đầu phải đi lấy từ đĩa. In the book's example, /usr/bin/time cal > /dev/null reports (2major+254minor)pagefaults — 2 major and 254 minor faults. The major ones occurred when the kernel loaded the program from disk for the first time; run it again and you probably get no major faults, because the kernel cached the pages.19

    Lỗi trang lớn và thrashing

    Lỗi trang lớn xảy ra khi trang cần thiết hoàn toàn không có trong bộ nhớ chính, nghĩa là nhân phải nạp nó từ đĩa hoặc một cơ chế lưu trữ chậm khác. Nhiều lỗi trang lớn sẽ làm hệ thống ì ạch, vì nhân phải làm một lượng công việc đáng kể để cung cấp trang, cướp mất cơ hội chạy của các tiến trình bình thường.1 Một số lỗi lớn là không tránh được — chẳng hạn khi bạn nạp mã từ đĩa lúc chạy chương trình lần đầu. Vấn đề lớn nhất xảy ra khi bạn bắt đầu cạn bộ nhớ, buộc nhân hoán đổi các trang bộ nhớ làm việc ra đĩa để lấy chỗ cho trang mới, và điều này có thể dẫn tới thrashing.1

    Xem lỗi trang theo từng tiến trình

    Với top, bấm f để đổi các trường hiển thị và chọn nMaj làm một cột để xem số lỗi trang lớn; chọn vMj (số lỗi trang lớn kể từ lần cập nhật trước) hữu ích khi bạn đang lần theo một tiến trình có thể đang hành xử bất thường.13 Với ps, dùng định dạng kết xuất tuỳ biến, ví dụ ps -o pid,min_flt,maj_flt 20365: hai cột MINFL và MAJFL cho số lỗi trang nhỏ và lớn.12

    Đừng đổ tội cho bộ nhớ quá nhanh

    Một trong những cách đơn giản nhất để kiểm tra tình trạng bộ nhớ toàn hệ thống là chạy free hoặc xem /proc/meminfo để biết bao nhiêu bộ nhớ thật đang dùng cho bộ đệm (cache) và vùng đệm (buffer). Nếu không có nhiều bộ nhớ cache/buffer được dùng (mà phần bộ nhớ thật còn lại đã bị chiếm), có thể bạn cần thêm bộ nhớ. Nhưng Ward cảnh báo ngay: “quá dễ để đổ lỗi cho tình trạng thiếu bộ nhớ trong mọi vấn đề hiệu năng trên máy bạn”.113

Cụm khái niệm 04 Concept cluster 04

Bốn máy đo: vmstat, iostat, iotop, pidstat Bốn cái đồng hồ đo khác nhau Four meters: vmstat, iostat, iotop, pidstat

Trong số rất nhiều công cụ theo dõi hiệu năng hệ thống, vmstat là một trong những công cụ cổ nhất và có chi phí phụ trội tối thiểu. Ward gọi nó là thứ tiện tay để có cái nhìn tổng quát về việc nhân hoán đổi trang ra vào bao nhiêu lần, CPU bận cỡ nào, và tài nguyên vào/ra đang được dùng ra sao. Ông nói luôn mẹo mở khoá sức mạnh của nó: hiểu kết xuất của nó.114

Bốn lệnh này giống bốn cái đồng hồ trên bảng điều khiển xe: một cái đo chung, một cái đo đĩa, một cái đo ai đang đọc ghi đĩa, một cái đo riêng một chương trình. Nhớ nhé: đúng đồng hồ thì đọc ra đúng chuyện.

Among the many tools for monitoring system performance, vmstat is one of the oldest, with minimal overhead. Ward calls it handy for a high-level view of how often the kernel swaps pages in and out, how busy the CPU is, and how I/O resources are being used. He states the trick to unlocking its power at once: understand its output.114

Một chi tiết dễ bỏ sót khi đọc vmstat. Bạn thường bắt đầu nhìn từ dòng thứ hai của kết xuất — vì dòng đầu tiên là trung bình cho toàn bộ thời gian máy đã chạy, chứ không phải khoảng đo vừa rồi.1 Ward cũng thừa nhận chương này không khai thác hết các cột: bạn có thể đào sâu qua trang vmstat(8), nhưng có lẽ cần học thêm về quản lý bộ nhớ của nhân từ một khoá học hay một quyển như Operating System Concepts, ấn bản 10 (Wiley, 2018) của Silberschatz, Gagne và Galvin để hiểu chúng.11415

Sáu nhóm cột của vmstat. Kết xuất chia thành các nhóm: procs cho tiến trình, memory cho việc dùng bộ nhớ, swap cho các trang được kéo vào và đẩy ra vùng hoán đổi, io cho việc dùng đĩa, system cho số lần nhân chuyển sang mã của nhân, và cpu cho thời gian được các phần khác nhau của hệ thống sử dụng.114

Nói đơn giản. Bảng của vmstat có sáu nhóm cột: việc đang chạy, bộ nhớ, hoán đổi, đĩa, nhân, và CPU. Nhìn nhóm nào thì biết chuyện nhóm đó. Nhớ nhé: sáu nhóm, sáu câu chuyện.

vmstat's six column groups. The output falls into categories: procs for processes, memory for memory usage, swap for pages pulled in and out of swap, io for disk usage, system for the number of times the kernel switches into kernel code, and cpu for the time used by different parts of the system.114

vmstat 2  → toàn hệ thống, mỗi 2 s
iostat -d 2 → theo thiết bị
iotop    → theo luồng (TID)
pidstat -p 1329 1 → một tiến trình

vmstat → cả máy
iostat → từng ổ đĩa
iotop → ai đang đọc ghi
pidstat → một chương trình

vmstat 2  → whole system, every 2 s
iostat -d 2 → per device
iotop    → per thread (TID)
pidstat -p 1329 1 → one process

  1. vmstat

    vmstat — đọc một máy nhàn rỗi, rồi đọc một máy đang cạn bộ nhớ vmstat — máy đang rảnh hay đang đuối vmstat — reading an idle machine, then a memory-starved one

    Trong ví dụ vmstat 2 của sách (báo cáo mỗi hai giây) trên một hệ thống không làm gì nhiều: hệ thống có 320.416 KB bộ nhớ đã bị hoán đổi ra đĩa (cột swpd) và khoảng 3.027.000 KB (3 GB) bộ nhớ thật còn trống. Dù có một ít không gian hoán đổi đang được dùng, hai cột si (hoán đổi vào) và so (hoán đổi ra) đều bằng 0, cho biết nhân hiện không hoán đổi thứ gì vào hay ra khỏi đĩa. Cột buff chỉ lượng bộ nhớ nhân đang dùng cho vùng đệm đĩa.114

    Chạy vmstat 2 thì cứ hai giây có một dòng mới. Nếu hai cột si và so đều là 0 thì máy đang thoải mái. Nếu chúng bắt đầu nhảy số thì máy đang thiếu bộ nhớ. Nhớ nhé: si và so bằng 0 là tin tốt.

    In the book's vmstat 2 example (reporting every two seconds) on a system that isn't doing much: it has 320,416KB of memory swapped out to disk (swpd) and around 3,027,000KB (3GB) of real memory free. Even though some swap space is in use, the zero-valued si (swap-in) and so (swap-out) columns report the kernel is not currently swapping anything in or out. The buff column indicates memory the kernel is using for disk buffers.114

    Bạn gặp nó ở đâuWhere you meet it Bốn cột us, sy, id, wa dưới tiêu đề CPU lần lượt cho phần trăm thời gian CPU dành cho tác vụ người dùng, tác vụ hệ thống (nhân), thời gian nhàn rỗi, và thời gian chờ vào/ra. Trong ví dụ, CPU ngồi không 99 phần trăm thời gian.1 Bốn cột cuối cho biết CPU đang làm gì: việc của bạn, việc của nhân, ngồi không, hay đang chờ đĩa. The four columns us, sy, id, wa under the CPU heading give the percentage of time the CPU spends on user tasks, system (kernel) tasks, idle time, and waiting for I/O. In the example, the CPU sits idle 99 percent of the time.1

    Khi một chương trình lớn khởi động

    Listing 8-3 của sách cho thấy CPU bắt đầu có việc trong một quãng dài, nhất là từ các tiến trình người dùng; vì còn đủ bộ nhớ trống, lượng bộ nhớ dùng cho cache và buffer bắt đầu tăng khi nhân dùng đĩa nhiều hơn.1 Một chi tiết thú vị: nhân kéo về bộ nhớ một số trang từng bị hoán đổi ra (cột si) — nghĩa là chương trình vừa chạy có lẽ đã truy cập vài trang dùng chung với tiến trình khác, chuyện rất thường gặp vì nhiều tiến trình chỉ dùng mã trong một số thư viện chia sẻ lúc khởi động.1

    Khi bộ nhớ cạn kiệt

    Kết xuất khác hẳn khi bạn hết bộ nhớ: khi chỗ trống cạn dần, cả kích thước buffer lẫn cache đều giảm vì nhân ngày càng cần chỗ cho các tiến trình người dùng. Khi không còn gì nữa, bạn sẽ thấy hoạt động ở cột so (hoán đổi ra) lúc nhân bắt đầu chuyển trang lên đĩa — và gần như mọi cột kết xuất khác đều đổi theo để phản ánh khối lượng công việc nhân đang gánh: nhiều thời gian hệ thống hơn, nhiều dữ liệu ra vào đĩa hơn, và nhiều tiến trình bị chặn hơn vì bộ nhớ chúng muốn dùng không có sẵn.114

  2. iostat

    iostat — năm cột cho mỗi thiết bị iostat — đĩa nào đang bận iostat — five columns per device

    Mặc định vmstat cung cấp một ít thống kê vào/ra tổng quát; bạn lấy được mức dùng tài nguyên rất chi tiết theo từng phân vùng bằng vmstat -d, nhưng lượng kết xuất có thể làm bạn choáng. Thay vào đó, Ward giới thiệu một công cụ dành riêng cho vào/ra: iostat. Giống vmstat, khi chạy không kèm tuỳ chọn, iostat hiển thị thống kê cho toàn bộ thời gian máy đã chạy tới hiện tại.116

    Muốn biết ổ đĩa nào đang bận thì dùng iostat. Nó cho mỗi ổ một dòng: bao nhiêu lượt đọc ghi mỗi giây, bao nhiêu kilobyte đọc, bao nhiêu kilobyte ghi. Nhớ nhé: mỗi ổ một dòng, đọc và ghi riêng.

    By default vmstat provides some general I/O statistics; you can get very detailed per-partition usage with vmstat -d, but the volume may overwhelm you. Instead Ward introduces a tool just for I/O: iostat. Like vmstat, run without options it shows statistics for your machine's current uptime.116

    Bạn gặp nó ở đâuWhere you meet it Năm cột cho mỗi thiết bị: tps (số lần truyền dữ liệu trung bình mỗi giây), kB_read/s, kB_wrtn/s (trung bình kilobyte đọc và ghi mỗi giây), kB_read và kB_wrtn (tổng kilobyte đã đọc và đã ghi).116 Khi bạn nghi ổ đĩa là thủ phạm làm máy chậm. Five columns per device: tps (average data transfers per second), kB_read/s, kB_wrtn/s (average kilobytes read and written per second), kB_read and kB_wrtn (total kilobytes read and written).116

    Khoảng thời gian và phân vùng

    Giống vmstat, bạn cung cấp một đối số khoảng thời gian — iostat 2 để cập nhật mỗi hai giây — và khi dùng khoảng thời gian, bạn thường chỉ muốn hiện báo cáo thiết bị bằng tuỳ chọn -d (ví dụ iostat -d 2). Mặc định kết xuất bỏ qua thông tin phân vùng; dùng -p ALL để hiện tất cả — và vì một hệ thống điển hình có nhiều phân vùng, bạn sẽ nhận rất nhiều kết xuất.116

    Tổng phân vùng không bằng tổng đĩa

    Trong ví dụ của sách, sda1, sda2 và sda5 đều là phân vùng của đĩa sda, nên các cột đọc và ghi có phần chồng lấn. Nhưng tổng các cột phân vùng không nhất thiết cộng lại bằng cột của đĩa: dù một lần đọc từ sda1 cũng tính là một lần đọc từ sda, bạn vẫn có thể đọc thẳng từ sda — chẳng hạn khi đọc bảng phân vùng.1

  3. iotop

    iotop — công cụ hiếm hoi hiển thị luồng thay vì tiến trình iotop — ai đang đọc ghi đĩa nhiều nhất iotop — one of the few tools that shows threads, not processes

    Nếu cần đào sâu hơn để thấy tài nguyên vào/ra mà từng tiến trình dùng, iotop giúp được. Dùng nó giống dùng top: nó tạo một màn hình cập nhật liên tục cho thấy các tiến trình đang dùng nhiều vào/ra nhất, kèm một bản tóm tắt chung ở đầu.117 Điểm đáng chú ý nhất: cùng với các cột người dùng, lệnh và đọc/ghi, nó có cột TID thay vì cột PID — iotop là một trong số ít tiện ích hiển thị luồng thay vì tiến trình.1

    iotop giống top, nhưng xếp hạng theo việc đọc ghi đĩa chứ không theo CPU. Một điểm lạ: nó liệt kê từng luồng, không phải từng chương trình. Nhớ nhé: iotop đếm theo luồng.

    If you need to dig deeper into the I/O resources individual processes use, iotop helps. Using it is similar to using top: it generates a continuously updating display showing the processes using the most I/O, with a general summary at the top.117 Most notable: alongside the user, command and read/write columns there's a TID column instead of a PID column — iotop is one of the few utilities that displays threads instead of processes.1

    Bạn gặp nó ở đâuWhere you meet it Cột PRIO cho biết độ ưu tiên vào/ra; nó giống độ ưu tiên CPU nhưng ảnh hưởng tới tốc độ nhân lập lịch các lần đọc và ghi cho tiến trình. Trong một độ ưu tiên như be/4, phần be là lớp lập lịch còn con số là mức ưu tiên; số nhỏ hơn thì quan trọng hơn, nên nhân cho tiến trình ưu tiên be/3 nhiều thời gian vào/ra hơn tiến trình be/4.1 Khi máy kêu è è vì đĩa quay liên tục mà bạn không biết vì ai. The PRIO column shows the I/O priority; it resembles the CPU priority but affects how quickly the kernel schedules I/O reads and writes. In a priority like be/4, be is the scheduling class and the number is the priority level; lower numbers are more important, so the kernel allows more I/O time to a be/3 process than a be/4 one.1

    Ba lớp lập lịch vào/ra

    Nhân dùng lớp lập lịch để có thêm quyền kiểm soát khi sắp xếp vào/ra. Bạn sẽ thấy ba lớp trong iotop: be (best effort) — nhân cố hết sức lập lịch vào/ra một cách công bằng cho lớp này, và phần lớn tiến trình chạy dưới lớp này; rt (real time) — nhân lập lịch mọi vào/ra thời gian thực trước bất kỳ lớp nào khác, bất kể thế nào; và idle — nhân chỉ thực hiện vào/ra cho lớp này khi không còn vào/ra nào khác phải làm, và lớp idle không có mức ưu tiên.1

    Đổi độ ưu tiên vào/ra

    Bạn kiểm tra và thay đổi độ ưu tiên vào/ra của một tiến trình bằng tiện ích ionice; chi tiết ở trang ionice(1). Ward nói thẳng phần kết luận thực dụng: bạn có lẽ sẽ chẳng bao giờ cần bận tâm tới độ ưu tiên vào/ra.118

  4. pidstat

    pidstat — một tiến trình, một dòng mỗi giây, không xoá quá khứ pidstat — ghi nhật ký cho một chương trình pidstat — one process, one line per second, history kept

    Bạn đã thấy cách theo dõi các tiến trình cụ thể bằng top và iotop. Nhưng màn hình của chúng làm mới theo thời gian, và mỗi lần cập nhật lại xoá mất kết xuất trước đó. Tiện ích pidstat cho bạn thấy mức tiêu thụ tài nguyên của một tiến trình theo thời gian theo lối của vmstat — mỗi khoảng một dòng mới, giữ nguyên các dòng cũ. Ví dụ của sách theo dõi tiến trình 1329, cập nhật mỗi giây: pidstat -p 1329 1.119

    top làm mới màn hình nên bạn mất dữ liệu cũ. pidstat thì in thêm một dòng mới mỗi giây, nên bạn giữ được cả lịch sử để so sánh. Nhớ nhé: muốn so sánh theo thời gian thì dùng pidstat.

    You've seen how to monitor specific processes with top and iotop. But their displays refresh over time, and each update erases the previous output. The pidstat utility lets you see a process's resource consumption over time in the style of vmstat — a new line per interval, old lines kept. The book's example monitors process 1329, updating every second: pidstat -p 1329 1.119

    Bạn gặp nó ở đâuWhere you meet it Kết xuất mặc định cho phần trăm thời gian người dùng và thời gian hệ thống, tổng phần trăm thời gian CPU, và thậm chí cả việc tiến trình đang chạy trên CPU nào.119 Khi bạn muốn xem một chương trình ngốn máy đều đều hay chỉ thỉnh thoảng. The default output shows the percentages of user and system time and the overall percentage of CPU time, and even tells you which CPU the process was running on.119

    Cột %guest

    Ward gọi cột %guest là “hơi lạ”: đó là phần trăm thời gian tiến trình dành để chạy thứ gì đó bên trong một máy ảo. Trừ khi bạn đang chạy máy ảo, đừng bận tâm tới nó.1

    Không chỉ CPU

    Dù mặc định hiện mức dùng CPU, pidstat làm được nhiều hơn thế: tuỳ chọn -r để theo dõi bộ nhớ và -d để bật theo dõi đĩa. Trang pidstat(1) còn nhiều tuỳ chọn nữa cho luồng, chuyển ngữ cảnh, hay gần như bất kỳ thứ gì đã bàn trong chương.119

Cụm khái niệm 05 Concept cluster 05

Nhóm điều khiển: từ “nhìn” sang “giới hạn” cgroups — đặt hạn mức cho một nhóm Control groups: from watching to limiting

Ý tưởng cơ bản rất gọn: bạn đặt nhiều tiến trình vào một cgroup, và điều đó cho phép bạn quản lý tài nguyên chúng tiêu thụ trên phạm vi cả nhóm. Ví dụ, nếu muốn giới hạn lượng bộ nhớ mà một tập tiến trình có thể tiêu thụ cộng gộp, một cgroup làm được việc đó. Sau khi tạo cgroup, bạn thêm tiến trình vào nó, rồi dùng một bộ điều khiển (controller) để thay đổi cách các tiến trình đó hành xử — chẳng hạn có bộ điều khiển cpu cho phép giới hạn thời gian bộ xử lý, một bộ điều khiển memory, và vân vân.120

cgroup giống như xếp nhiều chương trình vào chung một cái hộp, rồi dán lên hộp một tấm biển: “cả hộp này chỉ được dùng ngần này bộ nhớ”. Muốn giới hạn gì thì gắn thêm một cái “bộ điều khiển” cho hộp đó. Nhớ nhé: đặt luật cho cả hộp, không đặt cho từng người.

The basic idea is compact: you place several processes into a cgroup, which lets you manage the resources they consume on a group-wide basis. For example, if you want to limit the memory a set of processes may cumulatively consume, a cgroup can do it. After creating a cgroup you add processes to it, then use a controller to change how those processes behave — there is a cpu controller allowing you to limit processor time, a memory controller, and so on.120

Một đính chính về quyền sở hữu. Ward ghi chú riêng: dù systemd dùng tính năng cgroup rất nhiều và phần lớn (nếu không muốn nói là toàn bộ) cgroup trên máy bạn có thể do systemd quản lý, cgroup nằm trong không gian nhân và không phụ thuộc vào systemd.120 Đây là phân biệt hữu ích khi bạn đọc tài liệu: cấu trúc thư mục bạn thấy có thể do systemd dựng, nhưng cơ chế thì của nhân.

Hai phiên bản, một khác biệt cấu trúc. Có hai phiên bản cgroup, 1 và 2, và không may là cả hai hiện đều đang được dùng và có thể được cấu hình đồng thời trên một hệ thống, dẫn tới khả năng gây nhầm lẫn.120 Trong cgroups v1, mỗi loại bộ điều khiển (cpu, memory…) có tập cgroup riêng; một tiến trình có thể thuộc một cgroup cho mỗi bộ điều khiển, nghĩa là nó có thể thuộc nhiều cgroup. Trong cgroups v2, một tiến trình chỉ có thể thuộc một cgroup duy nhất, và bạn thiết lập nhiều loại bộ điều khiển khác nhau cho từng cgroup.120

Nói đơn giản. Bản cũ (v1): mỗi loại hạn mức là một cái hộp riêng, nên một chương trình nằm trong nhiều hộp. Bản mới (v2): mỗi chương trình chỉ nằm trong một hộp, và cái hộp đó có thể mang nhiều loại hạn mức. Nhớ nhé: bản mới gọn hơn — một chương trình, một hộp.

Two versions, one structural difference. There are two versions of cgroups, 1 and 2, and unfortunately both are currently in use and can be configured simultaneously on a system, leading to potential confusion.120 In cgroups v1, each type of controller (cpu, memory, …) has its own set of cgroups; a process can belong to one cgroup per controller, meaning it can belong to multiple cgroups. In cgroups v2, a process can belong to only one cgroup, and you set up different types of controllers for each cgroup.120

v1: 3 nhóm × 2 controller = 6 cgroup
v2: 3 nhóm × 2 controller = 3 cgroup
giao diện: /sys/fs/cgroup (cgroup2)
tệp giao diện: cgroup.*

bản cũ: 3 nhóm cần 6 hộp
bản mới: 3 nhóm cần 3 hộp
xem ở: /sys/fs/cgroup
tệp điều khiển bắt đầu bằng cgroup.

v1: 3 sets × 2 controllers = 6 cgroups
v2: 3 sets × 2 controllers = 3 cgroups
interface: /sys/fs/cgroup (cgroup2)
interface files: cgroup.*

  1. viewing cgroups

    Xem cgroup — qua hệ thống tệp, không qua lời gọi hệ thống Xem cgroup bằng cách mở thư mục Viewing cgroups — through the filesystem, not a system call

    Khác với giao diện lời gọi hệ thống Unix truyền thống để tương tác với nhân, cgroup được truy cập hoàn toàn qua hệ thống tệp, thường được gắn dưới dạng hệ thống tệp cgroup2 tại /sys/fs/cgroup. (Nếu bạn cũng đang chạy cgroups v1, chỗ này có lẽ nằm dưới /sys/fs/cgroup/unified.)120 Bạn liệt kê cgroup v1 và v2 của bất kỳ tiến trình nào bằng cách xem tệp cgroup của nó trong /proc/<pid> — ví dụ cat /proc/self/cgroup cho cgroup của chính shell bạn.121

    Bạn không cần lệnh đặc biệt nào để xem cgroup — chỉ cần cat mấy tệp trong thư mục /sys/fs/cgroup. Gõ cat /proc/self/cgroup thì thấy cái hộp mà shell của bạn đang nằm trong. Nhớ nhé: cgroup là thư mục, không phải lệnh.

    Unlike the traditional Unix system-call interface for interacting with the kernel, cgroups are accessed entirely through the filesystem, usually mounted as a cgroup2 filesystem under /sys/fs/cgroup. (If you're also running cgroups v1, this will probably be under /sys/fs/cgroup/unified.)120 You can list the v1 and v2 cgroups for any process by looking at its cgroup file in /proc/<pid> — for instance cat /proc/self/cgroup for your own shell.121

    Bạn gặp nó ở đâuWhere you meet it Trong kết xuất của /proc/self/cgroup, các số từ 2 đến 12 là của cgroups v1 (bộ điều khiển được liệt kê ngay cạnh số); số 1 cũng thuộc v1 nhưng không có bộ điều khiển, chỉ dùng cho mục đích quản lý; và dòng cuối, số 0, là của cgroups v2. Trên một hệ thống không có cgroups v1, đó sẽ là dòng duy nhất.121 Dòng bắt đầu bằng số 0 là bản mới. Nếu chỉ có một dòng thì máy bạn chỉ dùng bản mới. In /proc/self/cgroup output, numbers 2–12 are for cgroups v1 (their controllers listed next to the number); number 1 is also v1 but has no controller and exists for management purposes only; and the last line, number 0, is for cgroups v2. On a system without cgroups v1, that will be the only line.121

    Tên cgroup là phân cấp

    Tên cgroup có tính phân cấp và trông giống các phần của đường dẫn tệp: trong ví dụ của sách có những cgroup tên /user.slice và những cái khác tên /user.slice/user-1000.slice/session-2.scope.1 Những tên dưới user.slice có chứa session là các phiên đăng nhập do systemd gán — bạn sẽ thấy chúng khi xem cgroup của một shell; còn cgroup cho các dịch vụ hệ thống của bạn nằm dưới system.slice.1

    Các tệp giao diện chính

    Trong nhiều tệp có thể có ở đó, các tệp giao diện cgroup chính bắt đầu bằng cgroup. Hãy bắt đầu bằng cgroup.procs (dùng cat là được), tệp này liệt kê các tiến trình trong cgroup; một tệp tương tự, cgroup.threads, bao gồm cả luồng.120 Để xem các bộ điều khiển đang dùng, xem cgroup.controllers; trong ví dụ của sách nó trả về memory pids — hai bộ điều khiển mà phần lớn cgroup dùng cho shell đều có, kiểm soát lượng bộ nhớ dùng và tổng số tiến trình trong cgroup.1

    Đọc một giá trị: pids.current và memory.max

    Để tương tác với một bộ điều khiển, tìm các tệp khớp với tiền tố của nó. Muốn biết số luồng đang chạy trong cgroup, xem pids.current; muốn biết lượng bộ nhớ tối đa cgroup được tiêu thụ, xem memory.max. Giá trị max nghĩa là cgroup này không có giới hạn cụ thể — nhưng vì cgroup có tính phân cấp, một cgroup ở phía trên chuỗi thư mục vẫn có thể giới hạn nó.120

  2. manipulating cgroups

    Thao tác và tạo cgroup — ba luật dễ vấp Tạo cgroup — ba điều luật Manipulating and creating cgroups — three rules that trip you up

    Ward nói rằng bạn có lẽ sẽ chẳng bao giờ cần sửa cgroup, nhưng việc đó rất dễ. Để đặt một tiến trình vào cgroup, hãy ghi PID của nó vào tệp cgroup.procs với quyền root: # echo pid > cgroup.procs. Đây là cách phần lớn thay đổi với cgroup hoạt động — ví dụ, muốn giới hạn số PID tối đa của một cgroup ở mức 3.000, làm như sau: # echo 3000 > pids.max.120

    Muốn cho một chương trình vào hộp, bạn ghi số của nó vào một tệp. Muốn đặt hạn mức, bạn ghi con số hạn mức vào một tệp khác. Tất cả chỉ là ghi tệp. Nhớ nhé: đặt luật = ghi một con số vào một tệp.

    Ward says you probably won't ever need to alter cgroups, but it's easy. To put a process into a cgroup, write its PID to its cgroup.procs file as root: # echo pid > cgroup.procs. This is how many changes to cgroups work — for example, to limit a cgroup's maximum number of PIDs to, say, 3,000: # echo 3000 > pids.max.120

    Bạn gặp nó ở đâuWhere you meet it Về mặt kỹ thuật, tạo cgroup dễ như tạo một thư mục con ở đâu đó trong cây cgroup — khi bạn làm vậy, nhân tự động tạo các tệp giao diện; và nếu một cgroup không có tiến trình nào, bạn gỡ nó bằng rmdir ngay cả khi các tệp giao diện vẫn còn đó.1 Tạo hộp mới = tạo một thư mục mới. Bỏ hộp rỗng = xoá thư mục. Technically, creating a cgroup is as easy as creating a subdirectory somewhere in the cgroup tree — the kernel then automatically creates the interface files; and if a cgroup has no processes you can remove it with rmdir even with the interface files present.1

    Ba luật chi phối cgroup

    (1) Bạn chỉ đặt được tiến trình vào các cgroup ở tầng ngoài cùng (“lá”): nếu có /my-cgroup và /my-cgroup/my-subgroup, bạn không đặt tiến trình vào /my-cgroup được, nhưng /my-cgroup/my-subgroup thì được (ngoại lệ là khi các cgroup không có bộ điều khiển nào). (2) Một cgroup không thể có bộ điều khiển mà cgroup cha của nó không có. (3) Bạn phải chỉ định tường minh các bộ điều khiển cho cgroup con, thông qua tệp cgroup.subtree_control — ví dụ muốn một cgroup con có bộ điều khiển cpu và pids, hãy ghi +cpu +pids vào tệp đó.120

    Ngoại lệ: cgroup gốc

    Một ngoại lệ cho các luật trên là cgroup gốc, nằm ở đáy của phân cấp: bạn có thể đặt tiến trình vào cgroup này. Một lý do bạn có thể muốn làm thế là để tách một tiến trình khỏi quyền kiểm soát của systemd.1

  3. cpu.stat

    Xem mức dùng tài nguyên — cả đời một nhóm, gộp cả tiến trình con Xem cả nhóm đã dùng bao nhiêu Viewing resource utilization — a group's whole lifespan, subprocesses included

    Ngoài việc giới hạn tài nguyên theo cgroup, bạn còn xem được mức dùng tài nguyên hiện tại của mọi tiến trình theo cgroup của chúng. Ngay cả khi không bật bộ điều khiển nào, bạn vẫn thấy mức dùng CPU của một cgroup qua tệp cpu.stat của nó — ví dụ của sách trả về ba dòng usage_usec, user_usec, system_usec.120

    Bạn xem được cả nhóm đã dùng bao nhiêu CPU từ lúc sinh ra, kể cả phần của những chương trình con đã chết. Nhớ nhé: sổ ghi cho cả hộp, không mất dấu khi ai đó rời đi.

    Besides limiting resources by cgroup, you can also see the current resource utilization of all processes across their cgroups. Even with no controllers enabled, you can see a cgroup's CPU usage by looking at its cpu.stat file — the book's example returns three lines: usage_usec, user_usec, system_usec.120

    Bạn gặp nó ở đâuWhere you meet it Vì đây là mức dùng CPU tích luỹ trên toàn bộ vòng đời của cgroup, bạn thấy được một dịch vụ tiêu thụ bao nhiêu thời gian bộ xử lý ngay cả khi nó sinh ra nhiều tiến trình con rồi các tiến trình đó kết thúc.1 Khi một dịch vụ cứ sinh con rồi con chết, mà bạn vẫn muốn tính tổng. Because this is accumulated CPU usage over the cgroup's entire lifespan, you can see how a service consumes processor time even if it spawns many subprocesses that eventually terminate.1

    Khi bật bộ điều khiển memory

    Bạn xem được các loại mức dùng khác nếu bộ điều khiển thích hợp đã bật: ví dụ bộ điều khiển memory cho truy cập vào tệp memory.current (mức dùng bộ nhớ hiện thời) và tệp memory.stat (dữ liệu bộ nhớ chi tiết cho toàn bộ vòng đời của cgroup). Các tệp này không có ở cgroup gốc.120

    Đi xa hơn

    Ward chỉ thẳng chỗ tra cứu: chi tiết đầy đủ về cách dùng từng bộ điều khiển, cũng như mọi luật tạo cgroup, nằm trong tài liệu của nhân — “chỉ cần tìm trực tuyến ‘cgroups2 documentation’ là bạn sẽ thấy”.120 Hiểu cơ chế cơ bản của cgroup cũng giúp giải thích cách systemd tổ chức tiến trình, và sau này khi đọc về container, bạn sẽ thấy chúng được dùng cho một mục đích rất khác.1

Đính chính Corrections

Ba ngộ nhận mà người đọc lần đầu hay mắc Ba chỗ hay hiểu nhầm Three misconceptions first readers hit

Phần này thuộc mức đọc Đầy đủ: nó đối chiếu điều người đọc thường nghĩ với điều bản văn thật sự nói.

Phần này hơi khó, bạn có thể bỏ qua và quay lại sau. Nhớ nhé: hiểu chậm mà chắc vẫn hơn.

This block belongs to the Đầy đủ (full) reading level: it sets what readers usually assume against what the text actually says.

“Tải trung bình 4 nghĩa là CPU đã quá tải” "A load average of 4 means the CPU is overloaded"

Ngộ nhận: con số tải trung bình là một thang đo tuyệt đối, cứ vượt một ngưỡng nào đó là hệ thống có vấn đề.

Bản văn nói: tải trung bình cao không nhất thiết nghĩa là hệ thống đang gặp trục trặc — một hệ thống đủ bộ nhớ và tài nguyên vào/ra dễ dàng gánh được nhiều tiến trình đang chạy, và nếu máy vẫn phản hồi tốt thì đừng hoảng.1 Con số còn phải đọc theo số lõi: với hai lõi, tải 1 nghĩa là chỉ một lõi có việc tại một thời điểm, còn tải 2 nghĩa là cả hai lõi vừa đủ việc suốt.1 Trên máy chủ web hay máy chủ tính toán, tiến trình có thể sinh ra và kết thúc nhanh đến mức chính cơ chế đo không hoạt động hiệu quả.1

Misconception: the load average is an absolute scale, and crossing some threshold means trouble.

The text says: a high load average doesn't necessarily mean your system is in trouble — a system with enough memory and I/O resources can easily handle many running processes, and if it still responds well, don't panic.1 The number must also be read against the core count: with two cores, a load of 1 means only one core is likely active at a time, and 2 means both have just enough to do all the time.1 On a web or compute server, processes can start and terminate so quickly that the measurement mechanism itself can't function effectively.1

“Lỗi trang là lỗi — nên phải tìm cách loại bỏ” "Page faults are errors — so they must be eliminated"

Ngộ nhận: chữ “lỗi” trong lỗi trang hàm ý điều gì đó hỏng hóc.

Bản văn nói: lỗi trang nhỏ là chuyện thường ngày — “không có gì phải lo, và rất nhiều lỗi loại này xảy ra trong lúc một tiến trình chạy”.1 Ngay cả một số lỗi trang lớn cũng không tránh được, chẳng hạn khi nạp mã từ đĩa lúc chạy chương trình lần đầu.1 Điều đáng lo không phải sự tồn tại của lỗi trang, mà là số lượng lớn lỗi trang lớn khi máy cạn bộ nhớ và bắt đầu thrash.1 Trong ví dụ của sách, một lệnh cal hết sức bình thường đã sinh ra 254 lỗi trang nhỏ.1

Misconception: the word "fault" in page fault implies something broken.

The text says: minor page faults are routine — "nothing to worry about, and many occur as a process runs."1 Even some major faults are unavoidable, such as loading code from disk when running a program for the first time.1 What matters is not that faults occur but a lot of major ones when the machine runs out of memory and starts thrashing.1 In the book's example an utterly ordinary cal command produced 254 minor faults.1

“cgroups là tính năng của systemd” "cgroups are a systemd feature"

Ngộ nhận: vì mọi cgroup bạn thấy đều có tên kiểu user.slice và system.slice, cgroup hẳn là do systemd tạo ra và sở hữu.

Bản văn nói: dù systemd dùng tính năng cgroup rất nhiều và phần lớn (nếu không muốn nói là toàn bộ) cgroup trên máy bạn có thể do nó quản lý, cgroup nằm trong không gian nhân và không phụ thuộc vào systemd.120 Chính vì thế bạn thao tác với chúng bằng cách đọc ghi tệp dưới /sys/fs/cgroup, chứ không qua bất kỳ lệnh riêng nào của systemd.1

Misconception: since every cgroup you see is named like user.slice or system.slice, cgroups must be created and owned by systemd.

The text says: although systemd makes extensive use of the cgroup feature and most (if not all) of the cgroups on your system may be managed by it, cgroups are in kernel space and do not depend on systemd.120 That is exactly why you manipulate them by reading and writing files under /sys/fs/cgroup, not through any systemd-specific command.1

Tự kiểm tra Self-check

Bạn đã đọc được các con số chưa? Thử trả lời xem nào Can you read the numbers yet?

Trả lời bằng lời của bạn, không tra sách. Nếu một câu khiến bạn ngập ngừng, đó chính là công cụ bạn nên mở lên gõ thử.

Thử trả lời miệng thôi, không cần giở lại. Câu nào bí thì mở terminal gõ thử lệnh đó nhé. Nhớ nhé: chỗ bí chính là chỗ cần gõ.

Answer in your own words, without looking back. Whichever question makes you hesitate points at the tool you should open a terminal and try.

  1. ps và top khác nhau ở điểm cốt lõi nào, và vì sao khác biệt đó quyết định việc bạn chọn công cụ nào?

    Gợi ý sâu hơn: hãy nói thêm ba phím M, T, P sắp xếp theo tiêu chí nào.

  2. Cột FD trong kết xuất lsof có thể chứa hai loại nội dung khác nhau — đó là hai loại nào?

    Gợi ý sâu hơn: cwd thuộc loại nào, và con số 3 thuộc loại nào?

  3. strace và ltrace quan sát hai tầng khác nhau — hãy đặt chúng vào mô hình ba tầng của Chương 1.

    Gợi ý sâu hơn: vì sao ltrace không chạy được trên nhị phân liên kết tĩnh?

  4. Trong time, hiệu số real − (user + sys) nói lên điều gì về tiến trình?

    Gợi ý sâu hơn: vì sao muốn xem lỗi trang bạn phải dùng /usr/bin/time chứ không dùng bản dựng sẵn của shell?

  5. Vì sao một máy mở hai mươi cửa sổ vẫn có thể có tải trung bình gần 0?

    Gợi ý sâu hơn: tải trung bình đếm tiến trình ở trạng thái nào, và bỏ qua trạng thái nào?

  6. Lỗi trang nhỏ khác lỗi trang lớn ở chỗ nào, và loại nào đáng lo?

    Gợi ý sâu hơn: hai cột nào của ps -o cho bạn hai con số đó?

  7. Trong vmstat, vì sao bạn nên bắt đầu đọc từ dòng thứ hai chứ không phải dòng đầu?

    Gợi ý sâu hơn: hai cột si và so bằng 0 nói lên điều gì?

  8. Khác biệt cấu trúc giữa cgroups v1 và v2 là gì — nói bằng đúng một câu?

    Gợi ý sâu hơn: ba nhóm tiến trình với hai bộ điều khiển cần bao nhiêu cgroup ở mỗi phiên bản?

  1. Lệnh nào cho bạn xem ai đang ngốn máy nhiều nhất, và nó tự cập nhật bao lâu một lần?

  2. Muốn biết chương trình nào đang mở một tệp thì dùng lệnh gì?

  3. Máy tính chỉ có ba thứ để tranh nhau — kể tên ba thứ đó.

  4. nice để làm gì? Số lớn hơn nghĩa là được ưu tiên hơn hay chịu nhường hơn?

  5. “Trang nhớ” là gì, và một trang thường to bao nhiêu?

  6. cgroup dùng để làm gì? Nói một câu thôi cũng được.

  1. What is the core difference between ps and top, and why does it decide which tool you reach for?

  2. The FD column in lsof output can hold two different kinds of content — which two?

  3. strace and ltrace watch two different layers — place them in Chapter 1's three-level model.

  4. In time, what does the difference real − (user + sys) tell you about a process?

  5. Why can a machine with twenty open windows still show a load average near 0?

  6. How does a minor page fault differ from a major one, and which should worry you?

  7. In vmstat, why should you start reading at the second line rather than the first?

  8. What is the structural difference between cgroups v1 and v2 — in exactly one sentence?

Khép lại chương Closing the chapter

Đừng để hiệu năng làm bạn phân tâm: tối ưu một hệ thống vốn đã chạy đúng là phí thời gian. Hãy tập trung hiểu các công cụ thật sự đo cái gì — và bạn sẽ nhìn thấy nhân đang hành động khi nó chia tài nguyên cho các tiến trình.1

Máy đang chạy tốt thì đừng vặn nữa — vặn chỉ tốn thời gian. Học mấy lệnh này để nhìn thấy máy đang chia phần cho ai. Nhớ nhé: học để nhìn, không phải để vặn.

Don't get distracted by performance: trying to optimize a system that's already working correctly is a waste of time. Concentrate on understanding what the tools actually measure — and you'll see the kernel in action as it divides resources among processes.1