Linux 之 System V信号量

其实就是学几个函数的用法:ftok(),  semget() , semctl(),  semop()   如果对哪个函数不熟悉就man 一下,例如man semctl()

下面是几个函数简单的实现代码,自己可以实现一下,助于理解...

sem.h:

对相应的系统函数”包装“,便于使用,例如
Ftok()对应于系统里的ftok();

//////sem.h

#include
#include
#include
#include
#include

key_t Ftok(const char *pathname, int proj_id)
{
    key_t key = ftok(pathname, proj_id);
    if(key == -1)
      {
          perror("ftok Error.\n");
          exit(1);
      }

    return key;
}


int Semget(key_t key, int nsems, int semflg)
{
    int sem_id = semget(key, nsems, semflg);
    if(sem_id == -1)
    {
       perror("sem_get Error.\n");
       exit(1);
    }

    return sem_id;
}

union semun 
{
   int               val;
   struct semid_ds  *buf;
   unsigned short   *array;
   struct seminfo   *__buf;
};

创建信号量:Ftok()、Semget()

这里的创建呢,信号量就相当于一个数组,然后,你创建多少个n个信号量,就把这个大的数组分成n个,下标从0到n-1,依次标识。到时候你操作哪个就写哪个下标即可。

//sem_create.c

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
      printf(": %s pathname proj_id.\n",argv[0]);
      return -1;
    }

    key_t sem_key = Ftok(argv[1], atoi(argv[2]));
    printf("sem_key: %x\n",sem_key);

    int sem_id = Semget(sem_key, 1, IPC_CREAT|IPC_EXCL|0755);//创建1个
    printf("sem_id: %d\n",sem_id);

    return 0;
}

删除信号量:IPC_RMID

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
      printf(":%s pathname proj_id\n",argv[0]);
      return -1;
    }
    key_t sem_key = Ftok(argv[1], atoi(argv[2]));

    int sem_id = Semget(sem_key, 0, 0);
    
    int ret = semctl(sem_id, 0, IPC_RMID);//删除0下标的信号量
    if(ret == -1)
    {
      printf("remove fail.");     
    }
    else
     printf("remove success.");

    return 0;
}   

 

设置信号量的值:SETVAL 
  因为前面只创建了一个,所以就只能给下标为0的SETVAL。

 

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 4)
    {
      printf(": %s pathname proj_id sem_val.\n",argv[0]);
      return -1;
    }
    key_t sem_key = Ftok(argv[1], atoi(argv[2]));

    int sem_id = Semget(sem_key, 0 , 0);

    union semun init;
    init.val = atoi(argv[3]);
    int ret = semctl(sem_id, 0, SETVAL, init);//给信号量数组下标为0的SETVAL

    if(ret == -1)
     printf("setval Error.\n");
    else
     printf("setval Success.\n");

    return 0;
}

   获取信号量的值:GETVAL

//GetValue

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
      printf(": %s pathname proj_id.\n",argv[0]);
      return -1;
    }
    key_t sem_key = Ftok(argv[1], atoi(argv[2]));

    int sem_id = Semget(sem_key, 0, 0);
    
    int ret = semctl(sem_id, 0, GETVAL);

    if(ret == -1)
      printf("getval Error.\n");
    else
      printf("getval: %d\n",ret);

    return 0;
}

 

对semop()函数的解释,例如:

struct sembuf  info[3];

info[0].sem_num = 0;

info[0].sem_op =  -1;

info[0].sem_flg = 0; 

 

info[1].sem_num = 1;

info[1].sem_op = ..;

info[1].sem_flg = 0;

 

info[2].sem_num = 2;

...

如果你要操作三个信号量,semop(sem_id,  info, 3);即可

如果操作前两个:semop(sem_id, info, 2);

如果只是操作第二个:semop(sem_id, info[1], 1 )也可以。

 

对信号量进行“V“操作:可用资源数+1

//////v_sem.c

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
      printf(": %s pathname proj_id\n",argv[0]);
      return -1;
    }

    key_t sem_key = Ftok(argv[1], atoi(argv[2]));

    int sem_id = Semget(sem_key, 0, 0);
 
    struct sembuf info;
    info.sem_num = 0;
    info.sem_op  = 1;//类似于V操作
    info.sem_flg = 0;
    int ret = semop(sem_id, &info, 1);//对一个信号量进行操作
    if(ret == -1)
     printf("v Error.\n");
    else
     printf("v Success.\n");

    return 0;
}

 对信号量执行“p”操作:可用资源数 -1

///p_sem.c

#include"sem.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
      printf(": %s pathname proj_id.\n",argv[0]);
      return -1;
    }

    key_t sem_key = Ftok(argv[1], atoi(argv[2]));
    
    int sem_id = Semget(sem_key, 0, 0);
    
    struct sembuf info;
    info.sem_num = 0;
    info.sem_op  = -1;//类似于P操作
    info.sem_flg = 0;

    int ret = semop(sem_id, &info, 1);
    if(ret == -1)
     printf("operator sem Error.\n");
    else
     printf("operator sem Success.\n");

    return 0;
}

 

你可能感兴趣的:(Linux)