目录
前言
System V IPC(Inter-Process Communication)对象是一种用于在不同进程之间进行通信的机制。它包括三种类型的对象:消息队列(Message Queue)、信号量(Semaphore)和共享内存(Shared Memory)。
一、system V IPC对象图解
1.流程图解:
2.查看linux内核中的ipc对象:
二、消息队列
1.消息队列的原理
2.消息队列相关的API
2.1 获取或创建消息队列(msgget)
实例代码如下:
int main(void)
{
key_t key;
int msg_id;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取消息对象
msg_id = msgget(key,IPC_CREAT|0666);
if(msg_id < 0){
perror("msgget");
exit(1);
}
return 0;
}
2.2 发送消息到消息队列中
实例代码如下:
int main(void)
{
key_t key;
int msg_id;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取消息对象
msg_id = msgget(key,IPC_CREAT|0666);
if(msg_id < 0){
perror("msgget");
exit(1);
}
//向消息队列中发送消息
while(1){
bzero(&buf,sizeof(buf));
printf("请输入消息的类型:");
scanf("%ld",&buf.mtype);
printf("请输入消息:");
while(getchar() != '\n'); //清空输入缓冲区
fgets(buf.mtext,sizeof(buf.mtext),stdin);
buf.mtext[strlen(buf.mtext)-1] = '\0';
if(msgsnd(msg_id,&buf,strlen(buf.mtext),0) < 0){
perror("msgsnd");
exit(1);
}
}
return 0;
}
2.3 从消息队列中获取消息
实例代码如下:
int main(void)
{
key_t key;
int msg_id;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取消息对象
msg_id = msgget(key,IPC_CREAT|0666);
if(msg_id < 0){
perror("msgget");
exit(1);
}
//从消息队列中获取消息
while(1){
bzero(&buf,sizeof(buf));
printf("请输入消息的类型:");
scanf("%ld",&buf.mtype);
if(msgrcv(msg_id,&buf,sizeof(buf.mtext),buf.mtype,0) < 0){
perror("msgsnd");
exit(1);
}
printf("msg:%s\n",buf.mtext);
}
return 0;
}
2.4 消息队列相关的命令
2.5 管理消息队列
实例代码如下:
int main(int argc,char **argv)
{
int msg_id;
msg_id = atoi(argv[1]);
if(msgctl(msg_id,IPC_RMID,NULL) < 0){
perror("msgget");
exit(1);
}
return 0;
}
三、共享内存
1.概念
2.原理图解
3.相关的api函数
3.1 创建共享内存对象
实例代码如下:
int main(void)
{
key_t key;
int shm_id;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取共享内存对象
shm_id = shmget(key,SHM_SIZE, IPC_CREAT|0666);
if(shm_id < 0){
perror("shmget");
exit(1);
}
return 0;
}
3.2 映射共享内存
3.3 取消映射
实例代码reader.c如下:
#include "shm.h"
int main(void)
{
key_t key;
int shm_id;
char *buf;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取共享内存对象
shm_id = shmget(key,SHM_SIZE, IPC_CREAT|0666);
if(shm_id < 0){
perror("shmget");
exit(1);
}
//将共享内存映射到进程的虚拟空间中
buf = (char*)shmat(shm_id,NULL,0);
if(buf < 0){
perror("shmat");
exit(1);
}
//打印共享内存中的数据
while(1){
printf("%s",buf);
sleep(1);
}
//解除映射
if(shmdt(buf) < 0){
perror("shmdt");
exit(1);
}
return 0;
}
实例代码writer.c如下:
#include "shm.h"
int main(void)
{
key_t key;
int shm_id;
char *buf;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取共享内存对象
shm_id = shmget(key,SHM_SIZE, IPC_CREAT|0666);
if(shm_id < 0){
perror("shmget");
exit(1);
}
//将共享内存映射到进程的虚拟空间中
buf = (char*)shmat(shm_id,NULL,0);
if(buf < 0){
perror("shmat");
exit(1);
}
//向共享内存写数据
while(1){
printf("请输入字符串:");
fgets(buf,SHM_SIZE,stdin);
}
//解除映射
if(shmdt(buf) < 0){
perror("shmdt");
exit(1);
}
return 0;
}
实例代码shm.h 如下:
#ifndef __SHM_H__
#define __SHM_H__
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024
#endif
3.4 管理共享内存
实例代码如下:
int main(int argc,char **argv)
{
int shm_id;
shm_id = atoi(argv[1]);
if(shmctl(shm_id,IPC_RMID,NULL) < 0){
perror("shmget");
exit(1);
}
return 0;
}
四、信号灯 (信号量)
1.概念
2.信号灯相关的api函数
2.1 创建或获取信号灯对象
实例代码如下:
int main(void)
{
key_t key;
int sem_id;
//获取key值
key = ftok("./",0xa);
if(key < 0){
perror("ftok");
exit(1);
}
//创建或获取共享内存对象
sem_id = semget(key,1, IPC_CREAT|0666);
if(sem_id < 0){
perror("semget");
exit(1);
}
return 0;
}
2.2 实现P操作和V操作
实例代码如下:
//1》实现P操作
void sem_p(int sem_id,int index)
{
struct sembuf buf = {index,-1,0};
if(semop(sem_id,&buf,1) < 0){
perror("semop");
exit(1);
}
}
//2》实现v操作
void sem_v(int sem_id,int index)
{
struct sembuf buf = {index,1,0};
if(semop(sem_id,&buf,1) < 0){
perror("semop");
exit(1);
}
}
2.3 管理信号灯
实例代码如下:
//初始化指定的信号灯
void sem_init(int sem_id,int semnum,int value)
{
union semun su;
su.val = value;
if(semctl(sem_id,semnum,SETVAL,su) < 0){
perror("semctl");
exit(1);
}
}
//初始化所有信号灯
void sem_init_all(int sem_id,unsigned short vals[])
{
union semun su;
su.array = vals;
if(semctl(sem_id,0,SETALL,su) < 0){
perror("semctl");
exit(1);
}
}
总结
本篇文章针对进程间通信system V IPC对象进行详细讲解,希望能够帮到大家!
以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识,感谢大家支持懒大王!
希望这篇博客能给各位朋友们带来帮助,最后懒大王请来过的朋友们留下你们宝贵的三连以及关注,感谢你们!