进程定义:
进程控制块 (PCB):
task_struct 结构的主要内容:
组织进程 可以在内核源代码⾥找到它。所有运⾏在系统⾥的进程都以task_struct链表的形式存在内核⾥。

查看进程信息

获取进程标识符
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()6
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
return 0;
}创建进程:fork() 系统调用 使用 fork() 系统调用可以创建子进程。fork() 会返回两个值:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int ret = fork();
if(ret < 0)
{
perror("fork");
return 1;
}
else if(ret == 0)
{
//child
printf("I am child : %d!, ret: %d\n", getpid(), ret);
}else
{
//father
printf("I am father : %d!, ret: %d\n", getpid(), ret);
}
sleep(1);
return 0;
}fork为什么会有两个返回值? fork() 系统调用会有两个返回值,这是因为它用于创建一个新的进程。具体来说:
原因:fork() 的这种行为是为了区分父子进程,便于父进程与子进程执行不同的代码。通过返回值,父进程可以判断自己是父进程,执行一部分逻辑;而子进程可以判断自己是子进程,执行不同的代码逻辑。
两个返回值各自给⽗⼦如何返回? 父进程返回值:
子进程返回值:
原因:fork() 函数的目的是创建一个新的进程(子进程),并让父进程和子进程能够独立地运行。通过将 fork() 的返回值区分为父进程返回子进程的 PID 和子进程返回0,可以让父进程与子进程在代码中做不同的事情。例如:
这种设计简化了父子进程之间的分流控制,使得它们能够根据 fork() 返回的值决定各自的行为。
Linux内核中,进程的状态在 task_struct 结构中定义,包括以下几种常见的状态:
R (Running):运行状态,表示进程正在运行或准备运行。 S (Sleeping):睡眠状态,进程等待某些事件的完成(可中断睡眠)。 D (Disk Sleep):磁盘休眠状态,进程通常在等待I/O操作完成(不可中断睡眠)。 T (Stopped):停止状态,进程被暂停。 t (Tracing stop):是一个特殊的状态,通常用于调试场景,表示进程由于被调试工具跟踪而停止。 X (Dead):死亡状态,进程已终止。 Z (Zombie):僵尸进程,子进程已结束,但父进程尚未读取其退出状态。
下面是关于Linux内核的源码

使用 ps aux 或 ps axj 命令可以查看进程的详细状态。命令选项的含义如下:
a:显示所有用户的进程。 x:显示没有控制终端的进程。 u:以用户为中心格式显示进程信息。 j:显示进程的进程组ID、会话ID、父进程ID等。

僵尸进程(Zombie Process)是指已经结束执行的子进程,但其父进程尚未通过 wait() 或类似的系统调用来读取其退出状态。这些进程的状态是 Z (Zombie),它们在进程表中仍然占据一个位置,但不再占用CPU资源。
来⼀个创建维持30秒的僵死进程例⼦:
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t id = fork();
if(id < 0){
perror("fork");
return 1;
}
else if(id > 0)
{
//parent
printf("parent[%d] is sleeping...\n", getpid());
sleep(30);
}
else
{
printf("child[%d] is begin Z...\n", getpid());
sleep(5);
exit(EXIT_SUCCESS);
}
return 0;
}编译并在另⼀个终端下启动监控

开始测试

看到结果

父进程回收子进程状态:父进程在子进程退出后,应该及时调用 wait() 或 waitpid() 系统调用来回收子进程的退出状态,避免子进程成为僵尸进程。 使用 signal 处理:父进程可以通过设置信号处理函数来在子进程终止时自动回收其状态。 孤儿进程的处理:如果父进程退出,子进程会成为孤儿进程,并由 init 进程(PID为1)收养并清理其状态,避免僵尸进程的积累。
当父进程结束时,子进程会变为孤儿进程,且由 init 进程(PID为1)领养并回收。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t id = fork();
if(id < 0){
perror("fork");
return 1;
}
else if(id == 0)
{
//child
printf("I am child, pid : %d\n", getpid());
sleep(10);
}
else
{
//parent
printf("I am parent, pid: %d\n", getpid());
sleep(3);
exit(0);
}
return 0;
}