Linux 多进程程序调试实例(六)-- 信号量

信号量

介绍

  • 信号量本质是一个计数器,用来统计临界资源数量的一个计数器,根据临界资源的数量,同步和互斥进程使用的临界资源。
  • 信号量主要用来起到同步互斥的目的,和共享内存配合在进程间实现互斥的传输数据
  • 信号量不仅可以用来在不同进程间的同步和互斥,还可以在线程间实现同步和互斥

函数

1. semget()

  • 函数介绍
    • 该函数转换键值获取信号量 ID。
  • 函数原型
int semget (key_t __key, int __nsems, int __semflg)
  • 函数说明
    • key: 该值得获取通过 ftok 函数
    • nsems:初始信号集合中的数组个数,如果是新建的必须指定该值,如果引用已有的信号量,则置为 0
    • flag:设置的权限,参考消息队列

2. semctl()

  • 函数介绍
    • 该函数对信号量执行多种操作
  • 函数原型
semctl (int __semid, int __semnum, int __cmd, .../*union semun arg*/)
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) */
};
  • 函数说明
    • semid: 信号 ID,从 semget() 函数中返回的
    • semnum: 指定信号量集合中的哪一个成员, 从 0 到 nsems-1
    • cmd: ctl的一些控制命令,具体使用 man semctl 查看
    • arg:可选参数,具体使用取决于所请求的命令
    • 成功返回 0,失败返回 -1

1. semop()

  • 函数介绍
    • 信号量增加或者减少的操作函数
  • 函数原型
int semop (int __semid, struct sembuf *__sops, size_t __nsops);
struct sembuf
{
  unsigned short int sem_num;	/* semaphore number */
  short int sem_op;		/* semaphore operation */
  short int sem_flg;		/* operation flag */
};
  • 函数说明
    • semid: 信号量 ID
    • sops: 一个指向 sembuf 结构的指针
    • nops: 规定该数组中操作数的数量
    • 返回值:成功返回0,失败返回 -1

代码

// semaphore.h
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/sem.h>
#include<cstdio>

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

int set_semvalue(int sem_id, int count);
void del_semvalue(int sem_id);
int semaphore_p(int sem_id);
int semaphore_v(int sem_id);

// semaphore.cpp
#include"semaphore.h"

// init semaphore
int set_semvalue(int sem_id, int count){
    semun sem_union;
    sem_union.val = count;
    if(semctl(sem_id, 0, SETVAL, sem_union) == -1){
        printf("set_semvalue failed\n");
        return -1;
    }
    return 0;
}

void del_semvalue(int sem_id){
    semun sem_union;
    if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) {
        printf("del_semvalue failed\n");
    }
}

int semaphore_p(int sem_id){
    sembuf sem_b;
    sem_b.sem_num = 0;
    sem_b.sem_op = -1;
    sem_b.sem_flg = SEM_UNDO;
    if(semop(sem_id, &sem_b, 1) == -1){
        printf("semphore_p failed\n");
        return -1;
    }
    return 0;
}

int semaphore_v(int sem_id){
    sembuf sem_b;
    sem_b.sem_num = 0;
    sem_b.sem_op = 1;
    sem_b.sem_flg = SEM_UNDO;
    if(semop(sem_id, &sem_b, 1) == -1) {
        printf("semaphore_v failed\n");
        return -1;
    }
    return 0;
}

// sem_1.cpp
#include"semaphore.h"

int main()
{
    key_t key = ftok("./tmp",2);
    int sem_id = semget(key, 1, 0666 | IPC_CREAT);
    set_semvalue(sem_id,0);

    for(int i = 0; i < 10; ++i){
        semaphore_p(sem_id);
        printf("sem1 semaphore_p: %d\n",i);
    }

    printf("%d -- finished\n", getpid());

    del_semvalue(sem_id);
    return 0;
}
// sem_2.cpp
#include"semaphore.h"
/*
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) */
};
*/
int main()
{
    key_t key = ftok("./tmp",2);
    int sem_id = semget(key, 1, 0666 | IPC_CREAT);

    for(int i = 0; i < 10; ++i){
        printf("sem2 semaphore_v i:%d\n",i);
        semaphore_v(sem_id);
        sleep(1);
    }

    printf("%d -- finished\n",getpid());
    return 0;
}
posted @ 2023-02-07 16:17  王清河  阅读(129)  评论(0编辑  收藏  举报