包含三个方面:1.消息队列 2.共享内存 3.信号量集
使用命令ipcs 可以查看system v TPC的对象
第一步:获取一个键值
如何获取键值?使用ftok(3)获取一个键值
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:转换pathname和proj_id为一个key值。
参数:
pathname:指定文件的名字
proj_id:一个整数,这个整数的低八位不能为0
返回值:
成功 key值返回
-1 失败 errno被设置
举例使用ftok(3) 获取一个键值
第二步:通过键值获取一块内存,将这块内存的id返回。
第三步:通过内存的id操作这块内存。
1.消息队列
通过键值获取一块内存,将这块内存的id返回。需要使用msgget(2),获取内核对象的id
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:获取一个消息队列的id
参数:
key:fotk(3)获得key值
msgflg:
IPC_CREAT:
IPC_EXCL:
mode:指定了消息队列的权限
返回值:
-1 失败 errno被设置
成功返回消息的队列的id
举例验证,通过键值获取消息队列的id
向消息队列中发送消息,使用msgsnd(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:向消息队列发送消息
参数:
msqid:指定了要操作的消息队列的id
msgp:指向msgbuf类型的指针
msgsz:是metxt的长度
msgflg:
返回值:
0 成功
-1 失败 errno被设置
举例验证,将一个消息放入消息队列中。
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
功能:从消息队列中获取消息
参数:
msqid:制定了消息队列的id
msgp:指向了获取到的消息
msgsz:是mtext的长度
msgtyp:消息的类型
msgflg:
IPC_NOWAIT:如果消息队列中没有消息,立即返回。
0 :如果消息队列中没有消息,阻塞等待。
返回值:
-1 错误 errno 被设置
获取到的消息体的字节数
举例从消息队列中获取消息输出到显示器
补充:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
2.共享内存
根据键值获取共享内存的id,如何获取?使用shmget(2)
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:
参数:
key:ftok(3)返回的键值
size:指定了共享内存的尺寸
shmflg:
IPC_CREAT :指定创建共享内存段
返回值:
-1 错误
返回共享内存段的id
举例,创建共享内存段
将共享内存映射到进程的虚拟地址空间里,使用shmat(2)
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:将共享内存绑定到进程的地址空间里
参数:
shmid:共享内存的id
shmaddr:指定了进程绑定共享内存的地址。指定为空,系统做选择。
shmflg:
返回值:
返回和共享内存段绑定的地址
(void *) -1 错误 errno被设置
int shmdt(const void *shmaddr);
功能:解除和共享内存段的绑定
参数:shmaddr:指定了要解除共享内存段在进程中的地址
返回值:
0 成功
-1 失败 errno被设置
举例使用共享内存实现进程间的通信。shmA.c shmB.c
ipcrm 用来从内核中移除ipc通讯对象。
3.信号量集
信号量集就是有一个或多个信号量组成的集合。
如何使用信号量集是实现进程间的通讯?
1.获取一个键值
2.通过键值获取信号量集semid
semget(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
3.对信号量集中的某个信号量进程pv操作。semop(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
功能:信号量的操作
参数:
semid:制定了信号量集的id
sops:制定了对信号量的操作
nsops:指定了要操作的信号量的个数。
返回值:
0 成功
-1 失败 errno被设置
补充:
unsigned short semval; /* semaphore value */
unsigned short semzcnt; /* # waiting for zero */
unsigned short semncnt; /* # waiting for increase */
pid_t sempid; /* process that did last op */
struct sembuf{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};
sem_num 指定了要操作的信号量的下标
sem_op 指定了对信号量的pv操作
>0 semval+sem_op v 操作
=0 进程等待到零 立即处理。
<0 如果sem_op 的绝对这小于semval 立即处理。semval-sem_op p操作
如果sem_op的绝对值大于semval,IPC_NOWAIT被指定,semop(2)立即返回错误。
sem_flg IPC_NOWAIT(非阻塞) and SEM_UNDO()为零时,阻塞。
4.为信号量集中的某个信号量设置初值。或者获取信号量的值。
为了信号量中的某一个信号量设置初值。或者获取信号量的值。控制信号量集中某一个信号量,需要使用到semxtl(2)
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
补充:
第四个参数:
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */
};
举例,使用信号量集实现进程间的通信
client.c
sever.c