目录
一,共享内存
申请共享内存 shmget
控制共享内存 shmctl
关联共享内存 shmat / 去联共享内存 shmdt
二,消息队列
创建或打开消息队列 msgget
发送消息 msgsnd / 接收消息 msgrcv
控制消息 msgctl
三,信号量
创建或打开信号量 semget
信号量操作 semop
信号量控制 semctl
一,共享内存
共享内存是最快的进程间通信IPC形式,即允许两个或多个进程共享物理内存的同一块区域(通常被称为段),进程间数据传递将不再涉及到内核(即将不再通过内核系统调用来传递数据);
维护共享内存的数据结构
//vim /usr/include/bits/shm.h
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 */
};
//vim /usr/include/bits/ipc.h/* Data structure used to pass permission information to IPC operations. */ struct ipc_perm { __key_t __key; /* Key. */ __uid_t uid; /* Owner's user ID. */ __gid_t gid; /* Owner's group ID. */ __uid_t cuid; /* Creator's user ID. */ __gid_t cgid; /* Creator's group ID. */ unsigned short int mode; /* Read/write permission. */ unsigned short int __pad1; unsigned short int __seq; /* Sequence number. */ unsigned short int __pad2; __syscall_ulong_t __unused1; __syscall_ulong_t __unused2; };
申请共享内存 shmget
- key,用于唯一区分共享内存,可由ftok函数生成;
- size,建议为4KB的倍数;
- shmflg,标签;
- IPC_CREAT,如目标共享内存不存在,即创建,否则获取;
- IPC_CREAT | IPC_EXCL,如目标共享内存不存在,即创建,否则出错;
//vim /usr/include/bits/ipc.h#include <bits/types.h> /* Mode bits for `msgget', `semget', and `shmget'. */ #define IPC_CREAT 01000 /* Create key if key does not exist. */ #define IPC_EXCL 02000 /* Fail if key exists. */ #define IPC_NOWAIT 04000 /* Return error on wait. */ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ #define IPC_STAT 2 /* Get `ipc_perm' options. */ #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif
控制共享内存 shmctl
关联共享内存 shmat / 去联共享内存 shmdt
//makefile CC=gcc .PHONY:all all: server client server:server.c $(CC) -o $@ $^ client:client.c $(CC) -o $@ $^ .PHONY:clean clean: rm -rf server client
//comm.h #pragma once #include <stdio.h> #define PATH_NAME "/home/wz/Desktop/pipe" #define PROJ_ID 0x6666#define SIZE 4097
//server.c include "comm.h" #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int main() { key_t k = ftok(PATH_NAME, PROJ_ID); if(k < 0){ perror("ftok"); return 1; } printf("key: %x\n", k); sleep(3); int shmid = shmget(k, SIZE, IPC_CREAT|IPC_EXCL|0644); if(shmid < 0){ perror("shmget"); return 2; } printf("shmid: %d\n", shmid); sleep(3); char* start = (char*)shmat(shmid, NULL, 0); printf("server already attach on shared memory!\n"); while(1){ printf("%s\n", start); sleep(1); if(strlen(start) == 26) break; } shmdt(start); printf("server already dattach off shared memory!\n"); sleep(3); shmctl(shmid, IPC_RMID, NULL); printf("delete %d\n", shmid); return 0; }
//client.c #include "comm.h" #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int main() { key_t k = ftok(PATH_NAME, PROJ_ID); if(k < 0){ perror("ftok"); return 1; } printf("key: %x\n", k); sleep(3); int shmid = shmget(k, SIZE, IPC_CREAT); if(shmid < 0){ perror("shmget"); return 2; } printf("client shmid: %d\n", shmid); sleep(3); char* start = (char*)shmat(shmid, NULL, 0); printf("client already attach on shared memory!\n"); char c = 'A'; while(c <= 'Z'){ start[c - 'A'] = c; c++; sleep(1); } shmdt(start); printf("client already dattach off shared memory!\n"); sleep(3); return 0; }
//查看共享内存 [wz@192 pipe]$ ipcs -m //删除指定id共享内存 [wz@192 pipe]$ ipcrm -m 426047
共享内存的生命周期随OS;
共享内存不提供任何同步与互斥,彼此独立;
共享内存是所有进程间通信中,速度最快的;
共享内存系统分配的shm,是按照4KB为基本单位的,如指定不是4KB的倍数,多余会浪费掉;
二,消息队列
消息队列是进程间通信的一种方式,提供一个从一个进程向另一个进程发生一块数据的方法;
维护消息队列的数据结构
//vim /usr/include/bits/msq.h
/* Structure of record for one message inside the kernel. The type `struct msg' is opaque. */ struct msqid_ds {
E> struct ipc_perm msg_perm; /* structure describing operation permission */ __time_t msg_stime; /* time of last msgsnd command */ #ifndef __x86_64__ unsigned long int __unused1; #endif __time_t msg_rtime; /* time of last msgrcv command */ #ifndef __x86_64__ unsigned long int __unused2; #endif __time_t msg_ctime; /* time of last change */ #ifndef __x86_64__ unsigned long int __unused3; #endif __syscall_ulong_t __msg_cbytes; /* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ __pid_t msg_lspid; /* pid of last msgsnd() */ __pid_t msg_lrpid; /* pid of last msgrcv() */ __syscall_ulong_t __unused4; __syscall_ulong_t __unused5; };
创建或打开消息队列 msgget
- key,用于唯一区分共享内存,可由ftok函数生成;
- msgflg,标签;
- IPC_CREAT,如目标消息队列不存在,即创建,否则获取;
- IPC_CREAT | IPC_EXCL,如目标消息队列不存在,即创建,否则出错;
发送消息 msgsnd / 接收消息 msgrcv
控制消息 msgctl
三,信号量
信号量并不是原来进程间传输数据的,是原来同步进程当作的,主要用于同步与互斥;由于进程要求共享资源,而有些资源需互斥使用;系统中的某些资源一次只允许一个进程使用,称这些资源为临界资源或互斥资源;涉及到互斥资源的程序段,称为临界区;
维护信号量的数据结构
//vim /usr/include/bits/sem.h /* Data structure describing a set of semaphores. */ struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ __time_t sem_otime; /* last semop() time */ __syscall_ulong_t __unused1; __time_t sem_ctime; /* last time changed by semctl() */ __syscall_ulong_t __unused2; __syscall_ulong_t sem_nsems; /* number of semaphores in set */ __syscall_ulong_t __unused3; __syscall_ulong_t __unused4; };
创建或打开信号量 semget
信号量操作 semop
信号量控制 semctl