Linux8.15 day13 信号量

8.15 信号量

(1)概念
信号量是一个特殊的变量,一般取正数值。它的值代表允许访问的资源数目。
Р操作:获取资源时,需要对信号量的值进行原子减一
当信号量值为0时,代表没有资源可用,Р操作会阻塞。
V操作:释放资源时,需要对信号量的值进行原子加一
!信号量主要用来同步进程!
信号量的值如果只取0、1,将其称为二值信号量。如果信号量的值大于1,则称之为计数信号量。

临界资源:同一时刻 只允许被一个进程或线程访问的资源

临界区:访问临界资源的代码段

(2)信号量使用

操作信号量的接口介绍:

int semget(key_t key,int nsems,int semflg);  //创建信号量

int semop(int semid,struct sembuf*sops,unsigned nsops);  //P V操作

int semctl(int semid,int semnum,int cmd,...);  //销毁信号量 cmd信号量初始化

(sem.h)

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

union semun
{
    int val;
};

void sem_init();
int sem_p();
int sem_v();
void sem_destory();

(sem.c)

#include "sem.h"

static int semid = -1;

void sem_init()
{
    semid = semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);  //全新创建信号量
    if(semid == -1)  //全新创建失败 信号量可能已经存在
    {
        semid = semget((key_t)1234,1,IPC_CREAT|0600);
        if(semid == -1)
        {
            printf("creat sem failed\n");
            return;
        }
    }
    else
    {
        union semun a;
        a.val = 1;  //信号量的初始值
        if(semctl(semid,0,SETVAL,a) == -1)  //初始化信号量
        {
            printf("sentl setval error\n");
            return;
        }
    }
}

int sem_p()
{
    struct sembuf buf;
    buf.sem_sun = 0;
    buf.sem_op = -1;  //p
    buf.sem_flg = SEM_UNDO;

    if(semop(semid,&buf,1) == -1)
    {
        printf("semop p err\n");
        return -1;
    }

    return 0;
}

int sem_v()
{
    struct sembuf buf;
    buf.sem_sun = 0;
    buf.sem_op = 1;  //v
    buf.sem_flg = SEM_UNDO;

    if(semop(semid,&buf,1) == -1)
    {
        printf("semop v err\n");
        return -1;
    }

    return 0;
}

void sem_destory()
{
    if(semctl(semid,0,IPC_RMID) = -1)
    {
         printf("semctl del err\n");
    }
}

ipcs 查看消息队列 共享内存 信号量数目
ipcs -s 查看信号量
ipcrm -s 1(semid) 删除信号量

!!笔试例题

三个进程ABC运用信号量最终打印出"ABCABCABC…"

(sem.h)

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

#define SEM_MAX  3
#define SEM1  0
#define SEM2  1
#define SEM3  2

union semun
{
    int val;
};

void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destory();

(sem.c)

#include "sem.h"

static int semid = -1;

void sem_init()
{
    int arr[SEM_MAX] = {1,0,0};  //信号量初始值
    semid = semget((key_t)1234,SEM_MAX,IPC_CREAT|IPC_EXCL|O600);
    if(semid == -1)  //全新创建失败 信号量可能已经存在
    {
        semid = semget((key_t)1234,SEM_MAX,0600);  //全新创建失败 尝试获取已存在的信号量
        if(semid == -1)  //仍获取失败
        {
            printf("semget err\n");
            return;
        }
    }
    else
    {
        union semun a;
        int i = ;
        for( ;i < SEM_MAX;i++)
        {
            a.val = arr[i];
            if(semctl(semid,i,SETVAL,a) == -1)
            {
                printf("semtcl setval err\n");
            }
        }
    }
}

void sem_p(int index)
{
    if(index < 0 || index > SEM_MAX)
    {
        printf("index err\n");
        return;
    }

    struct sebuf buf;
    buf.sem_num = index;
    buf.sem_op = -1;  //p
    buf.sem_flg = SEM_UNDO;

    if(semop(semid,&buf,1) == -1)
    {
        printf("semop p err\n");
    }
}

void sem_v(int index)
{
    if(index < 0 || index > SEM_MAX)
    {
        printf("index err\n");
        return;
    }

    struct sebuf buf;
    buf.sem_num = index;
    buf.sem_op = 1;  //v
    buf.sem_flg = SEM_UNDO;

    if(semop(semid,&buf,1) == -1)
    {
        printf("semop v err\n");
    }
}

void sem_destory()
{
    if(semctl(semid,0,IPC_RMID) == -1)
    {
        printf("sem destory err\n");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值