现在的位置: 首页 > 综合 > 正文

IPC通信

2012年05月28日 ⁄ 综合 ⁄ 共 5792字 ⁄ 字号 评论关闭
函数:
#include<sys/sem.h>
int semctl(int sem_id, int sem_num, int cmd, ...);
int semget(key_t, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
struct ipc_perm{
  __key_t __key;
  __uid_t uid; /**owner**/
  __gid_t gid;
  __uid_t cid;  /**creater**/
  __gid_t cid;
  unsigned short mode;
  unsigned short seq;
};
创建IPC标识符
:key_t
<sys/types.h>
<sys/ipc.h>
key_t ftok(const char * pathname, int proj_id);
-1出错。错误信息:
EACCES无权限进入目录
ELOOP 解析path存在循环
ENAMETOOLONG pathname长度超过PATH_MAX 或某目录长度超过NAME_MAX
ENOENT: pathname 某目录为空
ENODIR :含非目录部分
=====================================================================
消息队列
创建消息队列
<sys/msg.h>
int msgget(key_t key, intflag);
调用示例
---------------------------------------------------------------------
参数key               参数msgflg          调用结果            errno
---------------------------------------------------------------------
IPC_PRIVATE            无要求               成功              无
----------------------------------------------------------------------
系统中不存在相同key队列  IPC_CREAT|权限制   成功              无
----------------------------------------------------------------------
系统中存在相同key队列 IPC_CREAT|IPC_EXCEL|权限制  失败        EEXIST
----------------------------------------------------------------------
系统中存在相同key队列  IPC_CREAT|权限制   成功                 无
-----------------------------------------------------------------------
错误信息
EACCESS: 存在相同队列,调用进程无权限访问
ENOENT:不存在与key对应的消息队列,参数没有设置IPC_CREAT
ENIMEM:无内存
ENOSPC:超出最大队列数MSGMNB
//////////////////////////////////////////
消息队列中的基本结构
struct msqid_ds{
struct ipc_perm msg_perm;
time_t msg_stime;//最后调用msgsnd time
time_t msg_rtime;//最后调用msgrcv time
time_t msg_ctime;//改变
unsigned long  __msg_cbytes;//消息队列大小
msgqnum_t msg_qnum;//消息数目
msglen_t msg_qbytes;//消息队列最大比特数
pid_t msg_lspid;//最后调用msgsnd pid
pid_t msg_lrpid;//最后调用msgrcv pid
};
struct msg{
struct msg *msg_next;
long msg_type;类型
ushort msg_ts;长度
short msg_sport;指向消息队列内容指针
};
消息
int msgctl(int msqid, int cmd, struct msqid_ds *buf)
cmd:
IPC_STAT :读取
IPC_SET:
IPC_RMID:移除消息队列并唤醒等待进程
IPC_INFO返回系统级的消息队列限制,结果保存在buf中
struct msginfo{
int msgpool;//占用缓存大小,未使用
int msgmap;//未使用
int msgmax;//单挑消息最大长度
int msgmnb;//最大写入字节数,用于初始化msg_qbytes
int msgmin;//消息条数
int msgssz//段大小未使用
int msgtql;//所有消息可容纳消息数,未使用
unsigned short msgseg;//最大消息段大小未使用
}
MSG_INFO:
返回包括msgpool消息队列数 ,msgmap 所有消息队列消息数,msgtql总字节数
的msginfo
MSG_STAT:msqid 为内核的消息队列信息
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgp 为指向msgbuf指针,struct msgbuf{
   long mtype;
   char mtext[l];
   }
msgflg :0 或IPC_NOWAIT
成功调用后将更新msqid_ds结构的:
msg_lspid :调用进程的进程号
msg_qnum: +1
msg_stime: 当前时间
错误信息:
EACCESS :调用进程无权限向队列发送
EAGAIN: 消息队列达到最大信息量,同时msgflg使用了IPC_NOWAIT
EFAULT: msgp 指向非法地址
ERIDRM:消息队列被删除
EINTR:被信号中断
EINVAL:非法的msqid,mtype为负或msgsz不合法
ENOMEM:
msgrcv(int msqid, void * msgp, long msgtyp, int msgflg);
msgflg:IPC_NOWAIT 没有满足的消息立即返回,errno 为ENOMEG
IPC_EXCEPT 与msgtyp配合使用,返回队列第一个类型不为msgtyp的消息
IPC_NOERROR 如果队列满足条件的消息内容大于所请求的msgsz,将截断
成功后更新msqid_ds:
msg_lrpid :调用进程
msg_qnum: -1
msg_rtime:当前时间
错误信息:
E2BIG:消息长度过长
EAGAIN:无所要求类型且没设置IPC_NOWAIT
....
ENOMSG:
//////////////////////////////////////////
信号量集
int semget(key_t key,int nsems, int semflg);
基本同消息队列
struct semid_ds {
struct ipc_perm sem_perm;
time_t sem_otime;//最后调用semop
time_t sem_ctime;//最后调用semctl
unsigned short sem_nsems;
};
int semctl(int semid,int semnum, int cmd ,...);
struct seminfo{
int semmap;//信号集量映射里的记录数量
int semmni;//最大信号量集
int semmns;//所有信号量集中的最大信号量
int semmnu;//最大信号量撤销量,未使用
int semmsl;//信号量集合中可容信号量数
int semopm;//最大操作数目,
int semume;//进程最大撤销数目,未使用
int semusz;//sem_undo sz
int semvmx;//最大信号量值
int semaem;//可被用于信号量调整的值
}
union semun {
int val;//SETVAL取值
struct semid_ds *buf;//用于保存IPC_STAT IPC_SET 获得的数据
unsigned short *array;//GETVAL SETALL数组大小
struct seminfo * __buf;//IPC_INFO 参数空间
}
cmd:
IPC_STAT:将内核相关数据复制给指向semid_ds 结构体的arg.buf指针. semnum忽略
IPC_SET:arg.buf
IPC_RMID:
IPC_INFO:
SEM_INFO:获得semusz semaem IPC_INFO
SEM_STAT:semid 信号集的数组索引 IPC_STAT
GETALL:在arg.array中返回的信号量集的值
GETNCNT:返回等待信号量增加的进程数
GETPID:返回最后调用semop进程号
GETVAL:信号量值
GETZCNT:等待信号量为0进程数
SETALL:用arg.array来设置信号量集的值
SETVAL:将信号量集中的信号量设置为arg.array
////////
int semop(int semid, struct sembuf *sops, unsigned nsops);

-----------------------------------------------------------
#include
#include
#include
#include
#include
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo * __buf;
};
int main(int argc, char* argv[]) {
int semid;
pid_t pid;
int proj_id;
key_t key;
int num;
int i, j;
union semun arg;
static struct sembuf acquire= {0, -1, SEM_UNDO};
static struct sembuf release= {0, 1, SEM_UNDO};
//get child
if (argc != 2) {
  printf("Usage:%s num/n", argv[0]);
  return -1;
}
num = atoi(argv[1]);
//generate key
proj_id =2;
key=ftok("/home/program", proj_id);
if (key==-1) {
  perror("can't generate the ipc key");
  return -1;
}
//generate  semset
semid = semget(key, 1, IPC_CREAT|IPC_EXCL|0666);
//if (semid == -1)
{
  perror("cant create semaphore set");
  return -1;
}
static unsigned short stat_var = 1;
arg.array =1;
if (semctl(semid, 0, SETVAL, arg)==-1) {
  perror("cant set semaphore set");
  return -1;
}
for (i=0; i
   for (j=0; j
    //enter
    printf("====enter the critical section/n");
    printf("----pid: %ld----/n", (long)getpid());
    sleep(1);
    printf("====leave the critical section/n");
    //release
    if (semop(semid, &release, 1)==-1) {
     perror("cant release the resource");
     _exit(-1);
    }
   }
   _exit(0);
  }
}
  //child exit
  for(i=0;i

共享内存


int shmget(key_t key, size_t size, int shmflg);
 shmflg: SHM_HUGETLB给共享内存分配HUGETLB页
int shmctl(int shmid,int cmd, struct shmid_ds *buf);
IPC_STAT,IPC_SET,IPC_RMID
IPC_INFO: struct shminfo{
  unsigned long shmmax;最大共享内存段
  unsigned long shmmin;最小内存共享段 1
  unsigned long shmmni;最大共享内存段数
  unsigned long shmseg;进程可以访问的最大共享内存段数,未使用
  unsigned long shmall;系统最大共享内存页
}
SHM_INFO
struct shm_info{
 int used_ids;当前存在的共享内存段
unsigned long shm_tot;总的共享内存页数
unsigned long shm_rss;驻留的共享内存页数
unsigned long shm_swp;交换的共享内存页数
unsigned long swap_attempts;不再使用
unsigned long swap_successes;不再使用
}
SHM_STAT:shmid为内核维护的内部共享内存段数组索引
SHM_LOCK阻止交换;
SHM_UNLOCK;解锁,允许换出
错误信息
EACCESS EFAULT EIDRM
ENOMEM:SHM_LOCK创建的内存段超出调用进程限制
EOVERFLOW:cmd IPC_STAT,GID UID过大,无法保存在buf 指向的数据结构中
EPERM:IPC_SET IPC_RMID
void * shmat(int shmid,const void * shmaddr, int shmflg);
NULL 系统自选
非NULL, flg SHM_RND ,则将共享内存段连接到shmaddr-(addr mod SHMLBA),表低边界地址整数倍
int shmdt(const void * shmaddr)

抱歉!评论已关闭.