Linux IPC 信号量

本文详细介绍了一种基于IPC(Inter-Process Communication)的信号量实现方法,通过C++类封装了信号量的创建、获取、释放及删除操作。通过具体代码示例,展示了如何在多进程中使用信号量进行资源同步,确保了并发环境下资源访问的安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概念原理

ipc信号原理

2. Semphore.h

#ifndef SEMPHORE_H
#define SEMPHORE_H

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include "Typedef.h"

class CSem
{
private:
	key_t m_key;
	int m_semID;

public:
	CSem(){};
	~CSem(){};
	
	int InitSem(BYTE bBankNo, BYTE bSectNo, BYTE bIdx, int iSemVal);
	
	void P();
	
	void V();
	
	void DelSem();
	
	int GetSemID(){return m_semID;};
};
	

#endif //SEMPHORE_H

3. Semphore.cpp

#include<sys/stat.h>
#include "Semphore.h"


//描述:初始化信号量
//参数:@bBankNo BANK索引号
//		@bSectNo SECT索引号
//		@bIdx 对应索引
//		@iSemVal 信号量值,默认为1
//返回:失败小于0,反之成功
int CSem::InitSem(BYTE bBankNo, BYTE bSectNo, BYTE bIdx, int iSemVal)
{
	m_key = (bBankNo<<16) | (bSectNo<<8) | bIdx;
	m_key += 1;
	
    if((m_semID=semget(m_key, 1, IPC_CREAT)) < 0)
    {
		if ((m_semID=semget(m_key, 1, IPC_CREAT|IPC_EXCL|0666)) < 0)
		{
			printf("InitSem: semget error!\n");
			exit(1);
		}
    }
	
	if (access("/tmp/InitSemFlg", F_OK) != 0) //处理多个进程各自初始化不统一
	{
		system("touch /tmp/InitSemFlg");
		semctl(m_semID, 0, SETVAL, iSemVal); //只能初始化一次
		printf("touch /tmp/InitSemFlg\n");
	}
	
	
	printf("m_key=0x%08x.\n", m_key);
	
	return m_semID;
}

//描述:获取信号量
void CSem::P()
{
    struct sembuf op;
	
    memset(&op, 0, sizeof(op));
    op.sem_num = 0;
    op.sem_op = -1;
    op.sem_flg = SEM_UNDO;
    semop(m_semID, &op, 1);
}

//描述:释放信号量
void CSem::V()
{
    struct sembuf op;
	
    memset(&op, 0, sizeof(op));
    op.sem_num = 0;
    op.sem_op = 1;
    op.sem_flg = SEM_UNDO;
    semop(m_semID, &op, 1);
}

void CSem::DelSem()
{
	semctl(m_semID, 0, IPC_RMID);
}

4. main()测试函数

#include<sys/stat.h>
#include "Semphore.h"

int main(int argc, char *argv[])
{
	int iThrdNo;
	
	if (argc != 2)
	{
		printf("main: argc must be equal to 2.\n");
		exit(-1);
	}
	iThrdNo = atoi(argv[1]);
	
	CSem *pCSem;
	
	pCSem = new CSem();
	if (pCSem == NULL)
	{
		printf("pCSem == NULL.\n");
		exit(-1);
	}
	pCSem->InitSem(1, 1, 0, 1);
	
	if (iThrdNo == 1)
	{
		printf("before getval: %d\n", semctl(pCSem->GetSemID(), 0, GETVAL));
		pCSem->P();
		printf("ThrdNo=%d, P.\n", iThrdNo);
		while (getchar() == 'c')
			break;
		pCSem->V();
		printf("ThrdNo=%d, V.\n", iThrdNo);
	}
	else
	{
		printf("before getval: %d\n", semctl(pCSem->GetSemID(), 0, GETVAL));
		pCSem->P();
		printf("ThrdNo=%d, P.\n", iThrdNo);
		pCSem->V();
		printf("ThrdNo=%d, V.\n", iThrdNo);
	}
}

5. 交叉编译

root@ubuntu:/data/# arm-linux-gnueabi-g++ -o Semphore  Semphore.cpp -ldl -lrt

6. 测试运行(同步运行)

6.1 运行1号进程

root@nxbb:/mnt/# ./Semphore 1
touch /tmp/InitSemFlg
m_key=0x00010101.
before getval: 1
ThrdNo=1, P.
c
ThrdNo=1, V.

6.2 运行2号进程

root@nxbb:/mnt# ./Semphore 2
m_key=0x00010101.
before getval: 0
iThrdNo=2, P.
iThrdNo=2, V.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值