Linux——信号量(同步)

来源:互联网 发布:共享单车app源码 编辑:程序博客网 时间:2024/05/16 01:09
一.信号量(用于同步)
    1.回顾:
            一个进程控制另外一个进程.
            逻辑变量+pause/sleep+信号(前面章节 键盘控制随机数的例子)
    2.信号量(semaphore)信号灯
        三个数据:红灯/绿灯/黄灯                
 
        信号量是共享内存整数数组.根据需要定义指定的数组长度
        信号量就是根据数组中的值,决定阻塞还是解除阻塞
    
    3.编程模型
            3.1.创建或者得到信号量        semget (可用ipcs -s 来查看信号量)
            3.2.初始化信号量中指定下标的值    semctl
            3.3.根据信号量阻塞或者解除阻塞    semop
            3.4.删除信号量            semctl
案例:
            A:                B
            创建信号量        得到信号量
            初始化信号量                        
            根据信号量阻塞        解除阻塞
            删除信号量                            
                
            semget函数说明
            int semget(key_t key,
                    int nums,//信号量个数
                    int flags);//信号量的创建标记
                                            //创建IPC_CREAT|IPC_EXCL|0666
                                            //打开0
            返回:  -1:失败
                        >=0:成功返回信号量的ID
                        
                                        
            int semop(
                    int semid,//信号量ID
                    struct sembuf *op,//对信号量的操作.操作可以是多个
                    size_t nums,//第二个参数的个数
                );
            返回:
                    -1:时失败
                     0:成功                                    
            
            int semctl(int semid,
                        int nums,//对IPC_RMID无意义
                        int cmd,//SETVAL  IPC_RMID
                        ...);//对IPC_RMID无意义
            
            
            struct  sembuf
            {
                int sem_num;//下标
                int sem_op;
                int sem_flg;//建议为0.
            }
            
            sem_op:
                    前提条件信号量是unsigned short int;
                    不能<0.
                    -:够减,则semop马上返回,不够减,则阻塞.
                    +:执行+操作
                    0:判定信号量>0,则阻塞,直到为0
            控制进程的搭配方式:
                        +(解除阻塞) -(阻塞)
                        0(阻塞)     -(解除阻塞)  可实现双向通信
            
            

    semA.c 对信号量减一 阻塞

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/sem.h>//2.1.必须手工定义这个联合体union semun {intval;struct semid_ds *buf;unsigned short  *array;struct seminfo  *__buf;};main(){key_t key;int semid;//信号量IDunion  semun v;//2.2.定义初始化值int r;struct sembuf op[1];//<span style="color:#FF0000;">1.创建信号量</span>key=ftok(".",99);if(key==-1) printf("ftok err:%m\n"),exit(-1);//semid=semget(key,1/*信号量数组个数*/,//IPC_CREAT|IPC_EXCL|0666);//反复创建会失败 也可以在上面先删除semid=semget(key,1,0);//得到信号量if(semid==-1) printf("get err:%m\n"),exit(-1);printf("id:%d\n",semid);//<span style="color:#FF0000;">2.初始化信号量</span>v.val=2;r=semctl(semid,0,SETVAL,v);//2.3设置信号量的值if(r==-1) printf("初始化失败!\n"),exit(-1);//<span style="color:#FF0000;">3.对信号量进行阻塞操作</span>//3.1.定义操作op[0].sem_num=0;//信号量下标op[0].sem_op=-1;//信号量操作单位与类型op[0].sem_flg=0;while(1){r=semop(semid,op,1);printf("解除阻塞!\n");}//4.<span style="color:#FF0000;">删除信号量</span>(可以不删除)}

semB.c  每隔一秒对信号量加一解除阻塞

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/ipc.h>#include <sys/sem.h>//2.1.定义一个联合体union semun {intval;struct semid_ds *buf;unsigned short  *array;struct seminfo  *__buf;};main(){key_t key;int semid;//信号量IDunion  semun v;//2.2.定义初始化值int r;struct sembuf op[1];//1.<span style="color:#FF0000;">创建信号量</span>key=ftok(".",99);if(key==-1) printf("ftok err:%m\n"),exit(-1);semid=semget(key,1,0);//得到信号量if(semid==-1) printf("get err:%m\n"),exit(-1);printf("id:%d\n",semid);<span style="color:#FF0000;">//3.对信号量进行操作</span>//3.1.定义操作op[0].sem_num=0;//信号量下标op[0].sem_op=1;//信号量操作单位与类型op[0].sem_flg=0;while(1){r=semop(semid,op,1);sleep(1);}//4.删除(可以不删除)//semctl(semid,0,IPC_RMID);}



0 0