目录
一,共享内存
申请共享内存 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