linux进程通信--信号量

  1. 信号量的功能
    信号量自身并不具有通信功能,而是在当多个进程访问同一资源时,使用信号量实现多个进程之间的互斥与同步,因此信号量相当于数据锁功能。简单的说信号量就是解决不同进程访问共享资源时,避免出现问题而产生的一种机制。
    信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待P(-1)操作和发送V(+1)操作。最简单的信号量是只能取0和1的变量,这也是信号量最常见的一种形式,叫做二进制信号量,而可以取多个正整数的信号量被称为通用信号量。

  2. 信号量的实现过程
    信号量的实现过程:当进程获得信号量时,执行P(-1)操作,进入临界区,此时阻止其它进程对资源的访问,当该进程执行完毕,实行V(+1)操作,离开临界区。其他进程此时可以访问资源。

  3. 信号量操作函数

int semop(int semid, struct sembuf *sops, unsigned nsops);
//操作一组信号,实现PV操作
int semget(key_t key, int nsems, int semflg);    
//nsems表示信号量的数量,通常设为1
//该函数实现当存在信号量时获取信号量,若不存在则创建信号量
//semflag表示创建信号量的标志位,设置为IPC_CREAT与权限标志位或,该方式可以实现不存在时,创建新的信号量,已存在时也不会报错
int semctl(int semid, int semnum, int cmd, ...);
对信号量进行初始化和删除信号量,
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) 
           };

   unsigned short sem_num;  /* semaphore number 
           short          sem_op;   /* semaphore operation 
           short          sem_flg;  /* operation flags 

4.应用实例
使用两个进程实现对终端进行输出,使用信号量实现两个进程之间的协调操作。

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <unistd.h>
int sem_id;
//定义共用体
union semun { 
         int val;               // SETVAL使用的值   
         struct semid_ds *buf;  // IPC_STAT、IPC_SET 使用缓存区
         unsigned short *array; // GETALL,、SETALL 使用的数组 
         struct seminfo *__buf; // IPC_INFO(Linux特有) 使用缓存区 
};
//声明函数
int sem_init();
int sem_del();
int semop_p();
int semop_v();

int main(int argc,char *argv[])
{

    char message='W';   // 初始化输入参数
    int sed_num;
    sem_id=semget((key_t)1234, 1, 0666|IPC_CREAT);     
    //如果输入的参数大于1 则输出的参数为输入的值   否则的话 输出为X;
    //如果输入的参数大于1  需要对信号量进行初始话   否则的话信号量不起作用
    if(argc>1)
    {
        //程序第一次被调用
        if(!sem_init())
        {
            printf("init semaphore failed\n");
        }
        message=argv[1][0];//输出参数
        sleep(2);
    }
    //做10个循环    看两个程序同时共用 终端输出是否打架/冲突
    for(sed_num=0;sed_num<10;sed_num++)
    {

        if(!semop_p())   //挂起信号量  
            exit(EXIT_FAILURE);
        printf("The %d ,times send %c,current pid is %d\n",sed_num,message,getpid());
        fflush(stdout);
        sleep(rand()%3);//休眠一会
        printf("The %d ,times send %c,current pid is %d\n",sed_num,message,getpid());
        fflush(stdout);
        sleep(rand()%3);
        if(!semop_v())  //打印完毕
            exit(EXIT_FAILURE);
        sleep(1);
    }
    printf("The process %d is sucess\n",getpid());
    sleep(5);
    if(argc>1)
    {
        if(!sem_del())
        {
            exit(EXIT_FAILURE);
        }
    }

    exit(0);
}
int sem_init()
{
    union semun sem_num;
    sem_num.val=1;
    if(semctl(sem_id,0,SETVAL,sem_num)==-1)
    {
        //exit(EXIT_FAILURE);
        return 0;
    }
    return 1;
}

int sem_del()
{
    if(semctl(sem_id,0,IPC_RMID)==-1)
    return 0;
    else
    return 1;
}
int semop_p()
{
    struct sembuf semopler_p;

    semopler_p.sem_num=0;  //对第sem_num  信号量进行操作     这里只有一个信号量所以只用0
    semopler_p.sem_op=-1;
    semopler_p.sem_flg=SEM_UNDO;
    if(semop(sem_id,&semopler_p,1)==-1)   //第三个参数指的是信号量的个数
    {
        return 0;

    }
    else
        return 1;
}
int semop_v()
{
    struct sembuf semopler_v;

    semopler_v.sem_num=0;  //对第sem_num  信号量进行操作     这里只有一个信号量所以只用0
    semopler_v.sem_op=1;
    semopler_v.sem_flg=SEM_UNDO;

    if(semop(sem_id,&semopler_v,1)==-1)   //第三个参数指的是信号量的个数
    {
        return 0;

    }
    else
        return 1;

}

5.总结
信号量是一种特殊变量,目的就是为了实现多个进程访问同一资源时出现冲突等现象的协调操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值