信号量:相当于一个计数器,描述当前环境下临界资源的数目。信号量是用来保护临界资源的,而信号量本身也是临界资源。
生命周期:随内核。
原子性:即要么做,要么不做。
临界资源:不同进程可以看到的同一资源。
临界区:不同进程访问同一资源的代码区(write(),read())。
互斥:任一时刻,只有一个进程进入临界区访问临界资源,且访问时具有原子性。
同步:所有进程以某种顺序依次访问临界资源。
信号量的两个基本操作:P、V操作-----解决互斥和同步的问题。
P操作:申请资源,如果S>0,则S=S-1;如果S = 0,就挂起该进程的执行。
V操作:使用资源完毕,归还给系统,若有进程挂起,则唤醒等待进程,否则S=S+1。
代码如下:
comm.h:#ifndef _COMM_H#define _COMM_H#include<stdio.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#define PATHNAME "."#define PROJ_ID 0666union semun{ int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf;};//struct sembuf{//unsigned short sem_num; // semaphore number //short sem_op; // semaphore operation // short sem_flg; //operation flags //};int create_sem(int nsem);int get_sem();int destroy_sem(int semid);int init_sem(int semid,int which,int val);int P(int semid,int which);int V(int semid,int which);#endifcomm.c:#include"comm.h"static int comm_sem(int nsem ,int flag){ key_t key=ftok(PATHNAME,PROJ_ID); int semid=semget(key,nsem,flag); if(semid<0){ perror("semget"); } return semid;}static op_sem(int semid,int op,int which){ struct sembuf _sembuf; _sembuf.sem_op = op; _sembuf.sem_num = which; _sembuf.sem_flg = 0; return semop(semid,&_sembuf,1);}int create_sem(int nsem){ return comm_sem(nsem,IPC_CREAT|IPC_EXCL|0666);}int get_sem(){ return comm_sem(0,IPC_CREAT);}int destroy_sem(int semid){ if(semctl(semid,0,IPC_RMID)<0) { perror("semctl"); return -1; } //printf("destroy sucess"); return 0;}int init_sem(int semid,int which,int _val){ union semun _semun; _semun.val = _val; if(semctl(semid,which,SETVAL,_semun)<0) { perror("semctl"); return -2; } return 0;}int P(int semid,int which){ return op_sem(semid,-1,which);}int V(int semid,int which){ return op_sem(semid,1,which);}sem.c:#include"comm.h"#include<stdlib.h>int main(){ int semid=create_sem(10); init_sem(semid,0,1); pid_t id=fork(); if(id<0) { perror("fork"); return -1; } else if(id ==0){//child int sem_id=get_sem(); while(1) { P(sem_id,0); printf("A"); fflush(stdout); usleep(12345); printf("A"); fflush(stdout); usleep(13456); V(sem_id,0); } exit(0); } else{//father while(1) { P(semid,0); printf("B"); fflush(stdout); usleep(14345); printf("B"); fflush(stdout); usleep(13345); V(semid,0); } wait(NULL); } destroy_sem(semid); return 0;}Makefile:sem:comm.c sem.c gcc -o $@ $^.PHONY:cleamclean: rm -f sem