Linux进程间通信之共享内存
linux_shm.h文件
#ifndef LINUX_SHM__H_H
#define LINUX_SHM__H_H
#include <sys/types.h>
#include <unistd.h>
int create_shm(char *name, unsigned int size);
char* map_shm(int shmid);
void unmap_shm(char *shmaddr);
void close_shm(int shmid);
#endif
linux_shm.cpp文件
#include "linux_shm.h"
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define PROJ_ID 0x03
int create_shm(char *name, unsigned int size)
{
int shmid;
key_t shm_key;
if ((shm_key = ftok(name, PROJ_ID)) == (key_t) -1) {
perror(name);
return -1;
}
shmid = shmget(shm_key, size, 0666|IPC_CREAT);
if(shmid < 0 ) {
perror(name);
if (errno != EEXIST){
return -1;
}else {
//shm already exists
if((shmid = shmget(shm_key, size, SHM_R | SHM_W)) < 0) {
perror(name);
return -1;
}
}
}
return shmid;
}
char* map_shm(int shmid)
{
char* pt;
pt = (char *)shmat((int)shmid, 0, SHM_RND);
if(pt == NULL) {
perror("map error");
}
return pt;
}
void unmap_shm(char *shmaddr)
{
shmdt(shmaddr);
return ;
}
void close_shm(int shmid)
{
struct shmid_ds buf;
shmctl((int)shmid, IPC_RMID, &buf);
return ;
}
mgr_shm.h文件
#ifndef MGR_SHM__H_H
#define MGR_SHM__H_H
#include "linux_shm.h"
#define SHM_KEY "shm.key"
#define REG_READ 0x01 //读操作命令字
#define REG_WRITE 0x02 //写操作命令字
#define DATA_INVALID 0x00 //数据无效
#define DATA_VALID 0x01 //数据有效
//读寄存器的操作请求的消息结构体
typedef struct {
unsigned char valid; //数据是否可读标识,0:不可读 1:可读
unsigned char csid; //芯片片选id
unsigned char cmd; //读写操作命令字
unsigned short regaddr; //寄存器地址
} msg_rd_req;
//读寄存器的操作应答消息结构体
typedef struct {
unsigned char valid; //数据是否可读标识,0:不可读 1:可读
unsigned char csid; //芯片片选id
unsigned short regaddr; //寄存器地址
unsigned char value; //寄存器的值
} msg_rd_resp;
//写寄存器的操作请求的消息结构体
typedef struct {
unsigned char valid; //数据是否可读标识,0:不可读 1:可读
unsigned char csid; //芯片片选id
unsigned char cmd; //读写操作命令字
unsigned short regaddr; //寄存器地址
unsigned char value; //寄存器的值
} msg_wr_req;
//写寄存器的操作应答消息结构体
typedef struct {
unsigned char valid; //数据是否可读标识,0:不可读 1:可读
unsigned char csid; //芯片片选id
unsigned short regaddr; //寄存器地址
unsigned char status; //写入寄存器地址中的值成功与否,0:成功 -1:失败
} msg_wr_resp;
typedef struct {
msg_wr_req wr_req;
msg_wr_resp wr_resp;
msg_rd_req rd_req;
msg_rd_resp rd_resp;
} msg;
int attach_shm(const char* keypath);
void detach_shm(int shmid);
msg* get_msg();
void init_msg(msg* ptr);
void print_msg(const msg* ptr);
#endif
mgr_shm.cpp文件
#include "mgr_shm.h"
#include "string.h"
#include <stdio.h>
static msg* pMsg = NULL;
static void set_msg(msg* ptr)
{
pMsg = ptr;
}
int attach_shm(const char* keypath)
{
int chshm;
char cFileName [256];
sprintf(cFileName,"%s/%s",keypath,SHM_KEY);
chshm = create_shm((char *)cFileName,sizeof(msg));
pMsg = (msg*)map_shm(chshm);
if (pMsg == NULL )
{
return -1;
}
return chshm ;
}
void detach_shm(int shmid)
{
unmap_shm((char*)pMsg);
close_shm(shmid);
}
msg* get_msg()
{
return pMsg;
}
void init_msg(msg* ptr)
{
if(ptr == NULL)
return ;
ptr->rd_req.valid = 0;
ptr->rd_req.csid = 0;
ptr->rd_req.cmd = 0;
ptr->rd_req.regaddr = 0;
ptr->wr_req.valid = 0;
ptr->wr_req.csid = 0;
ptr->wr_req.cmd = 0;
ptr->wr_req.regaddr = 0;
ptr->wr_req.value = 0;
ptr->rd_resp.valid = 0;
ptr->rd_resp.csid = 0;
ptr->rd_resp.regaddr = 0;
ptr->rd_resp.value = 0;
ptr->wr_resp.valid = 0;
ptr->wr_resp.csid = 0;
ptr->wr_resp.regaddr = 0;
ptr->wr_resp.status = 0;
}
void print_msg(const msg* ptr)
{
if(ptr == NULL)
return ;
printf("ptr->rd_req.valid=%d\n",ptr->rd_req.valid);
printf("ptr->rd_req.csid=%d\n",ptr->rd_req.csid);
printf("ptr->rd_req.cmd=%d\n",ptr->rd_req.cmd);
printf("ptr->rd_req.regaddr=%d\n",ptr->rd_req.regaddr);
printf("ptr->rd_resp.valid=%d\n",ptr->rd_resp.valid);
printf("ptr->rd_resp.csid=%d\n",ptr->rd_resp.csid);
printf("ptr->rd_resp.regaddr=%d\n",ptr->rd_resp.regaddr);
printf("ptr->rd_resp.value=%d\n",ptr->rd_resp.value);
printf("ptr->wr_req.valid=%d\n",ptr->wr_req.valid);
printf("ptr->wr_req.csid=%d\n",ptr->wr_req.csid);
printf("ptr->wr_req.cmd=%d\n",ptr->wr_req.cmd);
printf("ptr->wr_req.regaddr=%d\n",ptr->wr_req.regaddr);
printf("ptr->wr_req.value=%d\n",ptr->wr_req.value);
printf("ptr->wr_resp.valid=%d\n",ptr->wr_resp.valid);
printf("ptr->wr_resp.csid=%d\n",ptr->wr_resp.csid);
printf("ptr->wr_resp.regaddr=%d\n",ptr->wr_resp.regaddr);
printf("ptr->wr_resp.status=%d\n",ptr->wr_resp.status);
}
server_shm.cpp文件
#include <stdio.h>
#include <string>
#include "mgr_shm.h"
#include "linux_shm.h"
int main(int argc,char** argv)
{
int shmid = attach_shm("/home/banting/test/shm_demo");
msg* ptr = get_msg();
while(1)
{
if(ptr->wr_req.valid == DATA_VALID)
{
ptr->wr_resp.valid = DATA_INVALID;
ptr->wr_resp.csid = ptr->wr_req.csid;
ptr->wr_resp.regaddr = ptr->wr_req.regaddr;
ptr->wr_resp.status = 0x00;
ptr->wr_resp.valid = DATA_VALID;
}
if(ptr->rd_req.valid == DATA_VALID)
{
ptr->rd_resp.valid = DATA_INVALID;
ptr->rd_resp.csid = ptr->rd_req.csid;
ptr->rd_resp.regaddr = ptr->rd_req.regaddr;
ptr->rd_resp.value = 0x40;
ptr->rd_resp.valid = DATA_VALID;
}
sleep(2);
}
detach_shm(shmid);
ptr = NULL;
return 0;
}
client_shm.cpp文件
#include <stdio.h>
#include <string.h>
#include <string>
#include "mgr_shm.h"
#include "linux_shm.h"
static void write_reg(int csid , unsigned short regaddr, unsigned char value)
{
int shmid = attach_shm("/home/banting/test/shm_demo");
msg* ptr = get_msg();
init_msg(ptr);
ptr->wr_req.csid = csid;
ptr->wr_req.cmd = REG_WRITE;
ptr->wr_req.regaddr = regaddr;
ptr->wr_req.value = value;
ptr->wr_req.valid = DATA_VALID;
while(ptr->wr_resp.valid != DATA_VALID)
{
sleep(1);
}
print_msg(ptr);
sleep(1);
ptr->wr_req.valid = DATA_INVALID;
//客户端不需要去释放内存,由服务端去释放
//否则客户多次重连,会出多个共享内存情况,两个进程无法通信
//detach_shm(shmid);
return ;
}
static void read_reg(int csid , unsigned short regaddr)
{
int shmid = attach_shm("/home/banting/test/shm_demo");
msg* ptr = get_msg();
init_msg(ptr);
ptr->rd_req.csid = csid;
ptr->rd_req.cmd = REG_READ;
ptr->rd_req.regaddr = regaddr;
ptr->rd_req.valid = DATA_VALID;
while(ptr->rd_resp.valid != DATA_VALID)
{
sleep(1);
}
print_msg(ptr);
sleep(1);
ptr->rd_req.valid = DATA_INVALID;
//客户端不需要去释放内存,由服务端去释放
//否则客户多次重连,会出多个共享内存情况,两个进程无法通信
//detach_shm(shmid);
return;
}
static void trim(std::string& src_string)
{
src_string.erase(0,src_string.find_first_not_of(" \r\n\t\v\f"));
src_string.erase(src_string.find_last_not_of(" \r\n\t\v\f") +1);
}
int main(int argc, char** argv)
{
if((argc == 5) && (strcmp(argv[1],"write_reg") == 0))
{
std::string csid_str(argv[2]);
trim(csid_str);
unsigned char csid = std::stoi(csid_str);
std::string regaddr_str(argv[3]);
trim(regaddr_str);
regaddr_str = regaddr_str.substr(2);
unsigned short regaddr = std::stoi(regaddr_str,nullptr,16);
std::string regvalue_str(argv[4]);
trim(regvalue_str);
unsigned char regvalue = std::stoi(regvalue_str);
write_reg(csid, regaddr,regvalue);
}
else if((argc == 4) && (strcmp(argv[1],"read_reg") == 0))
{
std::string csid_str(argv[2]);
trim(csid_str);
unsigned char csid = std::stoi(csid_str);
std::string regaddr_str(argv[3]);
trim(regaddr_str);
regaddr_str = regaddr_str.substr(2);
unsigned short regaddr = std::stoi(regaddr_str,nullptr,16);
read_reg(csid, regaddr);
}
else
{
return -1;
}
return 0;
}
编译
[banting@localhost shm_demo]g++ -g -std=c++11 linux_shm.cpp mgr_shm.cpp client_shm.cpp -o client_shm
[banting@localhost shm_demo]g++ -g -std=c++11 linux_shm.cpp mgr_shm.cpp server_shm.cpp -o server_shm
[banting@localhost shm_demo] ls -tlr
-rw-rw-r-- banting banting 0 Jul 29 16:19 shm.key
-rw-rw-r-- banting banting 944 Jul 29 16:19 linux_shm.cpp
-rw-rw-r-- banting banting 2096 Jul 29 16:19 client_shm.cpp
-rw-rw-r-- banting banting 242 Jul 29 16:19 mgr_shm.cpp
-rw-rw-r-- banting banting 802 Jul 29 16:19 linux_shm.h
-rw-rw-r-- banting banting 1775 Jul 29 16:19 server_shm.cpp
-rw-rw-r-- banting banting 2518 Jul 29 16:19 mgr_shm.h
-rw-rw-r-- banting banting 19304 Jul 29 16:19 client_shm
-rw-rw-r-- banting banting 13648 Jul 29 16:19 server_shm
运行
[banting@localhost shm_demo] ./server_shm
[banting@localhost shm_demo] ./client_shm write_reg 1 0x301 9
ptr->rd_req.valid = 0;
ptr->rd_req.csid = 0;
ptr->rd_req.cmd = 0;
ptr->rd_req.regaddr = 0;
ptr->rd_resp.valid = 0;
ptr->rd_resp.csid = 0;
ptr->rd_resp.regaddr = 0;
ptr->rd_resp.value = 0;
ptr->wr_req.valid = 1;
ptr->wr_req.csid = 1;
ptr->wr_req.cmd = 2;
ptr->wr_req.regaddr = 769;
ptr->wr_req.value = 9;
ptr->wr_resp.valid = 1;
ptr->wr_resp.csid = 1;
ptr->wr_resp.regaddr = 769;
ptr->wr_resp.status = 0;
[banting@localhost shm_demo]
查看哪些进程attach共享内存
#方式一:通过 lsof |grep shmid 这种方式不适合shmid为0的情况查看
[banting@localhost shm_demo]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00123456 0 root 664 5497632 0
0x65000006 32769 root 664 4096 0
0x03003f5a 229379 banting 666 26 1
[banting@localhost shm_demo]# lsof |grep 229379
server_sh 12339 banting DEL REG 0,4 229379 /SYSV03003f5a
#方式二:通过lsof | grep key 这种方式更通用
[banting@localhost shm_demo]# ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00123456 0 root 664 5497632 0
0x65000006 32769 root 664 4096 0
0x03003f5a 229379 banting 666 26 1
[banting@localhost shm_demo]# lsof | grep 03003f5a
server_sh 12339 banting DEL REG 0,4 229379 /SYSV03003f5a
[banting@localhost shm_demo]# ps -ef |grep 12339
root 12339 12320 0 08:20 ? 00:00:02 ./server_shm
root 16142 7475 0 08:51 pts/5 00:00:00 grep --color=auto 12339
root@gb:/home/gb/USB-Device-Mgr/USB-Device-Mgr/bin#
参考文献:
【Linux 系统】进程间通信(共享内存、消息队列、信号量)
在linux下查看有哪些操作系统进程正在使用某一个共享内存段
1251

被折叠的 条评论
为什么被折叠?



