Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 40.124 phút đọc

Tiến trình, PID, và /proc

Sau bài này bạn sẽ làm được

  • Kể các thành phần của một tiến trình
  • Lấy PID, PPID, UID bằng lời gọi hệ thống
  • Đọc thông tin tiến trình qua /proc
  • Phân biệt chương trình với tiến trình

Phần này nói chuyện trực tiếp với hệ điều hành. Trước khi tạo, thay, hay chờ một tiến trình, phải biết một tiến trình gồm những gì. Bài này mở nó ra và nhìn vào bên trong qua /proc.

#Tiến trình là gì

Tiến trình
Một chương trình đang chạy. Nó gồm mã lệnh, dữ liệu, ngăn xếp, heap, bảng mô tả tệp, và một không gian địa chỉ riêng mà không tiến trình khác nhìn thấy được.
  Tien trinh (mot khong gian dia chi rieng)
  +-------------------------------------------+
  |  ma lenh   (.text)     chi doc            |
  |  du lieu   (.data .bss) bien toan cuc     |
  |  heap                  malloc lon len ->  |
  |     ...                                   |
  |  <- ngan xep lon xuong  bien cuc bo       |
  +-------------------------------------------+
  |  bang mo ta tep: 0 stdin, 1 stdout, ...   |
  +-------------------------------------------+

/* Moi tien trinh co bang mo ta tep RIENG va khong gian dia chi
   RIENG. Hai tien trinh cung chay mot chuong trinh van la hai
   khong gian dia chi tach biet: sua bien trong cai nay khong
   anh huong cai kia. Do la khac biet co ban voi luong (Chuong 45),
   noi cac luong CHIA SE khong gian dia chi. */

#PID và họ hàng

Lấy PID, PPID, UID
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void) {
    pid_t pid  = getpid();      /* PID cua CHINH tien trinh nay */
    pid_t ppid = getppid();     /* PID cua tien trinh CHA */
    uid_t uid  = getuid();      /* ID nguoi dung so huu */

    printf("PID  = %d\n", pid);
    printf("PPID = %d\n", ppid);
    printf("UID  = %d\n", uid);
    return 0;
}
terminal
gcc pid.c -o pid && ./pid
PID  = 24817
PPID = 3921
UID  = 1000
# Chay lai: PID doi (moi lan chay la mot tien trinh moi)
./pid
PID  = 24831
PPID = 3921
UID  = 1000
Lời gọiTrả về
getpid()PID của chính tiến trình
getppid()PID của tiến trình cha
getuid()ID người dùng thật
geteuid()ID người dùng hiệu lực, khác uid khi setuid
getgid()ID nhóm

#Nhìn vào /proc

/proc
Một hệ tệp ảo của Linux. Mỗi tiến trình có một thư mục /proc/PID/ chứa thông tin về nó dưới dạng tệp đọc được. Không phải tệp thật trên đĩa; nhân sinh ra nội dung khi bạn đọc. /proc/self/ luôn trỏ tới tiến trình đang đọc.
terminal
# Thong tin tien trinh hien tai
cat /proc/self/status | head -8
Name:	cat
Umask:	0022
State:	R (running)
Tgid:	24902
Pid:	24902
PPid:	3921
TracerPid:	0
Uid:	1000	1000	1000	1000
# Cac mo ta tep dang mo (0,1,2 la stdin,stdout,stderr)
ls -l /proc/self/fd
lrwx------ 0 -> /dev/pts/2
lrwx------ 1 -> /dev/pts/2
lrwx------ 2 -> /dev/pts/2
lr-x------ 3 -> /proc/24902/fd

#Chương trình và tiến trình

Tự làm thử

  1. Viết chương trình in PID, PPID, UID và chạy nó vài lần, quan sát PID đổi.
  2. Đọc /proc/self/status và tìm dòng bộ nhớ đang dùng (VmRSS).
  3. Đếm số mô tả tệp trong /proc/self/fd và giải thích tại sao có bốn cái.
  4. Chạy pstree và tìm chương trình của bạn trong cây.
  5. Mở /proc/self/maps và tìm vùng ngăn xếp cùng vùng heap.
  6. Giải thích khác biệt giữa getuid và geteuid cho một chương trình setuid.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • Tiến trình là chương trình đang chạy, có không gian địa chỉ và bảng mô tả tệp riêng.
  • getpid, getppid, getuid cho biết tiến trình là ai và con của ai; mỗi tiến trình có đúng một cha.
  • /proc/PID/ là cửa sổ nhìn vào một tiến trình; /proc/self/fd là công cụ tìm rò rỉ mô tả tệp.
  • Một chương trình trên đĩa có thể sinh nhiều tiến trình, mỗi cái độc lập.
  • Unix tách tạo tiến trình (fork) khỏi thay chương trình (exec); Windows gộp chúng, nên MinGW không có fork.