介绍:
进程是程序执行的实体,可将其理解为程序。比如:当我们使用文本编辑器Notepad应用程序来编写一篇文章时,此时,Notepad应用程序就被加载到了内存中,并且它占用的资源(如内存、CPU等)也得到了分配。在这个过程中,Notepad应用程序就是一个进程,此进程在使用过程将不断被执行,当关闭Notepad应用程序,此进程占用的资源将释放,进程结束。而操作系统则是负责调度和管理这个进程的实体,它为进程分配资源,并在进程结束后回收资源。也就是说,操作系统负责管理进程。
进程控制块的简称为PCB,是操作系统中用于管理进程的数据结构。它包含了进程的所有状态信息,可以理解为进程属性的集合,用来描述一个进程的所有属性,是进程存在的唯一标志。
Linux下的PCB(进程控制块)是 task_struct 结构体,此结构体是Linux内核的一种数据结构。
使用ps axj指令可查看进程详细
信息。其中,PID对应的就是进程的标识符,
PPID对应的是父进程的标识符。标识符是用来描述本进程的唯一标示符,用来区别其他进程。
在写程序时,要想观察此进程的PID可在代码中使用 getpid() 函数,此函数可获得进程的PID,返回类型为pid_t(就是int),即谁调用getpid,就获取谁的PID。对应的还有 getppid() 函数,获取该进程的父进程标识符,返回类型为pid_t(就是int)。
这里要说明一下,每一次启动程序时,对应的PID都会发生变化,PPID一般不会发生变化,除非您通过某种方式改变了父进程。
在Linux中,当您启动一个程序时,该程序的PPID通常是被启动该程序的shell进程的PID,即该进程的PPID对应的就是bash或其他shell进程。可以说每启动的一个进程都是bash或shell的子进程。因此说每一次启动进程时,PID都会变化,PPID一般不会变化,除非我们将父进程也改变。
[zhu@zhujunhao day21]$ ll
total 16
-rw-rw-r-- 1 zhu zhu 305 Dec 21 17:07 code.cpp
-rwxrwxr-x 1 zhu zhu 9176 Dec 21 17:07 code.exe
[zhu@zhujunhao day21]$ cat code.cpp //程序的源代码
#include
#include
#include
using namespace std;
int main()
{
pid_t pid = getpid();
pid_t ppid = getppid();
sleep(3);
cout << "该进程对应的PID: " << pid << endl;
sleep(3);
cout << "该进程对应的PPID: " << ppid << endl;
return 0;
}
[zhu@zhujunhao day21]$ ./code.exe
该进程对应的PID: 2248
该进程对应的PPID: 1381
/*下面我们删除程序的进程,再次编译运行后可发现,该进程的PID发生了变化,PPID没有改变。该程序的PPID就是bash或shell进程*/
[zhu@zhujunhao day21]$ rm -f code.exe
[zhu@zhujunhao day21]$ ll
total 4
-rw-rw-r-- 1 zhu zhu 305 Dec 21 17:07 code.cpp
[zhu@zhujunhao day21]$ g++ -o code.exe code.cpp
[zhu@zhujunhao day21]$ ./code.exe
该进程对应的PID: 2257
该进程对应的PPID: 1381
下面,我们了解一下 /proc目录。/proc目录提供了一种访问系统内核内部数据结构、改变内核设置的机制。用户和应用程序可以通过访问/proc目录中的文件和子目录,来获取系统的信息,并可以改变内核的某些参数。
其中,/proc/[pid]目录提供了访问和操作进程信息的接口,此接口提供指定进程的各种详细信息,可方便地了解和控制进程的状态和行为。
这里要说明一下,当使用指令 ll /proc/[pid] 进行详细查看时,对应的cwd是当前进程启动的工作目录,即进程启动时所在的工作目录。exe对应的是可执行程序的工作目录,即进程运行的程序。当修改当前进程或可执行文件的工作目录时,对应的cwd或exe会发生变化。
[zhu@zhujunhao day21]$ ll /proc/1381
........
lrwxrwxrwx 1 zhu zhu 0 Dec 21 16:54 cwd -> /home/zhu/day21 //进程启动的工作目录
........lrwxrwxrwx 1 zhu zhu 0 Dec 21 16:54 exe -> /usr/bin/bash //可执行程序的工作目录
fork函数(没有参数):创建子进程,在fork之后,代码会形成分支形成两个,即代码共享,其中一个是该函数创建的一个子进程。其中,该函数返回值为pid_t,给创建的子进程返回0,父进程返回子进程的PID。
[zhujunhao@bogon code]$ cat test.cpp //源代码
#include
#include
#include
using namespace std;
int main()
{
cout << "PID: " << getpid() << endl;
int ret = fork();
cout << "ret = fork(): " << ret << endl;
sleep(1);
return 0;
}
[zhujunhao@bogon code]$ ./test.exe //执行源代码的可执行程序
PID: 9655
ret = fork(): 9656
ret = fork(): 0
此函数通常跟 if 条件连用,分别使父子进程执行不同的功能。
[zhujunhao@bogon code]$ cat test.cpp //源代码
#include
#include
#include
using namespace std;
int main()
{
cout << "PID: " << getpid() << endl;
int ret = fork();
if (ret == 0)
{
cout << "I am Child: PID " << getpid() << " PPID: " << getppid() << endl;
}
else
{
cout << "I am father: PID " << getpid() << " PPID: " << getppid() << endl;
}
sleep(1);
return 0;
}
[zhujunhao@bogon code]$ ./test.exe //可执行程序
PID: 10418
I am father: PID 10418 PPID: 3038
I am Child: PID 10419 PPID: 10418
在执行进程的过程中,若不想执行该进程,通常使用 kill -9 [pid]
命令强制终止指定进程的执行。关闭该进程后,不会影响该进程的子进程或父进程,即进程(任意进程,包括父子进程)之间是有独立性的,互相是不能影响,可放心使用。