目录
一、什么是进程
二、进程的标识符pid
三、getpid 得到进程的PID
四、kill 终止进程
五、父进程与子进程
六、目录中的进程
一、什么是进程
在windows中,我们查看进程很简单,打开任务管理器,就可以看到在运行的进程。这里我们还可以看到CPU要对进程进行处理,并且进程已经加载到了内存里。
那么什么是进程呢?
课本概念:程序的一个执行实例,正在执行的程序等。
内核观点:担当分配系统资源(CPU时间,内存)的实体。
在操作系统内部存在很多进程,操作系统要对进程进行管理,就得先描述,在组织。具体为什么参考这篇文章冯诺依曼与操作系统。使用结构体将进程描述起来,再使用数据结构将他们组织连接起来,这样我们对进程的管理就转化为对数据结构的增删查改了。
该结构体我们称之为进程的PCB(process control block),Linux操作系统下的PCB是: task_struct,他的结构体简略描述如下
struct task_struct
{
//进程id
//指向可执行程序的指针
//等等属性
struct task_struct*next
//其他指针
}
比如在存放在磁盘上的各种可执行程序,运行时就会被加载到内存中,这时操作系统(第一个被加载到内存的软件)会帮助我们创建进程的PCB,并将PCB链接起来形成进程链表,后续操作系统对进程的管理就转变成了对进程链表的增删查改。
进程不仅仅只有进程链表这一个结构,同一个进程还有可能在其他的结构中,如进程的运行队列,会根据进程的优先级进行排队,等待CPU处理。
现在我们可以给进程下一个定义:进程 = 可执行程序 + 内核数据结构。这里的内核数据结构包括了PCB,这可以方便操作系统对进程进行管理。
二、进程的标识符pid
Linux中,输入指令ps ajx 可以查看当前所有进程
ps ajx
其中进程的的标识符被称作pid
同时我们也可以编写一个程序,执行起来,看看这个进程的情况。
随便写个打印的死循环,同时睡眠一下方便观看。
Makefile也写上。
make 编译并执行
使用 ps ajx | head -1 取出第一行,同时通过 ps ajx | grep mycode 过滤出 mycode文件,这样就方便查看mycode进程的信息了,这里我们看到mycode进程的PID为1251。
我们ctrl + c 将进程终止后,再去查询,就发现可执行程序 mycode被终止掉了。
再运行以下,发现又可以查到,并且PID发生了变化。
现在我们可以得出一个结论:我们运行的所有指令,软件,自己写的程序,最终都是进程
三、getpid 得到进程的PID
在冯诺依曼与操作系统中,我们讲到通过库函数可以去调用系统接口,这里我们学习第一个接口getpid。他可以获取该进程的id,返回参数为pid_t(本质是无符号整数)。
如下,包一下getpid的头文件sys/types.h,就可以开始使用getpid了。
编辑好wq保存并退出,make后再执行一下。
四、kill 终止进程
输入指令 kill -9 + 进程PID 可以终止进程
-9这里为9号信号,这里记住就行。
五、父进程与子进程
其实,我们之前所写的可执行程序还有父进程。
这里我们观察到当前进程PID左边还有个PPID,这个PPID代表当前进程的父进程。
我们还发现当我们终止进程后重新启动该进程,进程的PID会发生变化,而PPID没有变。 如下图PPID都是5350。
Linux启动进程一般都是通过父进程创建的,那么这个父进程是谁呢? 这里我们看到该进程就是bash。当我们在命令行当中启动进程的时候,这些进程的父进程都是bash(命令行解释器)
我们有gitpid这个接口函数可以获取进程的pid,同时也有gitppid这个接口函数来获取进程ppid。我们将mycode.c做如下修改。
这里就可以打印出PPID了。
六、目录中的进程
Linux还有种方式可以查看进程,就是通过目录查看。输入命令 ls /proc/ 打开proc目录,这里面存放着所有的进程,目录的名称就是以这个进程的id命名的。
如图,我们运行mycode程序,8040进程存在 ,终止进程,8040就不存在了。
在目录中,该进程的内容很多,我们大可不必全都了解,了解重要的部分就行,如了解cwd与exe这两个文件就行了。
exe代表着该进程能找到自己的可执行程序,如果可执行程序被删除也能发现。
cwd 代表当前工作目录,比如在我们使用fopen函数进行文件写入的时候,如果不使用绝对路径,就会写入到cwd中。默认情况下,进程启动所处的路径就是当前路径。如下修改代码
这样就写入到了当前工作目录下
如果我们使用 chdir("路径") 修改当前工作目录。 那么写入的地方就会变成你修改的路径。
写入到了 /home/kky/109
同时cwd也被修改成了我们设置的目录