信号量是一个特殊的变量,一般取正数值。它的值代表允许访问的资源数目, 获取资源
时,需要对信号量的值进行原子减一,该操作被称为 P 操作。当信号量值为 0 时,代表没有
资源可用, P 操作会阻塞。释放资源时,需要对信号量的值进行原子加一,该操作被称为 V
操作。信号量主要用来同步进程。 信号量的值如果只取 0,1,将其称为二值信号量。如果信
号量的值大于 1,则称之为计数信号量。临界资源:同一时刻,只允许被一个进程或线程访问的资源
临界区:访问临界资源的代码段2.2信号量的使用
操作信号量接口介绍:
# include
# include # include int semget(key_t key,int nsems,int semflg); /*semget()创建或者获取已存在的信号量 *semget()成功返回信号量的ID,失败返回-1 *key :两个进程使用相同的key值,就可以使用同一个信号量 *nsems:内核维护的是一个信号量集,在新建信号量时,其指定信号量集中信号量的个数 semflg可选:IPC_CREAT IPC_EXCT */ int semop(int semid,struct sembuf*sops,unisgned nsops); //semop()对信号量进行改变,做p操作或这v操作 //semop()成功返回0,失败返回-1 //struct sembuf {unisgned short sem_num;//指定信号量集中的信号量下标short sem_op;//其值为-1,代表p操作,其值为1,代表v操作short sem_flg;//SEM_UNDO } int semctl (int semid,int semnum,int cmd,...); /* semctl() 控制信号量 semctl()成功返回0,失败返回-1 cmd选项:SETVAL IPC_RMID SETVAL:用来把信号量初始化为一个已知的值。这个值通过union semun中的val成员设置。 其作用是在信号量第一次使用之前对它进行设置 IPC_RMID:用于删除一个已经无需继续使用的信号量标识符。 semtcl函数会根据command参数的不同而返回不同的值。对于SETVAL和IPC_RMID,成功是返回0,失败时返回-1. */ 头文件sys/sem.h通常会依赖于另两个头文件sys/types.h和sys/ipc.h。一般情况下,它们都会呗sys/sem.h自动包含,因此不需要为它们明确添加相应的# include语句。
例题:进程 a 和进程 b 模拟访问打印机,进程 a 输出第一个字符‘ a’表示开始使用打印
机,输出第二个字符‘ a’表示结束使用, b 进程操作与 a 进程相同。(由于打印机同一时刻
只能被一个进程使用,所以输出结果不应该出现 abab) ,如图所示:
代码如下:
sem.h
#include
union semun{int val; }; void sem_init();//创建/或者已存在的信号量 void sem_p();//p 减一 void sem_v();//v 加一 void sem_destroy();//销毁 sem.c
#include
#include #include #include #include "sem.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);}else{union semun a;a.val = 1;//信号量的初始值if ( semctl(semid,0,SETVAL,a) == -1 ){perror("semctl error");}}}void sem_p()//p 减一{struct sembuf buf;buf.sem_num = 0;buf.sem_op = -1;//pbuf.sem_flg = SEM_UNDO;if ( semop(semid,&buf,1) == -1 ){perror("semop p error");}}void sem_v()//v 加一{struct sembuf buf;buf.sem_num = 0;buf.sem_op = 1;//vbuf.sem_flg = SEM_UNDO; if ( semop(semid,&buf,1) == -1 ){perror("semop v error");}}void sem_destroy()//销毁{if ( semctl(semid,0,IPC_RMID) == -1 ){perror("semctl del error");}} a.c
#include
#include #include #include #include int main() {sem_init();int i = 0;for( ;i < 10; i++ ){sem_p();printf("a");fflush(stdout);int n = rand() % 3;sleep(n);printf("a");fflush(stdout);sem_v();n = rand() % 3;sleep(n);}} b.c
#include
#include #include #include #include int main() {sem_init();int i = 0;for( ;i < 10; i++ ){sem_p();printf("b");fflush(stdout);int n = rand() % 3;sleep(n);printf("b");fflush(stdout);sem_v();n = rand() % 3;sleep(n);}} 执行结果:
上一篇:【Java进阶篇】——反射机制
下一篇:js学习15(正则表达式)