管道的创建--------------管道不属于ipc
#include <unistd.h>
int pipe(int fd [2]);
- 返回:成功返回0,出错返回-1
两个文件描述符数组
- fd[0]:为pipe的读端
- fd[1]:为pipe的写端
fd[0]用于读取管道,fd[1]用于写入管道
命名管道FIFO的创建
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char* pathname,mode_t mode);
- 返回:若成功则返回0,出错返回-1
------------------------------------------------------------------------------------------------------------
打开或创建消息队列
#include <sys/msg.h>
int msgget(key_t key, int flag);
- 返回:成功返回内核中消息队列的标识ID,出错返回-1
参数
- key:用户指定的消息队列的键值
- flag:IPC_CREAT , IPC_EXCL ,IPC_PRIVATE等
创建 | 存在返回-1 | 类似于文件I/O的非阻塞标志
若创建消息队列,key可以指定键值,也可以将之设置为IPC_PRIVATE——0;
消息队列控制函数
#include <sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
- 返回:成功返回0,出错返回-1
参数
- msqid:消息队列ID
- buf: 消息队列属性指针
- cmd:
IPC_STAT:获取消息队列的属性,取此队列msqid_ds结构,并将其存放在buf指向的结构中
IPC_SET:设置属性,按有buf指向的结构中的值,设置与此队列相关的结构中的字段
IPC_RMID:删除队列,从系统中删除该消息队列以及仍在该队列的所有数据。
发送消息函数
#include <sys/msg.h>
int msgsnd(int msqid,const void *ptr,size_t nbytes,int flag);
- 返回:成功返回0,出错返回-1
参数:
- msqid:消息队列ID
- ptr:消息
struct mymesg{
long mtype; //消息类型它由一个整数来代表,并且它只能是大于0的整数
char mtext[512]; //消息数据本身 在Linux中,消息的最大长度是4056个字节,其中包括mtype
int i; //消息数据本身
strcut student { }stu;
}
- nbytes :指定消息的大小,不包括mtype的大小
- flag:
0:阻塞
IPC_NOWAIT:类似于文件I/O的非阻塞标志
接受消息
#include <sys/msg.h>
ssize_t msgrcv(int msqid,void *ptr,size_t nbytes,long type,int flag)
- 返回:成功返回消息的数据部分长度,出错返回-1
参数
- msqid:消息队列ID
- ptr:指向存放消息的缓存
- nbytes:消息缓存的大小,不包括mtype的大小,计算方式:
nbyte = sizeof(struct mymesg)-sizeof(long)
- type:消息类型,消息类型是指只接受指定消息类型的消息
type == 0:获得消息队列中第一个消息
type > 0: 获得消息队列中类型为type的第一个消息
type < 0:获得消息队列中小于或等于type绝对值得消息(类型最小)
- flag:
0:阻塞
IPC_NOWAIT:类似于文件I/O的非阻塞标志
创建共享内存
#include <sys/shm.h>
int shmget(key_t key ,size_t size,int shmflg);
- 返回:如果成功,返回内核中共享内存的标识ID,如果失败,则返回-1.
参数:
- key:用户指定的共享内存键值
- size:共享内存大小
- shmflg:IPC_CREAT , IPC_EXCL ,IPC_PRIVATE等
创建 | 存在返回-1 | 类似于文件I/O的非阻塞标志
errno:
- EINVAL 无效的内存段大小
- EEXIST 内存段已经存在,无法创建
- EIDRM 内存段已经被删除
- ENOENT 内存段不存在
- EACCES 权限不够
- ENOMEM 没有足够的内存来创建内存段
共享内存控制函数
#include <sys/shm.h>
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
- 返回:成功返回0,出错返回-1
参数
- shmid:共享内存ID
- buf:共享内存属性指针
- cmd:
IPC_STAT 获取共享内存段属性
IPC_SET 设置共享内存段属性
IPC_RMID 删除共享内存段
SHM_LOCK 锁定共享内存段页面(页面映射到物理内存不和外存进行换入换出操作)
SHM_UNLOCK 解锁共享内存段页面的锁定
共享内存的映射和解除映射函数
#include <sys/shm.h>
void* shmat(int shmid,char* shmaddr,int shmflg);
- 返回:成功返回共享内存映射到进程虚拟内存空间中的地址,失败返回-1
int shmdt(char * shmaddr);
- 返回:失败返回-1
参数
- shmid :共享内存ID
- shmaddr:映射到进程虚拟内存空间的地址,建议设置为0,由操作系统分配
- shmflg:若shmaddr设置为0,则shmflag也设置为0
SHM_RND
SHMLBA 地址为2 的乘方
SHM_RDONLY 只读方式链接
errno
- EINVAL无效的IPC ID值或者无效的地址
- ENOMEM 没有足够的内存
- EACCES 存取权限不够
子进程不继承父进程创建的共享内存,大家都是共享的。子进程继承父进程映射的地址。
创建信号量集函数
#include <sys/sem.h>
int semget(key_t key,int nsems,int flag);
- 返回:成功返回信号集ID,出错返回-1
参数:
- key:用户指定的信号量键值
- nsems:信号量集中信号量个数
- flag:IPC_CREAT , IPC_EXCL ,IPC_PRIVATE等
创建 | 存在返回-1 | 类似于文件I/O的非阻塞标志
信号量集控制函数
#include <sys/sem.h>
int semctl(int semid,int semnum,int cmd, .../*union semun arg*/);
- 返回:成功返回0,出错返回-1
参数
- semid:信号量集ID
- semnum:0表示对所有信号量操作,信号量编号从0开始
- union semun arg:
union semun{ 此结构体需自己定义
int val; 放置获取或设置信号量集中某个信号量的值 初始值
struct semid_ds *buf; 信号量集属性指针
unsigned short *array; 放置获取或设置信号量集中所有信号量的值,array一般用数组接收
}; //用了联合体??因为这是集合了三种操作,自然是不能共存的
- cmd:
IPC_STAT 获取信号量集的属性 ->buf
IPC_SET 设置信号量集的属性 ->buf
IPC_RMID 删除信号量集 ->buf
GETVAL 返回信号量的值 ->val
SETVAL 设置semnum信号量的值 ->val
GETALL 获取所有信号量的值 ->array
SETALL 设置所有信号量的初始值 ->array
信号量集操作
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops,size_t nsops);
- 返回:成功返回0,出错返回-1
参数
- semid:信号量集ID
- sops:sembuf结构体数组指针:
struct sembuf{ 此结构体可以直接用
unsigned short sem_num; 信号量集中信号量的编号
short sem_op; 正数为V操作,负数为P操作,0可以用于对共享资源是否已用完的测试。
shrot sem_flg; SEM_UNDO标志,表示在进程结束时,相应的操作将被取消,如果设置了该标志,那么在进程没有释放共享资源就退出时,内核将代为释放。还有IPC_NOWAIT等
}
- nsops:第二个参数(sops)中结构体数组的长度
用于信号量集中信号量的加和减操作(PV操作)
可以用于进程间的互斥和同步
线程锁、线程信号量; 写在进程的数据内部
信号;
管道;
system v ipc对象(消息队列,共享内存,信号量集);