目录
基本概念
PCB
task_struct
task_struct内容分类
组织进程
查看进程
查看正在运行的进程信息
获取pid和ppid
创建子进程
基本概念
一个已经加载到内存中的程序,叫做进程,正在运行的程序,叫做进程,进程是担当分配系统资源(CPU时间、内存)的实体。
一个操作系统,不仅仅只能运行一个进程,可以同时运行多个进程,因此操作系统必须将进程管理起来,如何管理进程呢?先描述,再组织
任何一个进程,在加载到内存的时候,形成真正的进程时,要先创建描述进程(属性)的结构体对象--PCB(进程控制块)。
需要注意的是,PCB不等于进程,PCB只是操作系统用来描述进程的所有属性值。
进程 = 内核PCB数据结构对象+代码和数据
PCB
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。Linux操作系统下的PCB是:task_struct。
task_struct
- task_struct是PCB的一种,Linux中描述进程的结构体叫做task_struct;
- task_struct作为Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息
task_struct内容分类
- 标识符:描述本进程的唯一标识符,用来区别其他进程
- 状态:任务状态,退出代码,退出信号等
- 优先级:相对于其他进程的优先级
- 程序计数器:程序中即将被执行的下一条指令的地址
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据:进程执行时处理器的寄存器中的数据
- I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表
- 记账信息:可能包括处理器的时间总和,使用的时钟数总和,记帐号等
- 其他信息
组织进程
所有运行在系统里的进程都以task_struct链表的形式存在内核里
查看进程
进程的信息可以通过 /proc系统文件夹查看
查看正在运行的进程信息
查看进程信息除了上述通过/proc方法,还可以通过ps命令查看正在运行的进程信息
ps的本质就是遍历这个task_struct链表,格式化输出进程信息 。
获取pid和ppid
当进程想获取自己的PID,必须通过系统调用接口 getpid(),返回值是pid_t(也就是一个无符号整数)。
#include <sys/types.h>
#include <unistd.h>
//获取自己的pid
pid_t getpid(void);
//获取父进程的pid
pid_t getppid(void);
创建子进程
#include <unistd.h>
pid_t fork(void);
- 如果创建成功了,给父进程返回子进程的pid,给子进程返回0;
- 如果创建失败了,给父进程返回-1。
可以通过如下代码进行理解:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
pid_t id=fork();
if(id==0)
{
//子进程
}
else if(id>0)
{
//父进程
}
else{
//error
}
return 0;
}
fork之后通常需要使用if进行分流
1、为什么fork要给子进程返回0,给父进程返回子进程pid?
返回不同的返回值,是为了区分,让不同的执行流,执行不同的代码块。一般而言,fork之后的代码父子进程共享。
给子进程返回0,是为了区分子进程跟父进程。
给父进程返回子进程是为了区分不同的子进程,方便后续的对子进程控制。
2、一个函数是如何做到返回两次的?如何理解的?
fork也是一个函数,先创建子进程,在该函数内部return前,子进程已经被创建好了,因此子进程返回一次,父进程也返回一次。
3、id接收fork的返回值,怎么会有不同的内容?
父子进程代码共享,数据各自开辟空间,私有一份(写时拷贝)