进程同步的基本元素

目录

临界资源

临界区

信号量机制

整形信号量

记录型信号量

AND信号量

信号量集

信号量的应用

实现进程互斥

实现前驱关系

管程机制

总结


临界资源

I/O设备属于临界资源。著名的生产者-消费者问题就是关于临界资源的争夺产生的进程同步的问题。

生产者-消费者

描述:一群生产者生产产品,产品生成完以后运到仓库储存,仓库的大小有限,这里的仓库在表示中抽象成了缓冲区。一群消费者需要到仓库中取产品进行消费。

 

 代码:

#include "stdio.h"
#include "unistd.h"
#define MAXSIZE 100
int in = 0;
int out = 0;
int count[1] = {0};
int child_process_id = 0;
char buffer[MAXSIZE];
void producer();
void comsumer();
void main() {

    __pid_t pid = fork();
    //int n = 0;
    //count = &n;
    printf("The process id = %d\n", pid);
    if(pid == -1) {
        perror("fork error!");
    } else if(pid == 0){
        printf("Hello from child process: %d\n", getpid());
        child_process_id = getpid();
        comsumer();

    } else {
        printf("Hello from father process: %d\n", getpid());
        //__pid_t pid1 = fork();

        producer();

    }

}

void producer() {
    while (1)
    {
        while (*count == MAXSIZE){
            printf("producer:%d, %d\n", *count, getpid());

            scanf("%d", count);

        }
        in = (in+1)%MAXSIZE;
        (*count)++;
    }
    
}

void comsumer() {

    while (1)
    {
        //FILE *file = fopen("comsumer.txt", "w");
        //fputs(buffer, file);
        //fclose(file);

        while (*count == 0){
        printf("comsumer:%d, %d\n", *count, getpid());
        scanf("%d", count);
            
        }
        //getchar();

        out = (out+1)%MAXSIZE;
        (*count)--;   
        
        }
        printf("Comsumer exit!\n");
    
}

输出结果:

临界区

count可以理解为临界资源。

临界区:访问邻接资源的代码成为临界区。

访问count代码行成为临界区。

while (*count == MAXSIZE){//进入消费者临界区的条件

(*count)++;//生产者临界区

while (*count == 0){//进入消费者的临界区的条件

(*count)--;  

信号量机制

整形信号量

代码:

wait(S){

while(S <= 0) ;

S--;

}

signal(S) {

S++;

}

定义:

整形信号量S

简称

wait

P

signal

V

 

记录型信号量

代码:

typedef struct{

int value;

struct process_control_block *list;

}semaphore;

wait(semaphore *S) {

S->value--;

if(S->value < 0)block(S->list);

}

signal(semaphore *S) {

S->value++;

if(S->value<=0) wakeup(S->list);

}

S->value

某类资源的数目

S->list

等待使用某类资源的进程队列

block

阻塞进程队列,后续进程无法使用该类资源

wakeup

唤醒进程队列,可以使用该类资源

AND信号量

前面的信号量都是解决单个信号时出现的问题,如果出现两个或者以上的信号量呢?

信号量Dmutex = 1

信号量Emutex = 1

进程A:

进程B

由于并发进程存在随机性;所以存在以下的执行顺序:

A.P(Dmutex)

0

B.P(Emutex)

0

A.P(Emutex)

-1

A阻塞

B.P(Dmutex)

-1

B阻塞

伪码:

Swait(S1,S2,...,Sn)

{

while(true){

if(Si >=1 && ... Sn >=1) {

for(i = 1; i <=n; i++)Si--;

break;

} else {

将所有进程放入等待队列中

}

}

Ssignal(S1,S2,...,Sn)

{

while(true){

for(i = 1; i <=n; i++)Si--;

}

将所有进程放入就绪队列中

}

信号量集

如果一次性对多个进程的信号量做操作,同时每一次不是-1,而是减一个不确定值。信号量集可以解决这个问题。

Swait(S1,t1,d1,...,Sn,tn,dn);

Ssignal(S1,d1,...,Sn,dn);

信号量的应用

实现进程互斥

mutex的取值范围为-1,0,1时,结合以下的代码可以实现进程互斥。

while(1) {

wait(mutex);

临界区;

signal(mutex);

}

实现前驱关系

如果p1,p2进程存在p1->p2的关系,可以通过信号量机制,来实现前驱关系。

假设p1,p2都需要mutex = 0的信号量。

p1:signal(mutex);

p2:wait(mutex);

如果用有向图的理论来解释:

signal相当于p1到p2的边的起点,而wait相当于这条边的终点。

管程机制

管程是前面讲到的集中信号量机制的一个封装,统一的使用管程方法来实现进程的互斥,同步问题。


总结

本文从进程同步的一些基本元素:临界资源,临界区,信号量和管程机制,并且结合代码和伪码。来阐述一些概念。

  • 12
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值