进程管理(一)

一.进程概念: 
程序的一个执行实例 
正在执行的程序 
能分配处理器并由处理器执行的实体 
这三种说法都是对的 
那么正式进入进程的认识吧 
内核:担当分配和管理系统资源(CPU时间,内存)的实体 
管理的两个步骤:描述,组织 
操作系统对进程进行管理,都是对结构体数据(PCB(进程描述符,是一个结构体,包含了进程的所有描述信息))进行管理 
进程与可执行程序的区别: 
1>进程是动态的,进程状态是可以改变的;程序是静态的,处于存储状态 
2>进程在内存上,程序在硬盘上 
3>进程比程序多了很多的描述信息,其中最重要的是PCB(进程控制块),PCB经常改变

进程控制块:是task_struck结构体,这个结构体具体的实现我会之后写到,其中进程控制块包含了标识符,状态,优先级,程序计数器,内存指针,上下文数据,I/O状态信息,记账信息 等! 
*1>标识符:描述本进程的唯一标识符,用来区别其他进程 
*2>状态:任务状态,退出代码,退出信号等 
*3>优先级:相对于其他进程的优先级 
*4>程序计数器:程序中即将被执行的下一条指令的地址。 
5>内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针 
*6>上下文数据:进程执行时处理器的寄存器中的数据 
7>I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表 
8>记账信息:包括处理器时间总和,使用的时钟数总和,时间限制,记账号等 
所有运行在系统里的进程都以task_struck链表的形式存在内核里


二.操作系统中的进程

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。


三.操作系统:是一款做软件与硬件管理的软件 
操作系统与硬件之间有一个层次叫做驱动 
硬件<-驱动<-操作系统(核心层)<-外壳<-用户(最外层到最底层) 
对操作系统而言,对下要管理各种软件与硬件,对上而言,要提供各种使用方式对于用户 
内核:对下 
外壳:对上

.系统调用:调用的是一个个的函数,是操作系统提供的接口(操作系统给的一个个函数接口,用来进行各种操作) 
库函数是基于系统调用二次开发节省开发成本,增减代码移植性 
操作系统内核的四大要点 
进程管理,内存管理,设备管理,文件管理 
这里我们不做过多叙述,这里只是一个概念描述


五.介绍一些指令和进程的位置

ps aux指令:显示所有进程 


ps aux | grep “目标进程”:显示所要查询的进程信息 


getpid() 获得系统调用的进程id,返回值为pid_t类型,是一个被封装过的类型,为一个无符号整数 

getppid() 获得系统调用的父进程id,同样返回一个无符号整数


Linux下创建 子进程(PCB) 的方法 
fork指令:有两个返回值,创建子进程,成功给子进程返回0,给父进程返回子进程的pid;失败的时候给父进内容程返回-1;

解释为什么要给父进程返回子进程的pid:因为父进程的子进程不止有一个,所以这里给父进程返回子进程的pid,是为了让父进程                                                                    区别这是哪个子进程,但每个子进程只会有一个父进程。

子进程 :fork()创建的子进程与父进程的代码是一样的(用的就是父进程的数据结构模板),但数据是各自一份,子进程的数据是私有的,以写时拷贝创建的。

Linux下c语言中的地址空间是虚拟地址,看下面代码,创建的变量i,用fork创建子进程,子进程与父进程里变量i的值不同但是i的地址是相同的,&i直接打印出来的地址其实是虚拟地址,但是i的输出是从物理地址中取得的 ,所以才会出现同一个虚拟地址中的打印的值不同,因为他们的物理地址不同。 

 #include<stdio.h>
 #include<stdlib.h>
 #include<unistd.h> 
int main()
{
    int i = 0;
    pid_t id = fork();
    if(id==-1)
	{
		 printf("fork error\n");
    }				
    else if(id==0) //child
    {
		i = 10;
		printf("this is child\n");
		printf("i = %d  ",i);
		printf("&i:%p\n",&i);
		printf("child pid is:%d  father pid is:%d\n",getpid(),getppid());
    }
	else
    {
		i = 100;
		printf("this is father\n");
		printf("i = %d  ",i);
		printf("&i:%p\n",&i);
	        printf("father pid is:%d \n",getpid());
    } 
    return 0;
}	

运行结果:


并且我们可以看见同一个变量i在子进程和父进程中的地址是相同的,但是值却不同,这在我们通常的认知中这简直是不可能的,这里我们就引入了一个概念叫做虚拟地址,也就是代码中变量所指向的地址其实是一个虚拟地址,但是每一个虚拟地址通过页表映射转换为物理内存,也就是真正的的存储空间,来让我们看看这是一个怎样的过程 


父进程与子进程共享代码:经过页表同时只想一块物理地址 
父进程与子进程私有数据:经过页表指向不同的物理地址


  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值