LinuxC进程间通信之共享内存、信号量综合实例

LinuxC进程间通信之共享内存、信号量综合实例

公共接口

// interface.h
/*
** (C) Copyright 2023 Reil.kun All Rights Reserved.
** Description:
** Author:Reil.kun
** Date: 
** Modify Record:
*/

#ifndef __INTERFACE_H
#define __INTERFACE_H

#include <stdio.h>

#define  LOGI(fmt, ...) do { \
    printf("[INFO][%s:%d]"fmt"", __func__, __LINE__, ##__VA_ARGS__); \
    } while(0)

#define  LOGE(fmt, ...) do { \
    printf("[ERROR][%s:%d]"fmt"", __func__, __LINE__, ##__VA_ARGS__); \
    } while(0)

#define KEY_PATHNAME (".")
#define KEY_PROJECT_ID ('R')
#define SEMAPHORE_NUMS (1)
#define SHM_SEM_PERMISSION (0666)

#define PRINT_A (0)
#define PRINT_B (1)
#define PRINT_A_B_2S (2)
#define PRINT_A_B_250MS (3)

#define PRINT_TYPE0 (0)
#define PRINT_TYPE1 (1)
#define PRINT_TYPE2 (2)

#define DEALY_1MS (1000)
#define DELAY_1S (1000 * DEALY_1MS)
#define DEALY_2S (2 * DELAY_1S)
#define DELAY_250MS (250 * DEALY_1MS) 

#define SEM_CTRL_V (1)
#define SEM_CTRL_P (-1)

typedef struct {
    unsigned int type;
    unsigned int *state;
} PrintThreadInfoHandle;

typedef struct {
    unsigned int type;
    unsigned int state;
} ShmInfoHandle;

int IPC_SemShmIdInit(int *semId, int *shmId);
int IPC_SemaphoreCtrl(int semId, int type);
int IPC_DestorySemShm(int semId, int shmId);
int ChangePrintState(int type, int state);

#endif

/ ******************************************* /
// interface.c
/*
** (C) Copyright 2023 Reil.kun All Rights Reserved.
** Description:
** Author:Reil.kun
** Date: 
** Modify Record:
*/	

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "interface.h"

int IPC_SemShmIdInit(int *semId, int *shmId)
{
    if (semId == NULL || shmId == NULL) {
        LOGE("semId or shmId is NULL\n");
        return -1;
    }
    key_t key = 0;
    key = ftok(KEY_PATHNAME, KEY_PROJECT_ID);
    if (key < 0) {
        LOGE("Get key failed. err:%s\n", strerror(errno));
        return -1;
    }
    LOGI("Get key successful. key:%#x\n", key);
    *semId = semget(key, SEMAPHORE_NUMS, IPC_CREAT | SHM_SEM_PERMISSION);
    if (*semId < 0) {
        LOGE("Get semId failed. err:%s\n", strerror(errno));
        return -1;       
    }
    *shmId = shmget(key, sizeof(ShmInfoHandle), IPC_CREAT | SHM_SEM_PERMISSION);
    if (*shmId < 0) {
        LOGE("Get shmId failed. err:%s\n", strerror(errno));
        return -1;       
    }
    LOGI("Get semId and shmId successful. semId:%#x, shmId:%#x\n", *semId, *shmId);
    return 0;
}

int IPC_DestorySemShm(int semId, int shmId)
{
    int ret = 0;
	ret = semctl(semId, 0, IPC_RMID);
    if (ret < 0) {
        LOGE("Destory sem failed. err:%s\n", strerror(errno));
    }
    ret = shmctl(shmId,IPC_RMID,NULL);
    if (ret < 0) {
        LOGE("Destory shm failed. err:%s\n", strerror(errno));
    }
    LOGI("call IPC_DestorySemShm successful.\n");
    return 0;
}

int IPC_SemaphoreCtrl(int semId, int type)
{
    if (type != SEM_CTRL_P && type != SEM_CTRL_V) {
        LOGE("type is failed.\n");
        return -1;
    }
    int ret = 0;
    struct sembuf semBuf;
    semBuf.sem_num = 0;
	semBuf.sem_op = type;
	semBuf.sem_flg = SEM_UNDO;
	ret = semop(semId, &semBuf, 1);
    if (ret < 0) {
		LOGE("call semop failed. semId:%d, type:%d\n", semId, type);
		return -1;
	}
	return 0;
}

