IPC对象
在linux系统,消息队列/共享内存/信号量都是属于IPC对象。假设创建一条消息队列,等于创建了一个IPC对象。
动作 | 返回结果( 代表相对应的IPC对象) |
---|---|
访问文件 | 文件描述符 |
创建消息队列 | 消息队列ID |
创建共享内存 | 共享内存ID |
创建信号量 | 信号量ID |
查看命令
:~$ ipcs -a
Message Queues
key msqid owner perms used-bytes messages
Shared Memory Segments
key shmid owner perms bytes nattch status
Semaphore Arrays
key semid owner perms nsems
删除IPC对象
因为IPC对象ID号唯一的,所以可以根据IPC对象ID号删除。
删除共享内存: ipcrm -m 共享内存ID
删除消息队列: ipcrm -q 消息队列ID
删除信号量: ipcrm -s 信号量ID
创建IPC对象
IPC对象ID由key值来决定,也就是key值一致,那么根据key来申请ID号,ID号也会一致。
也就是说申请ID号之前,首先要申请一个key值。
申请key值
ftok() man 3 ftok
功能: 获取IPC对象的key值
提供一个路径和一个数字,那么就会返回IPC对象的key值。
pathname:一个合法并且存在的文件 “.”
proj_id:非0整数 0~128 例如: 10
只要路径/整数有一个不一致,那么返回值就会不一样。
返回值:
成功:申请到的key值
失败:-1
验证"只要路径/整数有一个不一致,那么返回值就会不一样"
int main()
{
key_t k1,k2,k3,k4;
k1 = ftok(".",10);
k2 = ftok("..",10);
k3 = ftok(".",20);
k4 = ftok(".",10);
printf("k1 = %d\n",k1); //与k4相同
printf("k2 = %d\n",k2); //k2与k1/k3都不相同
printf("k3 = %d\n",k3); //k3与k1/k2都不相同
printf("k4 = %d\n",k4); //与k1相同
}
那么如果两个任意的进程需要访问同一个IPC对象,那么这两个进程申请key值必须参数一致!
消息队列
消息队列特征: 读取特性类型的数据。
管道特性: 有什么数据,只能读取什么数据。
消息队列程序思路
为消息队列IPC对象申请key值 ftok()
根据申请到的key值去申请一个新的ID号 msgget() -> man 2 msgget
msgflg:
IPC_CREAT -> 不存在则创建 -> 需要添加起始权限: IPC_CREAT|0666
IPC_EXCL -> 存在则报错
返回值:
成功:消息队列的ID号
失败:-1
往消息队列中写入数据 msgsnd()
msqid:消息队列的ID号
msgp:数据缓冲区 -> 包含类型以及正文
struct msgbuf{ -> 需要在代码中重新声明一个这样的结构体,正文大小由用户自己设定!
long mtype; -> 消息的类型
char mtext[1]; -> 消息的正文 -> 自定义的结构体/数组
};
msgsz:消息正文的大小
msgflg: 正常普通属性填0
读取消息队列的数据 msgrcv()