IPC通信

    技术2022-05-12  9

    函数: #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)

    最新回复(0)