System V进程间通信--共享内存
来源:互联网 发布:delphi 数据库 编辑:程序博客网 时间:2024/05/16 19:22
一、共享内存IPC原理
共享内存进程间通信机制主要用于实现进程间大量数据的传输,共享内存是在内存中单独开辟的一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限、大小和最近访问时间。
数据结构定义如下:
struct shmid_ds { struct ipc_perm shm_perm; /* operation perms */ int shm_segsz; /* size of segment (bytes) */ __kernel_time_t shm_atime; /* last attach time */ __kernel_time_t shm_dtime; /* last detach time */ __kernel_time_t shm_ctime; /* last change time */ __kernel_ipc_pid_t shm_cpid; /* pid of creator */ __kernel_ipc_pid_t shm_lpid; /* pid of last operator */ unsigned short shm_nattch; /* no. of current attaches */ unsigned short shm_unused; /* compatibility */ void *shm_unused2; /* ditto - used by DIPC */ void *shm_unused3; /* unused */};
两个进程在使用此共享内存空间之前,需要在进程地址空间与共享内存空间之间建立联系,即将共享内存空间挂载到进程中。并且在使用共享内存进行数据的存取时,需要对空间进行同步操作,这个可以使用信号量机制完成。
系统对共享内存做了以下限制:
#define SHMMIN 1 /* min shared seg size (bytes) */#define SHMMNI 4096 /* max num of segs system wide */#define SHMMAX (ULONG_MAX - (1UL << 24)) /* max shared seg size (bytes) */#define SHMALL (ULONG_MAX - (1UL << 24)) /* max shm system wide (pages) */#define SHMSEG SHMMNI /* max shared segs per process */
二、共享内存的管理
1、创建共享内存
函数原型:
int shmget(key_t key, size_t size, int shmflg)
函数传入值:
key
0(IPC_PRIVATE):会建立新共享内存对象
大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值
size
大于0的整数:新建的共享内存大小,以字节为单位
0:只获取共享内存时指定为0
shmflg
0:取共享内存标识符,若不存在则函数会报错
IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符
IPC_CREAT|IPC_EXCL:如果内核中不存在键值 与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存则报错
函数返回值:
成功:返回共享内存的标识符
出错:-1,错误原因存于error中
2、共享内存控制
函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
函数传入值:
shmid
共享内存标识符
cmd
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
buf
共享内存管理结构体。具体说明参见共享内存内核结构定义部分
函数返回值
成功:0
出错:-1,错误原因存于error中
3、映射共享内存对象
函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg)
函数传入值:
shmid
共享内存标识符
shmaddr
指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflg
SHM_RDONLY:为只读模式,其他为读写模式
函数返回值
成功:附加好的共享内存地址
出错:-1,错误原因存于errno中
4、分离共享内存对象
函数原型:
int shmdt(const void *shmaddr)
函数传入值:
shmaddr:连接的共享内存的起始地址
函数返回值:
成功:0
出错:-1,错误原因存于error中
三、使用共享内存进行进程间通信的实例
1、发送端进程
/* *使用共享内存进行进程间的通信,并运用信号量机制实现同步 *此为信息的发送者 */#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<unistd.h>#include<string.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/sem.h>int main(int argc , char* argv[]){ int running = 1 ; int shid ; int semid ; int value ; void* sharem = NULL ; struct sembuf sem_b ; sem_b.sem_num = 0 ; sem_b.sem_flg = SEM_UNDO ; if((semid = semget((key_t)123456 , 1 , 0600 | IPC_CREAT)) == -1) //创建信号量(或读ID) { perror("semget") ; exit(EXIT_FAILURE) ; } if(semctl(semid , 0 , SETVAL , 0) == -1) //设置初始值为0 { printf("sem init error\n") ; if(semctl(semid , 0 , IPC_RMID , 0) != -1) //设置失败则进行删除 { perror("semctl") ; exit(EXIT_FAILURE) ; } exit(EXIT_FAILURE) ; } shid = shmget((key_t)654321 , (size_t)2048 , 0600 | IPC_CREAT) ; //创建共享内存(或读ID) if(shid == -1) { perror("shmget") ; exit(EXIT_FAILURE) ; } sharem = shmat(shid , NULL , 0) ; //挂载共享内存到当前进程 if(sharem == NULL) { perror("shmat") ; exit(EXIT_FAILURE) ; } while(running) { if(value = semctl(semid , 0 , GETVAL) == 0) //读取值为0则可以写 { printf("write data operate\n") ; printf("please input something :") ; scanf("%s" , sharem) ; sem_b.sem_op = 1 ; if(semop(semid , &sem_b , 1) == -1) //实行信号量的自加操作,允许读 { fprintf(stderr , "semaphore_p failure\n") ; exit(EXIT_FAILURE) ; } } if(strcmp(sharem , "end") == 0) { running-- ; } } shmdt(sharem) ; //解挂 return 0 ;}
2、接收端进程
/* *使用共享内存进行进程间的通信,并运用信号量机制实现同步 *此为信息的接收者 */#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<unistd.h>#include<string.h>#include<sys/ipc.h>#include<sys/shm.h>#include<sys/sem.h>int main(int argc , char* argv[]){ int running = 1 ; int shid ; int semid ; int value ; void* sharem = NULL ; struct sembuf sem_b ; sem_b.sem_num = 0 ; sem_b.sem_flg = SEM_UNDO ; if((semid = semget((key_t)123456 , 1 , 0600 | IPC_CREAT)) == -1) //创建信号量(或读ID) { perror("semget") ; exit(EXIT_FAILURE) ; } shid = shmget((key_t)654321 , (size_t)2048 , 0600 | IPC_CREAT) ; //创建共享内存(或读ID) if(shid == -1) { perror("shmget") ; exit(EXIT_FAILURE) ; } sharem = shmat(shid , NULL , 0) ; //挂载共享内存到当前进程 if(sharem == NULL) { perror("shmat") ; exit(EXIT_FAILURE) ; } while(running) { if(value = semctl(semid , 0 , GETVAL) == 1) //读取值为1则可以写 { printf("read data operate\n") ; sem_b.sem_op = -1 ; if(semop(semid , &sem_b , 1) == -1) //实行信号量的自减操作,允许写 { fprintf(stderr , "semaphore_p failure\n") ; exit(EXIT_FAILURE) ; } printf("%s\n" , sharem) ; } if(strcmp(sharem , "end") == 0) { running-- ; } } shmdt(sharem) ; //解挂 if(shmctl(shid , IPC_RMID , 0) != 0) //删除共享内存 { perror("shmctl") ; exit(EXIT_FAILURE) ; } if(semctl(semid , IPC_RMID , 0) != 0) //删除信号量 { perror("semctl") ; exit(EXIT_FAILURE) ; } return 0 ;}
3、我们可以查看运行结果
发送端:
接收端:
可以看到顺利通信(:
- System V进程间通信--共享内存
- linux进程间通信之共享内存(system v)
- Linux进程间通信之共享内存(system v)
- 进程间通信(9) - 共享内存(System V)
- linux进程间通信-----System V共享内存总结实例
- linux 进程间通信(system v 信号灯+system v 共享内存)实例
- 15章 进程间通信之共享内存区(Posix、System V共享内存)
- Linux 进程通信(System V) 第五节 ------>共享内存区
- Linux进程通信之System V共享内存
- Linux程序设计学习笔记----System V进程通信(共享内存)
- Linux 进程通信(System V)共享内存区
- 进程学习:进程间通信(system v IPC)2.共享内存
- linux进程间通信(system v信号灯+posix共享内存)实例
- 【九】 进程间通信——[System V IPC对象]共享内存(share memory)
- Linux C编程--进程间通信(IPC)5--System V IPC 机制3--共享内存
- Linux C编程--进程间通信(IPC)5--System V IPC 机制3--共享内存
- UNPv2:进程间通信(五) System V共享内存区
- Linux进程间通信(IPC)编程实践(七)共享内存的使用-System V共享内存(API)
- Android打包签名信息配置
- 一些宏的用处
- JavaScript HTML DOM
- 6.Map、Tuple、Zip实战解析
- Friends number NBUT
- System V进程间通信--共享内存
- StringBuffer
- Space在Android里的应用
- appframework实现Banner轮播图
- CentOS安装配置Nginx服务器
- A Star not a Tree?——poj2420 费马点退火算法(伪)
- Linux关闭防火墙
- 救基友记2
- Error running app: This version of Android Studio is incompatible with the Gradle Plugin used. Try