Linnux信号量之semget()、semctl()、semop()函数说明及应用

Linnux信号量函数及应用

概述:
信号量(semzphore)与ipc结构不同,他是计数器。信号量用于实现进程的互斥与同步,而不是用于存储进程间通讯数据。说白了,信号量是用来控制进程间的通讯的,实现两个进程或多个进程之间的信息交互的先后起到重要作用。

1、特定
a、信号量用于进程同步,若要在进程传递需要结合共享内存。
b、信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。
c、每次对信号量的PV操作不仅限于对信号量值加1或减1,而且可以加任意整数。
d、支持信号量组。
e、信号量应用步骤:创建信号量—初始信号量—PV操作(对信号量值加1或减1)达到控制进程先后运行的效果。

2、创建信号量semget()函数原型:

简单的信号量控制常见一种形式只取0和1的为变量,叫二值信号量。而多个正整数信号被称作通用信号量。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg); 
创建信号量;创建成功返回信号量集ID,失败返回-1
参数:
    key :键值
   nsems: 信号量集个数
   semflg:获取|创建IPC_CREAT|0666 

3、初始化信号量semctl()函数原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...); 
 //初始化信号量
 参数:
   1、 semid : 信号量集id
   2、semnum:操作第几个信号量集
   3、cmd    :初始化,SETVAL 设置信号量的值
   4...   :设置SETVAL需要配置第四个参数,第四个参数是一个联合体
   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) */
};

4、对信号量操作semop()函数原型:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops); 
//对信号量操作
 对信号量操作,改变信号量的值,成功返回0,失败返回-1
 参数:
  semid :信号量集id 
  *sops :配置信号量集 (结构体)
  nsops :配置信号量集的个数

 sops[n]结构体如下:
 n为信号量集个数
struct sembuf sops[2];
           int semid;

           /* Code to set semid omitted */
     配置以下三个参数:
     sops[0].sem_num = 0; 第几个信号量       /* Operate on semaphore 0 */
     sops[0].sem_op = 0; 操作信号量赋值       /* Wait for value to equal 0 */
     sops[0].sem_flg = SEM_UNDO (设置为阻塞)


     sops[1].sem_num = 0;        /* Operate on semaphore 0 */
     sops[1].sem_op = 1;         /* Increment value by one */
     sops[1].sem_flg = 0

共享内存配合信号量的应用demo:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>

         //    int semget(key_t key, int nsems, int semflg);
         //      int semctl(int semid, int semnum, int cmd, ...);
        //  int semop(int semid, struct sembuf *sops, unsigned nsops);
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 semid)
{
    struct sembuf sops;

    sops.sem_num =0;
    sops.sem_op  =-1;
    sops.sem_flg = SEM_UNDO;
    semop(semid, &sops,1);

}
void putkey(int semid)
{
   struct sembuf sops;
   
    sops.sem_num = 0;
    sops.sem_op  = 1;
    sops.sem_flg = SEM_UNDO;
    semop(semid, &sops,1);
}

int main()
{
       key_t key;
       int semid;
       
       char *p = (char *)malloc(sizeof(char)*1024*5);
       key = ftok(".",999);

       semid = semget(key,1 ,IPC_CREAT|0666);      
       union semun get;
       get.val = 0 ;
       semctl(semid,0,SETVAL,get);
       
       int shmid = shmget(key,1024*5, IPC_CREAT|0666);
       p = shmat(shmid,0, 0);
       
      int  pid = fork();
      if (pid >0){
           while(1){
                getkey(semid);
                printf("fatherget:%s\n",p);
               // printf("tis is father\n");
                printf("\n");
                strcpy(p,"connet sucess!");
                putkey(semid);
         }
      }else if(pid == 0){
            while(1){
                strcpy(p,"qing qiu connet...");
               // printf("tis is childer\n");
                printf("\n");
                putkey(semid);
                getkey(semid);
                printf("childerget:%s\n",p);
                sleep(2);
           }
      }
      system("pause");
      return 0;
 }                                      

运行显示:

CLC@Embed_Learn:~$ ./sem

fatherget:qing qiu connet...

childerget:connet sucess!

fatherget:qing qiu connet...

childerget:connet sucess!

fatherget:qing qiu connet...

childerget:connet sucess!
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值