IPC——共享内存与信号灯的基本函数整理

来源:互联网 发布:类似snapchat特效软件 编辑:程序博客网 时间:2024/05/16 01:20
IPC(Inter-Process Communication,进程间通信)
共享内存与信号灯


#include <sys/types.h>
#include <sys/ipc.h>


key_t ftok(const char *pathname,int proj_id)  
常用方法:key_t key = ftok(".".'a');
if(-1 == key){
perror("ftok");
exit(-1);



使用key打开或创建IPC通道(msg_get,shm_get,sem_get)


1、共享内存(key、shmid、void *(创建共享内存的首地址))
最为高效的进程间通信

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>


int shmget(key_t,int size,int shmflg) 
常用方法: shmid = shmget(key,SIZE,IPC_CREAT|0666);
if(-1 == shmid){
perror("shmget");
exit(-1);
}
size 为创建内存的大小;
返回值shmid(共享内存段的标识符)


void *shmat(int shmid,const void *shmaddr,int shmflg) 
常用方法:char *shmaddr = shmat(shmid,NULL,0);
if(-1 == shmid){
perror("shmat");
exit(-1);
}
shmaddr:将共享内存映射到指定的地址(NULL,表示由系统自动分配)
shmflg:SHM_RDONLY(共享内存只读)  0(共享内存可读写)
成功:映射后的地址
失败:-1

int shmdt(const void  *shmdt) 销毁共享内存
常用方法:int shmdd = shmdt(shmaddr);
if(-1 == shmdd){
perror("shmdt");
exit(-1);
}


2、信号灯(system V,由内核维护)
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>


int semget(key_t key,int nsems,int semflg)
常用方法:int semid = semget(key,num,IPC_CREAT|0666);
if(-1 == semid){
perror("semget");
exit(-1);
}
返回值:如果成功,则返回信号量集的IPC标识符。如果失败,则返回-1:
errno = EACCESS(没有权限)
EEXIST(信号量集已经存在,无法创建)
EIDRM(信号量集已经删除)
ENOENT(信号量集不存在,同时没有使用IPC_CREAT)
ENOMEM(没有足够的内存创建新的信号量集)
ENOSPC(超出限制)
int open_semophore_set(key_t key ,int numsems){
if(!numsems){
printf("numsems's value should larger than 0 ");
return -1;
}
int sid;
sid = semget(key,numsems,IPC_CREAT|0666);
if(-1 == sid){
perror("semget");
exit(-1);
}
return sid;
}
int semop(int semid,struct sembuf *sops,size_t nops)
struct sembuf{
  unsigned short sem_num;  /* semaphore number 将要处理的信号量在信号灯集的编号,从0开始*/
           short          sem_op;   /* semaphore operation:-1 执行P操作;+1 V操作;
  0 暂时阻塞直到信号量的值变为0*/
           short          sem_flg;  /* operation flags:IPC_NOWAIT:【对信号的操作条件不能满足时semop()不会阻塞,并立即返回,同时设定错误信息。】
                                           IPC_UNDO:【程序结束时 ( 不论正常或不正常 ) , 保证信号值会被重设为 semop() 调用前的值。】
                                 这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁, 造成该资源永远锁定。 */


}
NOPS:信号操作结构的数量,恒大于或等于 1
返回值:成功(0)出错(-1)
常用方法:
1、P操作
int sem_p(int semid,int index){

 struct sembuf buf;
 buf.sem_num = index;
 buf.sem_op = -1;
 buf.sem_flg = IPC_NOWAIT/0;
 
if(-1 == semop(semid,&buf,1)){
perror("semop");
exit(-1);
}
return 0;
}
2、V操作
int sem_v(int semid,int index){

struct sembuf buf = {index,+1,IPC_NOWAIT};

if(-1 == semop(semid,&buf,1)){
perror("semop");
exit(-1);

}  
 
int semctl(int semid,int semnum,int cwd,...../* union semun arg */)
功能描述: 
在指定的信号集或信号集内的某个信号上执行控制操作;

semid: 信号集的标识符,即是信号表的索引。
semnum:信号集的索引,用来存取信号集内的某个信号。
cmd:   需要执行的命令,有效值有
IPC_STAT //将与semid关联的内核数据结构拷贝到由arg.buf指针指向的内存区。
IPC_SET //将由arg.buf指针指向的semid_ds的一些成员写入相关联的内核数据结构, 同时更新它的sem_ctime成员。
IPC_RMID //立即删除信号集,唤醒所有被阻塞的进程。(常用)
.....
GETVAL //根据semnum返回信号的值。(常用)
SETVAL        //根据semnum设定信号的值。 (常用)

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };  

返回值:
成功执行时,根据不同的命令返回不同的非负值:

GETNCNT //返回semncnt的值
GETPID  //返回sempid的值
GETVAL  //返回semval的值//重点学习
GETZCNT //返回semzcnt的值
IPC_INFO //返回内核内部关于信号集信息的最大可用入口索引 
SEM_INFO //如同IPC_INFO.
SEM_STAT //返回信号集标识
剩下的命令返回0。

失败:-1


0 0