文章的目的为了记录使用C语言进行linux 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
linux C 语言开发 (一) Window下用gcc编译和gdb调试
linux C 语言开发 (二) VsCode远程开发 linux
linux C 语言开发 (六) 程序的编辑和编译(vim、gcc)
Linux C到Android App开发推荐链接(入门十二章):
开源 java android app 开发(一)开发环境的搭建_csdn 开源 java android app-优快云博客
开源 java android app 开发(一)开发环境的搭建-优快云博客
开源 java android app 开发(二)工程文件结构-优快云博客
开源 java android app 开发(三)GUI界面布局和常用组件-优快云博客
开源 java android app 开发(四)GUI界面重要组件-优快云博客
开源 java android app 开发(五)文件和数据库存储-优快云博客
开源 java android app 开发(六)多媒体使用-优快云博客
开源 java android app 开发(七)通讯之Tcp和Http-优快云博客
开源 java android app 开发(八)通讯之Mqtt和Ble-优快云博客
开源 java android app 开发(九)后台之线程和服务-优快云博客
开源 java android app 开发(十)广播机制-优快云博客
开源 java android app 开发(十一)调试、发布-优快云博客
开源 java android app 开发(十二)封库.aar-优快云博客
linux C到.net mvc开发推荐链接:
开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-优快云博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-优快云博客
开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-优快云博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-优快云博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-优快云博客、
内容:讲述进程IPC通讯方式之消息队列。
目录:
1.基本介绍
2.常用函数
3.源码分析
4.效果演示
一、基本介绍
System V IPC 包含三种进程间通信机制, 有消息队列, 信号灯(也叫信号量) , 共享内存。 此外还有 System V IPC 的补充版本 POSIX IPC, 这两组 IPC 的通信方法基本一致, 本章以 System V IPC 为例介绍 Linux 进程通信机制。
控制台输入IPCS可以查看系统中存在的 IPC 信息:
步骤
1. 获取 key 值, 内核会将 key 值映射成 IPC 标识符, 获取 key 值常用方法:
(1) 在 get 调用中将 IPC_PRIVATE 常量作为 key 值。
(2) 使用 ftok()生成 key。
2. 执行 IPC get 调用, 通过 key 获取整数 IPC 标识符 id, 每个 id 表示一个 IPC 对象。
| 接口 | 消息队列 | 共享内存 | 信号灯 |
| 创建/打开对象 | msgget() | shmget() | semget() |
3. 通过 id 访问 IPC 对象。
| 接口 | 消息队列 | 共享内存 | 信号灯 |
| 读写/调整 | msgsnd()/msgr cv() | shmat() | semop() |
4. 通过 id 控制 IPC 对象
| 接口 | 消息队列 | 共享内存 | 信号灯 |
| 控制 | msgctl() | shmctl() | semctl() |
二、常用函数
| 函数 | key_t ftok(const char *pathname, int proj_id) |
| 头文件 | #include <sys/types.h> #include <sys/ipc.h> |
| 参数 pathname | 路径名或文件名 |
| 参数 proj_id | 同一个文件根据此值生成多个 key 值, int 型或字符型, 多个若想访问同一 IPC 对象, 此值必须相同。 |
| 返回值 | 成功返回 key 值, 失败返回-1 |
| 功能 | 建立 IPC 通讯(如消息队列、 共享内存时) 必须指定一个 ID 值。 通常情况下, 该id 值通过 ftok 函数得到。 |
消息队列是类 unix 系统中一种数据传输的机制, 其他操作系统中也实现了这种机制, 可见这种通信机制在操作系统中有重要地位。
Linux 内核为每个消息队列对象维护一个 msqid_ds, 每个 msqid_ds 对应一个 id, 消息以链表形式存储,并且 msqid_ds 存放着这个链表的信息。

消息队列的使用步骤:
1. 创建 key;
2. msgget()通过 key 创建(或打开) 消息队列对象 id;
3. 使用 msgsnd()/msgrcv()进行收发;
4. 通过 msgctl()删除 ipc 对象
通过 msgget()调用获取到 id 后即可使用消息队列访问 IPC 对象, 消息队列常用 API 如下:
| 函数 | int msgget(key_t key, int msgflg) |
| 头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
| 参数 key_t key | 和消息队列相关的 key 值 |
| 参数 int msgflg | 访问权限 |
| 返回值 | 成功返回消息队列的 ID, 失败-1 |
| 功能 | 获取 IPC 对象唯一标识 id |
| 函数 | int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg) |
| 头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
| 参数 int msqid | 消息队列 ID |
| 参数 const void *msgp | 指向消息类型的指针 |
| 参数 size_t msgsz | 发送的消息的字节数。 |
| 参数 int msgflg | 如果为 0, 直到发送完成函数才返回, 即阻塞发送IPC_NOWAIT: 消息没有发送完成, 函数也会返回, 即非阻塞发送 |
| 返回值 | 成功返回 0, 失败返回-1 |
| 功能 | 发送数据 |
| 函数 | int msgctl(int msqid, int cmd, struct msqid_ds *buf) |
| 头文件 | #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> |
| 参数 int msqid | 消息队列的 ID |
| 参数 int cmd | IPC_STAT: 读取消息队列的属性, 然后把它保存在 buf 指向的缓冲区。IPC_SET: 设置消息队列的属性, 这个值取自 buf 参数IPC_RMID: 删除消息队列 |
| 参数 struct msqid_ds *buf | 消息队列的缓冲区 |
| 返回值 | 成功返回 0, 失败返回-1 |
| 功能 | 控制操作, 删除消息队列对象等 |
| 函数 | ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) |
| 参数 msqid | IPC 对象对应的 id |
| 参数 msgp | 消息指针, 消息包含类型和字段 |
| 参数 msgsz | 消息里的字段大小 |
| 参数 msgtyp | 消息里的类型 |
| 参数 msgflg | 位掩码, 不止一个 |
| 返回值 | 成功返回接收到的字段大小, 错误返回-1 |
| 功能 | 接收消息 |
三、源码分析
向消息队列里面写
msgWirte.c代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct msgbuf
{
long mtype;
char mtext[128];
};
int main(void)
{
int msgid;
key_t key;
struct msgbuf msg;
//获取 key 值
key = ftok("./a.c", 'a');
//获取到 id 后即可使用消息队列访问 IPC 对象
msgid = msgget(key, 0666 | IPC_CREAT);
if (msgid < 0)
{
printf("msgget is error\n");
return -1;
}
printf("msgget is ok and msgid is %d \n", msgid);
msg.mtype = 1;
strncpy(msg.mtext, "hello", 5);
//发送数据
msgsnd(msgid, &msg, strlen(msg.mtext), 0);
return 0;
}
从消息队列里面读
msgRead.c源码
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
struct msgbuf
{
long mtype;
char mtext[128];
};
int main(void)
{
int msgid;
key_t key;
struct msgbuf msg;
key = ftok("./a.c", 'a');
//获取到 id 后即可使用消息队列访问 IPC 对象
msgid = msgget(key, 0666 | IPC_CREAT);
if (msgid < 0)
{
printf("msgget is error\n");
return -1;
}
printf("msgget is ok and msgid is %d \n", msgid);
//接收数据
msgrcv(msgid, (void *)&msg, 128, 0, 0);
printf("msg.mtype is %ld \n", msg.mtype);
printf("msg.mtext is %s \n", msg.mtext);
return 0;
}
四、效果演示
运行2个程序以后,可以看到读出了消息队列的数据。同时可以查看新建的消息队列。

1165

被折叠的 条评论
为什么被折叠?



