进程,信号量同步

 进程:

基本状态:

1.新建:创建进程对象即进入新建状态

               创建步骤:申请空白PCB——>分配资源——>初始化——>插入就绪队列

               引起创建事件:用户登录,作业调度,提供服务,应用请求

 2.就绪:线程已获得除CPU之外的所有需要的资源

 3.执行:已获得CPU,线程正在执行。

 4.阻塞:正在执行的线程由于发生某事件(I/O请求,申请缓冲区失败等)致暂时无法执行。

               引起进程阻塞事件:请求共享资源失败,等待某种操作完成,新数据尚未到达,等待新任务。

               阻塞过程:发生上述事件后,使用block原语将自己阻塞

               唤醒过程:当被阻塞进程所期待的事件发生时,就把被阻塞进程从从等待该事件的阻塞队列中移除,将其PCB中现行状态由阻塞改为就绪,再将该PCB插入就绪队列。

              block(阻塞原语)与wakeup(唤醒原语)必须成对出现

 5.终止:线程执行完或因异常退出。

             引起进程异常终止的事件:越界错,保护错,非法指令,特权指令,运行超时,等待超时,算术运算错,I/O故障

             终止过程:根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,读出该进程状态,若处于执行状态,则立即终止程序执行,并置调度标志为真,若进程还有子孙进程,则子孙进程也应终止,将资源归还给父进程或系统,将该进程从PCB列表移除。

进程,信号量同步

进程状态转换:

1.挂起操作:系统中出现引起挂起进程挂起的事件时,挂起原语suspend将指定进程挂起(包括阻塞进程),包括两种情况,对处于活动就绪的进程改为静止就绪,活动阻塞改为静止阻塞。

2.**操作:当系统发生**进程事件时,系统利用**原语active,将指定进程**。active先将进程从外存调入内存,检查该进程现行状态,若是静止就绪,则改为活动就绪,若是静止阻塞,则改为活动阻塞。

PCB作用:

1.独立运行基本单位标志

2.能实现间断性运行方式

3.提供进程管理所需要的信息

4.提供进程调度所需要的信息

5.实现进程同步与通信

PCB中包含的信息

1.进程标识符

2.内部标识符

3.进程调度信息

4.进程控制信息

进程同步:

意义:一方面,可以是系统中多道程序并发执行,有效提高资源利用率,还可以显著提高系统吞吐量,但另一方面,会使系统变得更加复杂。

基本概念:对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能按照一定规则共享系统资源,并能很好的相互合作,从而使程序具有可再现性。

临界资源:只能采用互斥的形式访问的资源

临界区 :每个进程访问临界资源的代码,若能保证进程互斥的访问临界区,则能实现互斥访问临界资源。

信号量机制 :   

整型信号量:由Dijkstra把整型信号量定义为一个用于表示资源数目的整型量S,除初始化之外,仅能通过两个标准的原子操作(wait,signal)来访问。即P,V操作

wait(S){            //P操作
    while(S<=0);
    S--;
}                    //只要S<=0,就不断测试
signal(S){            //V操作
    S++;
}

wait(P),signal(V)是两个原子操作,在执行时不可中断;

记录型信号量:采用让权等待策略,需要一个代表资源数目的整型变量value,还有一个进程链表指针list,数据结构如下:

typedef struct{
    int value;
    struct process_control_block *list;
}semaphore;        //结构体

wait(semaphore *S){
    S->value--;
    if(S->value<=0)
        wakeup(S->list);
}
signal(semaphore *S){
    S->value++;
    if(S->value<=0)
        wakeup(S->list);
}

信号量实现进程互斥

设mutex为互斥信号量,初值1;

当mutex=1时,表示两个进程都没有进入互斥临界区

当mutex=0时,表示有一个进程进入临界区运行,而另一个需要等待,挂在阻塞队列

当mutex=-1时,表示一个进程正在临界区运行,另一个因等待而阻塞在信号量队列,需要被在临界区的进程退出时唤醒

代码如下:

semaphore mutex=1;
    Pa(){
    while(1){
        wait(mutex);
        临界区代码;
        signal(mutex);
        剩余区代码;
    }
    }

wait,signal必须成对出现,缺少wait,将导致系统混乱,不能保证对临界资源互斥的访问,缺少signal,将会导致临界资源永远不被释放,从而使因等待该资源而阻塞的进程不能被唤醒。

经典同步问题

生产消费者:生产消费者之间有n个缓冲区,mutex信号量保证互斥访问,empty,null表示空缓冲区和满缓冲区数量。只要缓冲池未满,生产者即可把消息放入缓冲区,只要缓冲池未空,消费者即可从缓冲区取走一个消息。

代码描述:

int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n;full=0;
void proceducer(){
    //生产者
    do{
        producer an item nextp;//生产一个
        wait(empty);//空缓冲区减一
        wait(mutex);//进入互斥
        buffer[in]=nextp;
        in :=(in+1)%n;//移向下一个缓冲区
        signal(mutex);//退出互斥
        signal(full);//满缓冲区减一
    }
    while(TRUE);
}
void consumer(){
    //消费者
    do{
        wait(full);
        wait(mutex);
        nextc=buffer[out];
        out=(out+1)%n;
        signal(mutex);
        signal(empty);
        consumer the item in nextc;//取出消息
    }
}
void main(){
    cobegin
        proceducer();
        consumer();
    coend
}

读者写者问题

semaphore rmutex=1,wmutex=1;
int readcount=0;
void reader(){
    do{
        wait(rmutex);
        //判断是否的第一个进入,若是,对写加锁
        if(readcount==0) wait(wmutex);
        readcount++;
        signal(rmutex);

        //此处执行读操作//
        
        wait(rmutex);
        readcount--;
        if(readcount==0) signal(wmutex);
        signal(rmutex);
    }
    while(TRUE);
}

void writer(){
    //写
    do{
        wait(wmutex);
        //此处执行写操作//
        signal(wmutex);
    }
    while(TRUE);
}

int main(){
    cobegin
        reader();
        writer();
    coend
}

进程通信类型:

共享存储器系统:进程共享某些数据结构或者某存储区,生产者消费者

管道(pipe)通信系统:进程之间共享一个文件(pipe文件),读者写者

消息传递系统:发送进程利用系统提供的发送原语,直接把消息发送给目的进程

客户机服务器系统:套接字(一个套接字就是一个通信标识类型数据结构,包含通信目的地址,通信用端口号,通信网络协议,进程所在网络地址,以及针对客户或服务器提供的不同系统调用【或者API函数等】) ;远程过程调用或者远程方法调用(远程过程调用一个通信协议,用于网络连接的系统)