介绍
信号量是Linux内部的一种进程同步方式,在多个进程同时执行时,使用信号量可保护临界区代码执行时不会乱序。
函数
//创建并获取信号量
int semget(key_t key, int num_sems, int sem_flags);
//改变信号量的值
int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);
//控制信号量
int semctl(int sem_id, int sem_num, int command, ...);
举例
sem1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <string.h>
#define SEMKEY 1234
union semun{
int val;
struct semid *buf;
unsigned short *array;
struct seminfo *__buf;
};
void sem_p(int semid){
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(ret == -1){
perror("semop");
return;
}
}
void sem_v(int semid){
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(ret == -1){
perror("semop");
return;
}
}
int main(){
int semid;
union semun unsem;
semid = semget(SEMKEY,1,0);
if(semid == -1){
perror("semget");
exit(1);
}
unsem.val = 1;
semctl(semid,0,SETVAL,unsem);
while(1){
sem_p(semid);
printf("This is the father process!\n");
sleep(10);
sem_v(semid);
}
semctl(semid,0,IPC_RMID);
return 0;
}
sem2.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <string.h>
#define SEMKEY 1234
union semun{
int val;
struct semid *buf;
unsigned short *array;
struct seminfo *__buf;
};
void sem_p(int semid){
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(ret == -1){
perror("semop");
return;
}
}
void sem_v(int semid){
int ret;
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
ret = semop(semid,&sbuf,1);
if(ret == -1){
perror("semop");
return;
}
}
int main(){
int semid;
union semun unsem;
semid = semget(SEMKEY,1,0);
if(semid == -1){
perror("semget");
exit(1);
}
//unsem.val = -1;
//semctl(semid,0,SETVAL,unsem);
while(1){
sem_p(semid);
printf("This is the child process!\n");
sleep(1);
sem_v(semid);
}
semctl(semid,0,IPC_RMID);
return 0;
}
执行效果
sem1.c 每隔10s输出一次信息,sem2.c虽然设置的是1s输出一次信息,但是由于信号被sem1.阻塞,所以也变成10s输出一次。