当然可以!下面是一个故事化版本,将你提出的问题——“如何获取进程的ID、父ID、组ID、有效组ID、子进程组ID”——融入一个生动的技术冒险故事中,帮助你轻松理解这些概念。


🌌《进程王国:身份之谜》

在遥远的 Linux 内核大陆,有一个由无数“进程”组成的庞大王国。这里没有国王,却有秩序;没有魔法,却有系统调用。每个进程都像一位公民,拥有自己的“身份证明”。

这一天,年轻的程序员少年 小程 被召唤进入内核世界,任务是调查一桩神秘事件:一个进程在系统中“消失”了,只留下它的子进程在等待回收

为了揭开真相,他必须学会识别每一个进程的身份信息。


🏛️ 第一站:自己的身份 —— getpid()getuid()

小程刚落地,就被一道光芒笼罩。一个声音响起:

“你是谁?报上你的 PID(进程ID)和 UID(用户ID)!”

小程一愣,随即想起老师教的口诀:

我是谁?getpid() 告诉我!” “我属于谁?getuid() 来确认!

他轻声念出:

 pid_t my_pid = getpid();    // 我的身份证号
 uid_t my_uid = getuid();    // 我的用户身份
 gid_t my_gid = getgid();    // 我的主组身份

光芒消散,守门人点头:“身份确认,小程,PID=1234,允许通行。”


👨 第二站:父亲是谁?—— getppid()

进入“进程森林”后,小程遇到一位迷路的孤儿进程(Orphan Process)。

“我不知道我的父亲是谁……我只记得他叫 init,但我不确定。”

小程安慰道:“别怕,我们查一查你的 PPID(父进程ID)。”

他教孤儿进程调用:

 pid_t parent_pid = getppid();

结果返回:PPID=1

“原来你是 init(PID=1)的孩子!他是所有孤儿的收养者。”

孤儿进程热泪盈眶:“我终于知道我是谁的孩子了!”


🏘️ 第三站:我在哪个组?—— getpgid()getpgrp()

继续前行,小程来到“进程组广场”。这里有成群结队的进程,他们属于同一个“作业”(Job),比如一个 shell 命令管道:

 ps aux | grep nginx | wc -l

这三个进程(ps, grep, wc)属于同一个进程组,由组长统一管理。

小程想知道:“我在哪个组?”

他调用:

 pid_t my_pgid = getpgrp();           // 获取自己的进程组ID
 // 或者
 pid_t my_pgid2 = getpgid(0);         // 0 表示当前进程

系统返回:PGID=1001

“原来我和 grep 是一个团队的!”


🛡️ 第四站:我以谁的身份在运行?—— geteuid()getegid()

突然,小程想修改系统配置文件 /etc/shadow,但权限被拒。

“奇怪,我是普通用户,为什么不能改?”

这时,一位白发老者出现:“你得看你的有效身份!”

老者教他:

 uid_t real_uid = getuid();      // 真实身份:普通用户
 uid_t effective_uid = geteuid(); // 有效身份:可能是 root(如果程序有 setuid 位)
 ​
 gid_t real_gid = getgid();
 gid_t effective_gid = getegid();

小程恍然大悟:“原来 passwd 命令之所以能改密码,是因为它的有效 UID 是 0(root),哪怕我是个普通用户!”


👶 第五站:我的孩子在哪个组?—— 子进程的组 ID

小程决定创建一个子进程来协助调查:

 pid_t child_pid = fork();
 ​
 if (child_pid == 0) {
     // 子进程
     pid_t child_pgid = getpgrp();  // 子进程的组ID
     printf("I am child, PID=%d, PGID=%d\n", getpid(), child_pgid);
 } else {
     // 父进程
     printf("I created child with PID=%d\n", child_pid);
 }

结果:

 I created child with PID=1235
 I am child, PID=1235, PGID=1001

“原来子进程默认继承父进程的组ID!除非我调用 setpgid() 改变它。”


🏁 终章:真相大白

小程终于找到了那个“消失”的进程——它已经变成 僵尸进程(Zombie),但它的子进程还在等待 wait() 被调用。

他用 getppid() 确认自己是父进程,然后调用 wait() 回收资源,系统恢复平静。

内核之声响起:

“你已掌握进程身份的五大核心: PID、PPID、PGID、UID、EUID。 你是真正的系统守护者。”


📜 附:身份获取函数速查表

信息 函数 说明
自己的 PID getpid() 我是谁
父进程 PID getppid() 谁生了我
自己的 PGID getpgrp()getpgid(0) 我在哪个团队
真实 UID/GID getuid(), getgid() 我的真实身份
有效 UID/GID geteuid(), getegid() 我当前以谁的身份运行
子进程 PGID 在子进程中调用 getpgrp() 子进程默认继承父进程组ID

✅ 结语

在 Linux 的世界里,每个进程都有身份,每个身份都有意义。 掌握这些系统调用,就像拥有了一张“内核通行证”,让你在系统深处自由穿行。

小程收起代码,轻声说:

“我不是在写程序, 我是在与无数进程, 共同编织系统的秩序。”

🌌 故事完。


如果你喜欢这种“技术+故事”的风格,我还可以为你编写 线程篇:线程ID与同步之战内存篇:虚拟地址的迷宫 等系列故事。欢迎继续提问!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