int ChangePrintState(int type, int state)
{
    int semId;
    int shmId;
    int ret = 0;
    ShmInfoHandle *info = NULL;
    ret = IPC_SemShmIdInit(&semId, &shmId);
    if (ret != 0) {
        LOGE("call IPC_SamShaIdInit failed.");
        return -1;
    }
    info = (ShmInfoHandle *)shmat(shmId, NULL, 0);
    if (info == (void *)-1) {
        LOGE("Get shm Addr failed. err:%s", strerror(errno));
        return 0;
    }
    info->type = type;
    info->state = state;
    IPC_SemaphoreCtrl(semId, SEM_CTRL_V);
    LOGI("ChangePrintState successful. type:%d state:%d\n", type, state);
    return 0;
}

进程1代码

/*
** (C) Copyright 2023 Reil.kun All Rights Reserved.
** Description:
** Author:Reil.kun
** Date: 
** Modify Record:
*/	

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "interface.h"

unsigned int print0State;
unsigned int print1State;
unsigned int print2State;

PrintThreadInfoHandle g_printThreadInfo[3] = { \
    {PRINT_TYPE0, &print0State}, \
    {PRINT_TYPE1, &print1State}, \
    {PRINT_TYPE2, &print2State}, \
};

static void *PrintThreadFunc(void *arg)
{
    if (arg == NULL) {
        LOGE("arg is null, start print thread failed.\n");
        return (void *)-1;
    }
    PrintThreadInfoHandle *info = NULL;
    info = (PrintThreadInfoHandle *)arg;
    LOGI("Start PrintThreadFunc type:%d p_state:%p\n", info->type, info->state);
    while (1) {
        switch (*info->state) {
            case PRINT_A:
                LOGI("type:%d PRINT_A---\n", info->type);
                break;
            case PRINT_B:
                LOGI("type:%d PRINT_B---\n", info->type);
                break;
            case PRINT_A_B_2S:
                while (*info->state == PRINT_A_B_2S) {
                    LOGI("type:%d PRINT_A_B_2S---A---\n", info->type);
                    usleep(DEALY_2S);
                    LOGI("type:%d PRINT_A_B_2S---B---\n", info->type);
                    usleep(DEALY_2S);
                }
                break;
            case PRINT_A_B_250MS:
                while (*info->state == PRINT_A_B_250MS) {
                    LOGI("type:%d PRINT_A_B_250MS---A---\n", info->type);
                    usleep(DELAY_250MS);
                    LOGI("type:%d PRINT_A_B_250MS---B---\n", info->type);
                    usleep(DELAY_250MS);
                }
                break;
        default:
            break;
        }
        usleep(DELAY_1S);
    }
    return (void *)0;
}

int main(int argc, char *argv[])
{
    unsigned int i = 0;
    int semId;
    int shmId;
    int ret = 0;
    ShmInfoHandle *info = NULL;
    pthread_t printThread[3];
    ret = IPC_SemShmIdInit(&semId, &shmId);
    if (ret != 0) {
        LOGE("call IPC_SamShaIdInit failed.");
        return -1;
    }
    info = (ShmInfoHandle *)shmat(shmId, NULL, 0);
    if (info == (void *)-1) {
        LOGE("Get shm Addr failed. err:%s\n", strerror(errno));
        goto destory;
    }
    memset(info, 0, sizeof(ShmInfoHandle));
    for (i = 0; i < 3; i++) {
        ret = pthread_create(&printThread[i], NULL, PrintThreadFunc, (PrintThreadInfoHandle *)&g_printThreadInfo[i]);
        if (ret < 0) {
            LOGE("Create Thread failed. err:%s i:%d\n", strerror(errno), i);
            goto destory;
        }
    }
    while (1) {
        IPC_SemaphoreCtrl(semId, SEM_CTRL_P);
        *g_printThreadInfo[info->type].state = info->state;
        LOGI("PrintState Change successful. type:%d state:%d\n", info->type, *g_printThreadInfo[info->type].state);
    }
destory:
    IPC_DestorySemShm(semId, shmId);
    return -1;
}

进程2

/*
** (C) Copyright 2023 Reil.kun All Rights Reserved.
** Description:
** Author:Reil.kun
** Date: 
** Modify Record:
*/	

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "interface.h"

#define INPUT_PARAMETER_NUMS (3)
#define INPUT_PARAMETER_TYPE_PRINT_TYPE (1)
#define INPUT_PARAMETER_TYPE_PRINT_STATE (2)

int main(int argc, char *argv[])
{
    if (argc != INPUT_PARAMETER_NUMS) {
        LOGE("arg failed.[0.file 1.type 2.state]\n");
        return 0;
    }
    int type = atoi(argv[INPUT_PARAMETER_TYPE_PRINT_TYPE]);
    int state = atoi(argv[INPUT_PARAMETER_TYPE_PRINT_STATE]);
    ChangePrintState(type, state);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Reil.kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值