信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。
第一: 父子进程相隔1s报数一次
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <string.h> #include <sys/sem.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> typedef union semun { int val; /* Value for SETVAL */ unsigned short *array; /* Array for GETALL, SETALL */ }SEM; //实现两个进程的0~99报数 int main(int argc,char *argv[]) { int i=0; //1、获取键值 ftok key_t key = ftok(argv[1], 2); if(-1 == key) { perror("ftok error\r\n"); return 0; } //2、创建信号量集 semget int semid = semget(key, 2, IPC_CREAT | 0666); if(-1 == semid) { perror("semget error\r\n"); return 0; } SEM num={0}; //3、设置0号信号量的值为1 SETVAL num.val = 1; if(semctl(semid, 0, SETVAL, num) == -1) { perror("SETALL error\r\n"); return 0; } //4、创建操作方式的结构体 struct sembuf struct sembuf sops[4]={{0,1,0},{0,-1,0},{1,1,0},{1,-1,0}}; //5、创建子进程 fork pid_t pid = fork( ); if(pid < 0) { perror("fork error\r\n"); return 0; }else if(0 == pid)//子进程 单数 { i=1; //初始为1 while(i < 100) { //信号1 -1 if(semop(semid, &sops[3], 1) == -1) { perror("semop 1 -1 error\r\n"); return 0; } printf("child:time = %d\r\n",i);// 1 i+=2; sleep(1); //信号0 +1 if(semop(semid, &sops[0], 1) == -1) { perror("semop 0 +1 error\r\n"); return 0; } } exit(0); }else//父进程 双数 { while(i < 100) { //信号0 -1 if(semop(semid, &sops[1], 1) == -1) { perror("semop 0 -1 error\r\n"); return 0; } printf("father:time = %d\r\n",i); //0 2 i+=2; sleep(1); //信号1 +1 if(semop(semid, &sops[2], 1) == -1) { perror("semop 1 +1 error\r\n"); return 0; } } wait(NULL); } return 0; }
第二:利用信号量实现父子进程通信
//实例2:利用父子进程通信 #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/wait.h> #include <sys/sem.h> union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo* _buf; }; int main() { int ret; int semid; //创建信号量 semid = semget(IPC_PRIVATE,1,IPC_CREAT|0644); //初始化信号量、设置信号量 union semun arg; arg.val=0;//信号量值为0 semctl(semid,0,SETALL,arg); //查询当前信号量的值 ret = semctl(semid,0,GETVAL);//GETVAL返回值为信号值 printf("val:%d\r\n",ret); //创建子进程 pid_t pid; pid = fork(); if(pid == 0) { //子进程 sleep(5); struct sembuf sops={0,1,0}; while(1) { semop(semid,&sops,1);//P操作 printf("--------V------\r\n"); sleep(1); } } else { //父进程 struct sembuf sops={0,-1,0}; while(1) { semop(semid,&sops,1);//P操作 printf("--------P------\r\n");//信号量0还可以执行最后一次 sleep(1); } } semctl(semid,0,IPC_RMID); return 0; }
总结:信号量就是为了对共享资源进行保护,理解基本实现方法非常重要。