美文网首页
进程通信之信号量

进程通信之信号量

作者: 二进制人类 | 来源:发表于2022-10-01 20:37 被阅读0次

获取信号量

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
 * [semget 创建信号量集合]
 * @param  key    [
 * key表示获取信号量的key
 * IPC_PRIVATE:表示每次获取新的信号量集合,主要用于既有亲缘关系的进程。
   非IPC_PRIVATE:在每次获取的时候,key对应的信号量集合不存在则创建并返回id;存在则直接返回已有信号量集合的id
 * ]
 * @param  nsems  [信号量集合中信号量的个数]
 * @param  semflg [
 * 信号量的访问权限和创建方式
 * IPC_CREAT    没有则创建,有则直接返回;
   IPC_CREAT | IPC_EXCL : 没有则创建返回,有则报错;
 * ]
 * @return        [成功返回信号量的id,失败返回-1且修改errno的值]
 */
int semget(key_t key, int nsems, int semflg);

控制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
 * [semctl 实现信号量集合中信号量的控制]
 * @param  semid  [信号量集合id]
 * @param  semnum [信号量在集合中的编号(编号从0开始计数)]
 * @param  cmd    [
 * 控制命令,是一个可变参数,需要根据cmd命令选择是否使用第4个参数
 *   IPC_STAT和IPC_SET    获取或者设置IPC的状态属性;
        IPC_RMID             删除IPC对象
        GETALL和SETALL       获取和设置信号量集合的属性值;
        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) /
};
 * ]
 * @return        [成功返回和cmd相关 失败返回 -1 修改errno值]
 */
int semctl(int semid, int semnum, int cmd,...);

PV操作

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
/**
 * [semop PV操作]
 * @param  semid [信号量集合的id]
 * @param  sops  [信号量操作的结构体]
 * @param  nsops [参数二数组个数]
 * @return       [成功返回0,失败返回-1]
 */
int semop(int semid, struct sembuf *sops, size_t nsops);

同步实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.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) */
};

/* P操作 */
int Sem_Wait(int semid)
{
    int ret;
    struct sembuf mysembuf =
    {
        .sem_num = 0,/* 信号量集合中信号的序号 */
        .sem_op = -1,/* -1表示资源数-1,实现P操作 */
        .sem_flg = 0
    };
    ret = semop(semid, &mysembuf, 1);
    if (ret == -1)
    {
        perror("semop->P");
        return -1;
    }
    return 0;
}

/* V操作 */
int Sem_Post(int semid)
{
    int ret;
    struct sembuf mysembuf =
    {
        .sem_num = 0,/* 信号量集合中信号的序号 */
        .sem_op = 1,/* 1表示资源数+1,实现V操作 */
        .sem_flg = 0
    };
    ret = semop(semid, &mysembuf, 1);
    if (ret == -1)
    {
        perror("semop->P");
        return -1;
    }
    return 0;
}

int main()
{
    key_t key;
    int semid;
    int ret;
    int i;
    union semun mysemum;
    pid_t pid;
    /* 获取信号量的key */
    key = ftok(".", 's');
    if (key == -1)
    {
        perror("ftok");
        return -1;
    }
    /* 创建信号量集合 */
    semid = semget(key, 1, 0777 | IPC_CREAT);
    if (semid == -1)
    {
        perror("semget");
        return -1;
    }
    mysemum.val = 0;
    /* 设置信号量的初始值 */
    ret = semctl(semid, 0, SETVAL, mysemum);
    if (ret == -1)
    {
        perror("semctl->SETVAL");
        return -1;
    }
    /* 实现多个任务的同步:子进程执行1次之后父进程才能执行1次 */
    pid = fork();
    if (pid == -1)
    {
        perror("fork");
        return -1;
    }
    else if (pid == 0)
    {
        while(1)
        {
            sleep(1);
            printf("child process\n");
            /* 信号量进行V操作 */
            Sem_Post(semid);
        }
        exit(EXIT_SUCCESS);
    }
    else
        while(1)
        {
            /* 信号量进行P操作 */
            Sem_Wait(semid);
            printf("parent process\n");
        }
    /* 删除信号量集合 */
    ret = semctl(semid, 0, IPC_RMID);
    if (ret == -1)
    {
        perror("semctl->IPC_RMID");
        return -1;
    }
}

互斥实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.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 shm_init(const char *pathname, int proj_id, size_t size, void **shmaddr)
{
    key_t key;
    int shmid;
    /* 获取共享内存的键值 */
    key = ftok(pathname, proj_id);
    if (key == -1)
    {
        perror("ftok");
        return -1;
    }
    /* 获取共享内存 */
    shmid = shmget(key, size, 0777 | IPC_CREAT);
    if (shmid == -1)
    {
        perror("shmget");
        return -1;
    }
    /* 共享内存的映射 */
    *shmaddr = shmat(shmid, *shmaddr, 0);
    if (*shmaddr == (void *) -1)
    {
        perror("shmat");
        return -1;
    }
    return shmid;
}

