共享内存常用函数介绍:
int shmget(key_t key,size_t size,int shmflg);
函数说明:得到一个共享内存标识符shmid
使用头文件:#include <sys/ipc.h> #include <sys/shm.h>
参数:
key:共享内存段名字,可通过fork函数生成,使用如:ftok("./", 66);
size:共享内存大小,以字节为单位;
shmflg:
IPC_CREAT: 如果共享内存不存在,则创建一个共享内存,否则打开操作;
IPC_EXCL:只有在共享内存不存在的时候,新的共享内存才建立,否则就产生错误。
例如:
key = ftok("/mnt/hgfs/Homework",87);
shmid = shmget(key, sizeof(struct shared_use_st), IPC_CREAT|0666);
void *shmat(int shmid,const void *shmaddr,int shmflg);
函数说明:映射共享内存,将共享内存区对象映射到调用进程的地址空间,返回的是一个指针,指向共享内存第一个字节
使用头文件:#include <sys/types.h> #include <sys/shm.h>
参数:
shmid:共享内存标识符
shmaddr: 指定共享内存出现在进程内存地址的什么位置,通常指定为NULL,让内核自己选择一个合适的地址位置
shmflg:通常为0
例如:
char *shm_buf = NULL; //虚拟地址
shm_buf = shmat(shmid, (void *)0, 0);
int shmdt(const void *shmaddr);
函数说明:将共享内存与当前进程脱离
使用头文件:#include <sys/types.h> #include <sys/shm.h>
参数:shmddr 连接共享内存的起始地址
例如:
if(-1 == shmdt(shm_buf))
int shmctl(int shmid,int cmd, struct shmid_ds* buf);
函数说明:控制共享内存块
使用头文件:#include <sys/types.h> #Include <sys/shm.h>
参数:
shmid:共享内存标识符
cmd:
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构赋值到buf所指向的buf中
IPC_SET:改变共享内存的状态,把buf所指向的shmid_ds结构中的uid、gid、mode赋值到共享内存的shmid_ds结构内
IPC_RMID:删除这块共享内存
buf:共享内存管理结构体,一般为NULLs
例如:
if(-1 == shmctl(shmid, IPC_RMID, NULL))
使用共享内存实例:
功能:linux下创建工程,至少包括三个以上目录,可以实现单独编译,全编译,程序1从文件输入指令流,并将程序指令流传输到程序2, 程序2在屏幕上显示指令的操作结果,程序3可以控制程序1,2的暂停和退出。
说明:
1.txt中存放字符串命令;
write.c负责读取1.txt中的命令并向共享内存中写入数据;
read.c负责读取共享内存中的数据并向共享内存中写入自身设备号;
control.c负责读取共享内存中所有的信息,并实现对read.c和write.c状态的控制
D.h:存放共享内存数据结构体
write.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "D.h"
int main(void)
{
int fd = -1;
char buf[128]={0}; //用来存储从文件获取的命令字符串
int shmid;
char *shm_buf = NULL; //虚拟地址
struct shared_use_st *shared = NULL;
key_t key;
//从文件中读取指令,存放在buf中 pwd存放在1.txt中
fd = open("/mnt/hgfs/Homework/1.txt",O_RDWR);
if(-1 == fd)
{
perror("open failed!");
exit(1);
}
read(fd,buf,127);//获取指令并存放在buf中
printf("Get_Command:%s",buf);
//创建一个共享内存,返回一个id
key = ftok("/mnt/hgfs/Homework",87);
shmid = shmget(key, sizeof(struct shared_use_st), IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget failed!");
exit(2);
}
//映射共享内存,得到虚拟地址
shm_buf = shmat(shmid, (void *)0, 0);
if((void *)-1 == shm_buf)
{
perror("shmat failed!");
exit(3);
}
//写共享内存
shared = (struct shared_use_st *)shm_buf;
strcpy(shared->text,buf);
shared->id1 = getpid();
printf("share_data:%s",shared->text);
printf("Write_id1:%d\n",shared->id1);
//解除映射
if(-1 == shmdt(shm_buf))
{
perror("shmdt failed!");
exit(4);
}
//销毁共享内存
/* if(-1 == shmctl(shmid, IPC_RMID, NULL))
{
perror("shmctl failed!");
exit(5);
}
printf("destory success!\n");
*/
close(fd);
while(1);
return 0;
}
read.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "D.h"
int main(void)
{
int shmid;
char *shm_buf = NULL;
struct shared_use_st *shared;
key_t key;
pid_t pid;
//生成一个key
key = ftok("/mnt/hgfs/Homework",87);
//获取共享内存,返回一个id
shmid = shmget(key, sizeof(struct shared_use_st), IPC_CREAT|0666);
if(-1 == shmid)
{
perror("shmget failed!");
exit(6);
}
//映射共享内存,得到虚拟地址
shm_buf = shmat(shmid, (void *)0, 0);
if((void *)-1 == shm_buf)
{
perror("shmat failed!");
exit(7);
}
//读共享内存
pid = getpid();
shared = (struct shared_use_st *)shm_buf;
printf("Share_Read_Data:%s",shared->text);
printf("Write_id1:%d\n",shared->id1);
shared->id2 = pid;
printf("Read_id2:%d\n",pid);
printf("The Path in the next:\n");
system(shared->text);//通过system函数来执行text中存放的字符串命令
//解除映射
if(-1 == shmdt(shm_buf))
{
perror("shmdt failed!");
exit(8);
}
while(1);
return 0;
}
control.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "D.h"
int main(void)
{
int shmid;
char *shm_buf = NULL;
struct shared_use_st *shared;//申请结构体指针变量
key_t key;
pid_t pid;
int Read_id,Write_id;
int num;
char buffer1[200],buffer2[200],buffer3[200],buffer4[200],buffer5[200],buffer6[200];//进行格式转换存储
//生成一个key
key = ftok("/mnt/hgfs/Homework",87);
//获取共享内存,返回一个id
shmid = shmget(key, sizeof(struct shared_use_st), IPC_CREAT);
if(-1 == shmid)
{
perror("shmget failed!");
exit(6);
}
//映射共享内存,得到虚拟地址
shm_buf = shmat(shmid, (void *)0, 0);
if((void *)-1 == shm_buf)
{
perror("shmat failed!");
exit(7);
}
//读共享内存
pid = getpid();
shared = (struct shared_use_st *)shm_buf;
printf("Share_Read_Data:%s",shared->text);
printf("The Path in the next:\n");
system(shared->text);//通过system函数来执行text中存放的字符串命令
printf("Write_id1:%d\n",shared->id1);
printf("Read_id2:%d\n",shared->id2);
printf("Own_id3:%d\n",pid);
Write_id = shared->id1;
Read_id = shared->id2;
//解除映射
if(-1 == shmdt(shm_buf))
{
perror("shmdt failed!");
exit(8);
}
/****************操作进程*******************/
//字符转换
sprintf(buffer1,"kill -STOP %d",Write_id);
sprintf(buffer2,"kill -STOP %d",Read_id);
sprintf(buffer3,"kill -CONT %d",Write_id);
sprintf(buffer4,"kill -CONT %d",Read_id);
sprintf(buffer5,"kill -KILL %d",Write_id);
sprintf(buffer6,"kill -KILL %d",Read_id);
printf("please input a num!\n");
scanf("%d",&num);
switch(num)
{
case 1:
system(buffer1);
printf("stop Write success!\n");
break;
case 2:
system(buffer2);
printf("stop Read success!\n");
break;
case 3:
system(buffer3);
printf("cont Write success!\n");
break;
case 4:
system(buffer4);
printf("cont Read success!\n");
break;
case 5:
system(buffer5);
printf("kill Write success!\n");
break;
case 6:
system (buffer6);
printf("kill Read success!\n");
break;
default:
printf("input a error number!\n");
}
return 0;
}
Makefile:
#! /bin/bash
all:mk1 mk2 mk3
$(MAKE) -C ./Read
$(MAKE) -C ./Write
$(MAKE) -C ./Control
mk1:
$(MAKE) -C ./Write
mk2:
$(MAKE) -C ./Read
mk3:
$(MAKE) -C ./Control
clean:
rm -rf test
rm -rf ./Read/*.o
rm -rf ./Write/*.o
rm -rf ./Control/*.o
D.h
#pragma once //在头文件中加入这条指令能够被编译一次
#define TEXT_SZ 1024
struct shared_use_st
{
int id1;//存放程序1id
int id2;//存放程序2id
char text[TEXT_SZ]; //记录写入和读取的文本
};