信号量

信号量:

信号量是用来控制临界资源的,那什么是临界资源呢:
在系统中有许多进程,他们共享各种资源,然而又很多资源一次只能供一个进程来使用,一次仅允许一个进程使用的资源称为临界资源,比如共享内存。共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取,所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量。

信号量集:

就是多个信号量的集合

P操作:

类似于拿锁,通过P操作来获取访问临界资源的权限。运行P,信号量S的值将被减少。企图进入临界区块的进程,需要先运行 P(wait())。当信号量S减为负值时,进程会被挡住,不能继续;当信号量S不为负值时,进程可以获准进入临界区块。

V操作:

类似于放锁,P操作后其他进程不能访问这个临界资源,只有P操作的进程执行了V操作后其他进程才可以访问。运行 V,信号量S的值会被增加。结束离开临界区块的进程,将会运行 V(又称signal())。当信号量S不为负值时,先前被挡住的其他进程,将可获准进入临界区块。


一、相关API

1.创建或者打开信号量集

 int semget(key_t key, int nsems, int semflg);
 //获取、创建一个信号量集,成功返回ID号,失败返回-1
 //nsems为你想创建的信号量集中信号量的个数,semflg为权限,通常可设置为IPC_CREAT|0777。

2.控制信号量

int semctl(int semid, int semnum, int cmd, ...);
//控制、初始化信号量
//semid为信号量组的ID,semnum为你要控制信号量组的第几个信号量(0开始),cmd为宏
union semun {
          int              val;    //开始有几把锁**
          struct semid_ds *buf;   
          unsigned short  *array;  
          struct seminfo  *__buf;  
            };

如果cmd指定为SETVAL(具体见man手册),则需要第四个参数,第四个参数为联合体

3.P操作或者V操作

 int semop(int semid, struct sembuf *sops, size_t nsops);
 //sops是一个指针,指向一个数组。nsops是数组的个数
 struct sembuf sops[2];
 sops[0].set_num = 0;//信号量的编号,可以看semctl第二个参数为多少
 sops[0].set_op = -1;//1为操作后锁+1,-1为操作后锁-1
 sops[0].set_flg= SEM_UNDO;//可以设置为SEM_UNDO,意思是当进程终止时取消对锁操作
 --------------------------------------------------------------------------
 sops[1].set_num = 0;
 sops[1].set_op = 1;
 sops[1].set_flg= SEM_UNDO;

 if(semop(semid,sops,2) == -1){
 	exit(-1);
  }

例子:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
union semun {
      int              val;    /* Value for SETVAL */
      struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
      unsigned short  *array;  /* Array for GETALL, SETALL */
      struct seminfo  *__buf;
};

void pkey(int id)
{
        struct sembuf sops;
        sops.sem_num = 0;
        sops.sem_op = -1;
        sops.sem_flg = SEM_UNDO;

        semop(id,&sops,1);
}

void vkey(int id)
{
        struct sembuf sops;
        sops.sem_num = 0;
        sops.sem_op = 1;
        sops.sem_flg = SEM_UNDO;

        semop(id,&sops,1);

}
int main()
{
        key_t key;
        key = ftok(".",5);
        int semId = semget(key,1,IPC_CREAT|0777);

        union semun initsem;
        initsem.val = 0;
        semctl(semId,0,SETVAL,initsem);


        int pid  = fork();
        if(pid >0){
                pkey(semId);
                printf("this is father\n");
                vkey(semId);
        }

        else if(pid == 0){
                printf("this is child\n");
                vkey(semId);

        }else{
                printf("fork error\n");
        }

        return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值