int shm_del(int shmid, void *shmaddr)
{
    int ret;
    /* 解除共享内存的映射:不会删除共享内存 */
    ret = shmdt(shmaddr);
    if (ret == -1)
    {
        perror("shmdt");
        return -1;
    }
    /* 删除共享内存:从内存中删除 */
    ret = shmctl(shmid, IPC_RMID, NULL);
    if (ret == -1)
    {
        perror("shmctl->IPC_RMID");
        return -1;
    }
    return -1;
}

int Sem_Init(const char *pathname, int proj_id, int nsems)
{
    key_t key;
    int semid;
    int ret;
    union semun mysemum;
    /* 获取信号量的key */
    key = ftok(pathname, proj_id);
    if (key == -1)
    {
        perror("ftok");
        return -1;
    }
    system("ipcs -s");
    /* 创建信号量集合 */
    semid = semget(key, nsems, 0777 | IPC_CREAT);
    if (semid == -1)
    {
        perror("semget");
        return -1;
    }
    mysemum.val = 1;
    /* 设置信号量的初始值 */
    ret = semctl(semid, 0, SETVAL, mysemum);
    if (ret == -1)
    {
        perror("semctl->SETVAL");
        return -1;
    }
    return semid;
}

/* P操作 */
int Sem_Wait(int semid)
{
    int ret;
    struct sembuf mysembuf =
    {
        .sem_num = 0,/* 信号量集合中信号的序号 */
        .sem_op = -1,/* -1表示资源数-1,实现P操作 */
        .sem_flg = 0
    };
    ret = semop(semid, &mysembuf, 1);
    if (ret == -1)
    {
        perror("semop->P");
        return -1;
    }
    return 0;
}

/* V操作 */
int Sem_Post(int semid)
{
    int ret;
    struct sembuf mysembuf =
    {
        .sem_num = 0,/* 信号量集合中信号的序号 */
        .sem_op = 1,/* 1表示资源数+1,实现V操作 */
        .sem_flg = 0
    };
    ret = semop(semid, &mysembuf, 1);
    if (ret == -1)
    {
        perror("semop->P");
        return -1;
    }
    return 0;
}

int main()
{
    int ret;
    int shmid;
    int semid;
    char *shmaddr = NULL;
    pid_t pid;
    /* 共享内存的初始化 */
    shmid = shm_init(".", 'm', 256, (void **)&shmaddr);
    if (shmid == -1)
        return -1;
    /* 信号量的初始化 */
    semid = Sem_Init(".", 's', 1);
    if (semid == -1)
        return -1;
    pid = fork();
    if (pid == -1)
    {
        perror("fork");
        return -1;
    }
    else if(pid == 0)
    {
        /* 子进程 */
        int len;
        int i;
        char tmp;
        strcpy(shmaddr, "0123456789");
        len = strlen(shmaddr);
        printf("------------\n");
        while(1)
        {
            Sem_Wait(semid);
            for (i = 0; i < len / 2; i++)
            {
                tmp = shmaddr[i];
                shmaddr[i] = shmaddr[len - 1 - i];
                shmaddr[len - 1 - i] = tmp;
            }
            Sem_Post(semid);
        }
        exit(EXIT_SUCCESS);
    }
    while(1)
    {
        Sem_Wait(semid);
        printf("%s\n", shmaddr);
        Sem_Post(semid);
        sleep(1);
    }
    ret = shm_del(shmid, shmaddr);
    if (ret == -1)
        return -1;
    return 0;
}

相关文章

  • 第二章 进程通信、线程

    进程通信:进程通信是指进程之间的信息交换。 一、低级通信——进程之间的互斥和同步 信号量机制是有效的同步工具,但...

  • 信号量

    线程中的信号量 有名信号量:进程通信 无名信号量:线程通信 初始化:调用sem_init()就可以创建成功,val...

  • 二.进程(6-7)进程通信、线程

    进程通信是指进程之间的信息交换。 一、低级通信——进程之间的互斥和同步 信号量机制是有效的同步工具,但作为通信...

  • 进程通信之信号量

    获取信号量 控制 PV操作 同步实例 互斥实例

  • 2-6-7进程通信、线程

    进程通信是指进程之间的信息交换。 一、低级通信——进程之间的互斥和同步 信号量机制是有效的同步工具,但作为通信工具...

  • 第2章 2-6、2-7进程通信、线程

    进程通信是指进程之间的信息交换。 一、低级通信——进程之间的互斥和同步 信号量机制是有效的同步工具,但作为通信工具...

  • 二.进程(6-7)进程通信、线程

    进程通信是指进程之间的信息交换。 一、低级通信——进程之间的互斥和同步 信号量机制是有效的同步工具,但作为通信工...

  • 操作系统——进程通信

    进程通信是指进程之间的信息交换。 1、低级通信——进程之间的互斥和同步信号量机制是有效的同步工具,但作为通信工具缺...

  • 8.ipc

    进程间通信 Linux中的进程间通信主要有:管道、FIFO、消息队列、信号量、共享存储以及网络IPC中的套接字。 ...

  • 操作系统

    操作系统 进程间通信的方法都有什么信号量(semophore ) :信号量是一个计数器,可以用来控制多个进程对共享...

网友评论

      本文标题:进程通信之信号量

      本文链接:https://www.haomeiwen.com/subject/lugdartx.html