临界资源:同一时刻只允许一个进程访问的资源
临界区:访问临界资源的代码段
当我们编写的程序使用了线程时,不管是运行在多用户系统上、多进程系统上,还是运行在多用户多进程系统上。我们通常会发现,程序中存在着一部分临界代码,我们需要确保只有一个进程(或只有一个执行进程)可以进去这个临界代码并拥有对资源独占式的访问权。
信号量:是一个特殊的变量,只允许对它等待(wait)和发送信号(signal)这两种操作。因为在Linux变成中,“等待”和“发送信号”都已具有特殊的含义,所以我们将用原先定义的符号来表示这两种操作。
p(信号量变量):用于等待。如果信号量变量sv大于0,就给它减去1,如果等于0,就挂起该进程的执行。
v(信号量变量):同于发送信号。如有其他进程因等待sv而被挂起,就让他恢复运行,如果没有进程因等待sv而被挂起,就给它加1。
信号量函数的定义如下:
#include<sys/sem.h>
int semctl(int sem_id,int sem_num,int command,...);
int semget(key_t key,int num_sems,int sem_flags);
int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_op);
接下来完成定义一个信号量进行p,v操作使得两个进程A,B同时运行轮番访问临界资源,进而输出为ABABAB…
sem.h:
//sem.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<sys/sem.h>
union semum
{
int val;
};
void sem_init();
void sem_p();
void sem_v();
void sem_destroy();
sem.c:
//sem.c
#include"main.h"
static int semid=-1;
void sem_init()
{
semid=semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);
if(semid==-1)
{
semid=semget((key_t)1234,1,0600);
if(semid==-1)
{
perror("semget error");
return ;
}
else
{
union semum a;
a.val=1;
if(semctl(semid,0,SETVAL,a)==-1);
{
perror("semctl error");
}
}
}
}
void sem_p()
{
struct sembuf buf;
buf.sem_num=0;
buf.sem_op=-1;//p
buf.sem_flg=SEM_UNDO;
if(semop(semid,&buf,1)==-1)
{
perror("semop p error");
}
}
void sem_v()
{
struct sembuf buf;
buf.sem_num = 0;
buf.sem_op = 1;//v
buf.sem_flg = SEM_UNDO;
if ( semop(semid,&buf,1) == -1 )
{
perror("semop p error");
}
}
void sem_destroy()
{
if ( semctl(semid,0,IPC_RMID) == -1 )
{
perror("semctl del error");
}
}
a.c:
//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "sem.h"
int main()
{
sem_init();
int i = 0;
for(; i < 5; i++ )
{
sem_p();
printf("A");
fflush(stdout);
int n = rand() % 3;
sleep(n);
printf("A");
fflush(stdout);
sem_v();
n = rand() % 3;
sleep(n);
}
sleep(10);
sem_destroy();
}
b.c:
//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main()
{
sem_init();
int i = 0;
for(; i < 5; i++ )
{
sem_p();
printf("B");
fflush(stdout);
int n = rand() % 3;
sleep(n);
printf("B");
fflush(stdout);
sem_v();
n = rand() % 3;
sleep(n);
}
}