linux ---17 --18----信号量编程实现

信号量相当于钥匙,进程A拿钥匙进入临界资源(多个进程都可以进入),B就没有钥匙进去了,只能A出来,B才有钥匙拿进去。

信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。

1、特点

  1. 信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
  2. 信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
  3. 每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
  4. 支持信号量组。

原子操作:就是在执行某一操作时不被打断。
linux原子操作问题来源于中断、进程的抢占以及多核smp系统中程序的并发执行。

2、原型

最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。而可以取多个正整数的信号量被称为通用信号量。

Linux 下的信号量函数都是在通用的信号量数组上进行操作,而不是在一个单一的二值信号量上进行操作。

1 #include <sys/sem.h>

// 创建或获取一个信号量组:若成功返回信号量集ID,失败返回-1
2 int semget(key_t key, int num_sems, int sem_flags);   创建信号量
   参数1 :key
   参数2: 信号量集当中的信号量个数  (1)
   参数3: (创建/获取) IPC_CREAT|0666    
   返回值:集合id 

// 对信号量组进行操作,改变信号量的值:成功返回0,失败返回-1
3 int semop(int semid, struct sembuf semoparray[], size_t numops);  
    参数1:semid
    参数2: 次参数的数组可以在结构体进行  
    参数3: SEM_UNDO (默认)t


  
void getkey(int id){
    struct sembuf set;
            set.sem_num =0;                      /* Operate on semaphore 0 */
           set.sem_op =-1;         /               * Wait for value to equal 0 */
           set.sem_flg = SEM_UNDO;
   semop(id,&set,1);
  printf("get  the  key\n");
}

void backkey(int id){
    struct sembuf set;
            set.sem_num =0;                      /* Operate on semaphore 0 */
           set.sem_op =1;                        /* Wait for value to equal 0 */
           set.sem_flg = SEM_UNDO;
   semop(id,&set,1);
  printf("back  the  key\n");
}



// 控制信号量的相关信息
4 int semctl(int semid, int sem_num, int cmd, ...);      初始化信号量
    参数1:返回值信号量集合id
   参数2:操作第几个信号量
   参数3:(设置信号量的值)SETVAL
   参数4: 一个结构体  (结构体的第一个数据提前初始化)

先实现一段代码 

  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;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };



void getkey(int id){
    struct sembuf set;
            set.sem_num =0;                      /* Operate on semaphore 0 */
           set.sem_op =-1;         /* Wait for value to equal 0 */
           set.sem_flg = SEM_UNDO;
   semop(id,&set,1);
  printf("get  the  key\n");
}

void backkey(int id){
    struct sembuf set;
          set.sem_num =0;                      /* Operate on semaphore 0 */
           set.sem_op =-1;         /* Wait for value to equal 0 */
           set.sem_flg = SEM_UNDO;
   semop(id,&set,1);
  printf("get  the  key\n");
}

void backkey(int id){
    struct sembuf set;
            set.sem_num =0;                      /* Operate on semaphore 0 */
           set.sem_op =1;         /* Wait for value to equal 0 */
           set.sem_flg = SEM_UNDO;
   semop(id,&set,1);
  printf("back  the  key\n");
}

int main(){

  union semun data;
    key_t key;
   key=ftok(".",'1');
  int semid =semget(key,1,IPC_CREAT|0666);     //创建
      data.val=0;                           //这个值关乎信息量钥匙的有与没,拿与放
      semctl(semid, 0, SETVAL,data.val);            //初始化 信息量

   pid_t pid=fork();

    if(pid>0){

         getkey(semid);                   //获取钥匙
            printf("the is  father\n");
            backkey(semid);             //退出钥匙
}
      else if (pid==0){
             //  getkey(semid);
              printf("the is chill\n");
               backkey(semid);
                }
     else{
              printf(" open pid error\n");
         }
return 0;
}


运行

CLC@Embed_Learn:~/ccc$ ./sig
the is chill
back  the  key
get  the  key
the is  father
back  the  key
CLC@Embed_Learn:~/ccc$ vi demo17.c

上面的例子如果不加信号量,则子进程会先执行完毕。这里加了信号量让子进程等待父进程执行完以后再执行。

更详细的代码参考

进程间通信(IPC)介绍_Heavy sea的博客-CSDN博客_进程ipc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追着太阳跑1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值