【Linux】—— 进程

冯诺依曼体系结构

【Linux】—— 进程_第1张图片

  • 输入单元:包括键盘, 鼠标,扫描仪, 写板等
  • 中央处理器(CPU):含有运算器和控制器等
  • 输出单元:显示器,打印机等

关于冯诺依曼,必须强调几点:

  • 这里的存储器指的是内存
  • 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
  • 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
  • 一句话,所有设备都只能直接和内存打交道

进程

在进入进程之前,我们先了解一下,操作系统是如何进行进程的管理的,在 OS的概念,定义 我们有提到过操作系统是一个进行软硬件资源管理的软件,是一个具有决策权的管理者

这里我们来举个栗子:
  • 以学校来举栗子吧,在学校中我们的校长可以看做是一个操作系统,辅导员可以看做是驱动设备,我们可以看做是被管理的软硬件,校长不会自己跟同学打交道,都是通过辅导员来管理所有的同学的,那校长又是怎么具体进行管理的呢
  • 我们都知道我们进入学校都会有一个学号,我们的信息都会被录入学校的系统中,只要系统中有某个同学的信息,说明这个同学是这个学校的学生,因此要管理一个学生,就先要把这个学生描述起来,这里就是通过一个结构体struct来描述一个学生的基本信息,比如:学号,姓名,年龄,班级,籍贯等等,当同学进入学校,就把他的信息录入系统,离开学校就删除该同学信息,即可管理好同学。

同理操作系统也是这么管理进程的,要管理进程就需要先把进程描述起来,再进行管理
先描述,再组织

基本概念

  • 课本概念:程序的一个执行实例,正在执行的程序等
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体。

进程与程序的区别

  • 一个在内存中(进程),一个在硬盘上(程序)
  • 进程比程序多了一个描述进程的结构体即进程描述块PCB

我们刚刚提到操作系统要管理一个进程之前,必须把一个进程先描述起来,因此这里来介绍一下,操作系统是怎么描述一个进程的。

描述进程-PCB

  • 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
  • 课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct

task_struct-PCB的一种

  • 在Linux中描述进程的结构体叫做task_struct,在linux下使用较为频繁的一种。
  • task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

task_ struct内容分类

  • 标示符: 描述本进程的唯一标示符,用来区别其他进程。
  • 状态: 任务状态,退出代码,退出信号等。
  • 优先级: 相对于其他进程的优先级。
  • 程序计数器: 程序中即将被执行的下一条指令的地址。(PC/IP,CPU内部的一个寄存器记录正在执行指令的下一条指令的地址)
  • 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
  • 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。(进程切换中十分重要,在一个进程在S状态时,保存这个进程的上下文数据以便之后该进程能够继续执行,而不是重新开始)
  • I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
  • 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。 其他信息

查看进程

进程的信息可以通过 /proc 系统文件夹查看

  • 如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。
  • 大多数进程信息同样可以使用top和ps这些用户级工具来获取
  • 运行如下代码,此时一个程序运行之后就会成为一个进程,被操作系统管理起来。
  • 通过输入指令ps aux | grep 'proc'或是ps aux | head -1 && ps aux | grep 'proc'可查看进程的信息.
  • 终止进程(一般用于终止后台进程):kill -9 31003(进程的PID)
#include 
#include 
#include 
int main()
{
	while (1){
		sleep(1);
	}
	return 0;
}

通过系统调用获取进程标示符

  • 进程id(PID)
  • 父进程id(PPID)//父进程的PPID不会改变

#include 
#include 
#include 
int main()
{
	printf("pid: %d\n", getpid());
	printf("ppid: %d\n", getppid());
	return 0;
}

通过系统调用创建进程-fork初识

  • 运行 man fork 认识fork(man为查看命令手册)
  • fork有两个返回值
  • 父子进程代码共享,数据各自开辟空间,私有一份(采用写时拷贝)
#include 
#include 
#include 
int main()
{
	int ret = fork();
	printf("hello proc : %d!, ret: %d\n", getpid(), ret);
	sleep(1);
	return 0;
}
  • fork 之后通常要用 if 进行分流,通过返回值判断父子进程,让父子进程执行不同的任务。
#include 
#include 
#include 
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;
}

你可能感兴趣的:(Linux)