linux操作系统-3进程管理(1)

来源:互联网 发布:手机亮度调节软件 编辑:程序博客网 时间:2024/05/21 21:35

进程是多任务并发的基本概念,在并行处理中,进程调度室影响系统性能的最重要因素之一。

进程与程序的区别

动态性和静态性

从结构上看,每个进程的实体都是由程序段和相应的数据段两部分构成的;

一个进程可以涉及到一个或几个程序的执行;反之,一个程序可以对应多个进程,即同一程序段可以在不同数据集合上运行,构成不同的进程;

并发性

进程具有创建其他进程的功能

操作系统中,每一个程序都是在一个进程现场中运行的。

每一个进程只能有一个父进程,但一个父进程可以有多个子进程。当进程创建时,操作系统会给子进程创建新的地址空间,并把父进程的地址空间的映射复制到子进程的地址空间去。父子进程共享数据和代码段,但是堆栈和堆是分离的。

进程控制块

进程描述程序的一次执行,它存在于内存中。系统资源分配、调度是以进程为单位的。进程的资源、运行状态等由内核管理,内核中只需要一个数据结构来描述。通常这种数据结构task_struct称为进程控制块(PCB)。一个进程可以说是由进程控制块、代码、数据组成(数据和代码由程序提供)

不同操作系统进程控制块内容不同,主要有以下几类:

1、进程标识符:包括进程的id、进程的名字、进程的家族关系和拥有此进程的用户标识等。

2、进程上下文环境:此进程运行时CPU各寄存器的内容,包括指令计数器、程序状态字和堆栈指针等。

3、进程调度信息:包括进程的状态、进程的调度策略、进程的优先级、进程的运行睡眠时间、进程的阻塞原因和进程的队列指针等。当进程处于不同的运行状态时,就会被放到不同的队列中。

4、进程控制信息:进程的代码、数据、堆栈的起始地址;进程的资源控制,比如进程的内存描述符、文件描述符、信号描述符和IPC描述符等。进程使用的所有资源都会在PCB中描述。

5、进程控制块的组织方式:当进程处于不同的状态时,内核会以不同的方式组织它们。1)链接方式,把进程按照不同的状态分别放到不同的队列;2)索引方式,想hash表等方式建立相应的索引表,处于不同状态的进程被放到相应的索引表中。

一个实用的内核通常会根据需要混合使用这些方式,不管使用哪种方式,都是把PCB放到不同的队列或表中,PCB就代表了子进程。

进程是程序的一次执行,是操作系统分配系统资源的基本单位。传统的操作系统把进程状态分为三种

运行状态:已获得必要资源,也获得了处理机,用户程序正在处理机上运行;

阻塞状态:进程等待某种事件完成而暂时不能运行的状态,处于该状态的进程不能参加竞争处理机。

就绪状态:该进程运行所需的一切条件都得到满足,但因处理机资源个数少于进程个数,所以该进程不能运行,而必须等待分配处理机资源,一旦获得处理机就立即投入运行。

这些状态互斥并可以相互转化。LINUX内核用task_struct->state表示进程的状态。

就绪状态变成运行状态

运行状态变成就绪状态

运行状态变成阻塞状态

阻塞状态变成就绪状态:处于阻塞状态的进程称为进程睡眠。从阻塞状态转换到运行状态称为唤醒

为了加快进程描述符的查找,内核在进程描述符设置了很多指针,parent(父进程)、sibling(兄弟进程)、children(第一个子进程)。所有的子进程用sibling的双向链接链接在一起。

线程的原理与实现

引入线程主要是提高系统的执行效率。线程和进程的主要区别和联系如下:

进程是资源分配的基本单位。一个进程中所有的线程共享该进程的所有资源。

线程是进程中的最小调度单位。

一个线程属于一个进程。一个进程至少有一个线程。

线程的实现是指操作系统在一个进程中创建多个线程的方法。一般有以下两种:

用户级线程:应用程序建立,操作系统并不知道线程的存在,只对该进程进行管理。缺点:多个线程不能同时运行,在这种实现中内核的调度单位是进程。

内核级线程:所有线程的创建、调度、管理都由内核完成,WINDOWS NT属于此类。

在一个实现内核级线程的操作系统中,应用程序还是可以使用用户级线程。因此有些操作系统也可以使用混合的方式。

LINUX2.6内核使用内核级线程的实现方式。实现了轻量级进程的概念,实质就是线程。在LINUX中,进程与线程不需要区分,内核使用统一的方式对它们进行创建、管理和调度。同时LINUX的轻量级进程又保留了线程的特性,如没有独立的地址空间、线程之间共享资源等。

所有的线程都被看做是一个进程线程和轻量级进程是等价的。轻量级进程没有独立的地址空间,一个进程中所有的轻量级进程会共享资源,如地址空间、信号处理等。进程中的轻量级进程是平等的,没有主从之分。轻量级进程也有一个task_struct。

LINUX进程创建和结束

在LINUX中,进程的创建是由系统调用fork和vfork完成的,它们生成一个子进程并且子进程是父进程的复制品。

fork与vfork区别(转载)

1.vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

2.fork要拷贝父进程的进程环境;而vfork则不需要完全拷贝父进程的进程环境,在子进程没有调用exec和exit之前,子进程与父进程共享进程环境,相当于线程的概念,此时父进程阻塞等待。

 为什么会有vfork呢?

因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,然后将会有两种行为:

1.执行从父进程那里拷贝过来的代码段

2.调用一个exec执行一个新的代码段

 当进程调用exec函数时,一个新程序替换了当前进程的正文,数据,堆和栈段。这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork。vfork并不复制父进程的进程环境,子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。

 因此,如果创建子进程是为了调用exec执行一个新的程序的时候,就应该使用vfork。

每个进程都有一个kernel中的堆栈,新进程的堆栈将被设置成新分配的堆栈。

进程结束:应用程序使用系统调用exit()来结束一个进程,此系统调用接受一个退出原因代码,父进程可以使用wait()系统调用来获取此代码,从而知道子进程退出的原因。对应到kernel,此系统调用sys_exit_group()。

线程的结束:和进程结束的流程类似。线程结束对应的kernel函数是sys_exit(),直接调用do_exit(),唯一差别是线程结束时不会将其他线程结束。

0 0