总结----进程管理

进程管理主要有三个部分:进程创建和退出、进程调度、进程间通信。

首先,什么是进程?
进程就是运行着的一个程序的实例。一个运行中的程序包含运行状态、属性、地址空间等信息,操作系统把这些东西整合起来看作进程,统一管理。

进程创建
对于每个进程,内核都会为这个进程生成 一个进程描述符 task_struct、 分配一个内核栈、 以及虚拟地址 映射 到物理地址的页表。
1.进程描述符和内核栈存在于内核空间,准确的说它们是一个联合结构体。
task_struct记录了进程的基本信息,包括标识号、信号、状态、调度信息、进程链信息(父子进程)、文件信息、局部描述符表、任务状态段等。  
2.进程的内核栈从用户态切换到内核态时都是空的。所以栈底记录了用户栈地址。   
3.每个进程拥有统一的虚拟地址空间,包括堆、栈、代码段、数据段等。
页表存放在系统空间的页表区,进程描述符中有指针指向页表。

(内核栈定义, 在/include/linux/sched.h中定义了一个联合结构:
union task_union {
        struct task_struct task;
        unsigned long stack[INIT_TASK_SIZE/sizeof(long)];
    };
INIT_TASK_SIZE 是8K

也就是说进程描述符和内核栈公用一个联合结构体,内核栈的栈顶位置为: 起始地址+8192

linux创建进程的系统调用有:fork(),vfork()
fork():
实际开销:创建唯一task_struct,复制父进程的页表。
f ork 实行写时拷贝,先让子进程共用父进程的地址空间,只有当写入时才复制。

vfork():
不复制父进程的页表,共用页表。所以子进程不能向父进程写入。

进程退出:
有5种方式
正常退出:
1,从main函数退出
2,调用exit
3,调用_exit
异常退出:
1,调用abort
2,有信号终止

exit与_exit的区别:
_exit直接使进程停止运行,清除使用的内存空间,销毁其在内核中的数据结构;
_exit是exit的最后一个步骤,在此之前,还会调用atexit() ,刷新I/O缓冲区,关闭所有文件。

僵尸进程:某个进程退出了,但是它的父进程没有调用wait,此时这个进程的进程描述符还在内核空间没有释放。
孤儿进程:某个进程还在运行,但是它的父进程退出了,该进程的父进程变成了init进程。

进程调度
每个cpu分配一个运行队列runqueue,通过动态优先级和时间片轮转的方式进行调度。
进程的动态优先级由静态优先级nice值和进程的动态交互性计算得来,nice值是内核。
每个cpu一个 runqueue,每个进程唯一的归属于一个 runqueue。
runqueue主要包含:一个保护运行队列的自旋锁、任务数目、活动优先级数组的指针、过期优先级数组的指针等等。
每个运行队列都有两个优先级数组,一个活跃的和一个过期的。
优先级数组中有三个成员:任务数目、优先级位图、优先级队列。
优先级位图为每个优先级准备一位,初始状态全置为0,当拥有某个优先级的进程就在位图中相应位置置为1,这样,查找系统中最高的优先级就变成了查找位图中被设置的第一位。
优先级队列:每个优先级对应一个链表,每个链表与一个给定的优先级相对应。这样就能通过位图找到最高优先级,然后在优先级队列中找到调度的进程。
为什么要两个优先级数组?
首先,系统只对活跃优先级数组里的进程进行调度。
活跃优先级数组中的进程在时间片耗尽之后,重新计算时间片,然后放到过期优先级数组中,当活跃优先级数组中的进程数目为0时,交换两个优先级数组的指针。
(调度程序提供一种机制以支持交互进程,如果一个进程交互性强,那么,当它的时间片用完之后,会重新计算时间片再次放入活动数组中。)

进程间通信
unix方式:管道、信号
system c方式:消息队列、信号量、共享内存
socket.

管道,一种特殊的文件(特殊是因为文件内容在内存中),用来实现进程间小规模的数据通信,由一个进程向管道内写数据,另一个进程从管道读数据。
管道分为有名管道和无名管道。无名管道是单工的临时管道,只能用于父子家族进程的通信。有名管道可以用于不同进程,管道文件
是双工的,但是只能以只读方式和只写方式分别打开。

信号是进程在运行过程中自身产生或由外部发过来的消息,它 是硬件中断的软件模拟,也就是软中断。信号不能传输特定数据,但是可以通过发送不同类型的信号来通知其他进程,进程可以根据不同的信号设置对应的处理函数。

消息队列,是存储在内核空间的一个消息的链表,不同进程可以通过指定的消息队列id号对同一个消息队列进行读写操作。

信号量,是内核用来表示系统可用资源数量的一种数据结构。通常用来实现进程同步。

共享内存,进程间可以通过共享内存来实现大量数据通信,主要是通过将不同进程各自的一块虚拟地址空间映射到同一块物理
地址来实现。 在对共享内存进行数据存取时,一般都配合二元信号量使用。

socket,一般用于网络中,两个程序通过一个双向的通信连接实现的数据交换。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值