消息队列,共享内存
This commit is contained in:
parent
e6757b9935
commit
49d2f0cabb
|
@ -0,0 +1,46 @@
|
|||
// 消费者
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct data
|
||||
{
|
||||
char data[32];
|
||||
int flag;
|
||||
} Data;
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("consumer\n");
|
||||
|
||||
key_t key = ftok("/", 15);
|
||||
if (key == -1)
|
||||
{
|
||||
perror("ftok");
|
||||
return 1;
|
||||
}
|
||||
int shmid = shmget(key, sizeof(Data), IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Data *data_buf = (Data *)shmat(shmid, NULL, 0);
|
||||
if (data_buf == (Data *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
while (data_buf->flag == 0)
|
||||
;
|
||||
sleep(1);
|
||||
printf("read data: %s\n", data_buf->data);
|
||||
data_buf->flag = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
|
||||
// ftok()函数用于获取消息队列的键值
|
||||
int main()
|
||||
{
|
||||
// 获取消息队列的键值,返回值是一个整数,表示消息队列(IPC)的键值
|
||||
key_t key = ftok("/", 26);
|
||||
printf("key = %d\n", key);
|
||||
|
||||
// ftok()函数的第一个参数是路径,第二个参数是索引值
|
||||
// 索引值是一个整数,范围是0~255,用于区分不同的消息队列
|
||||
// 超过255的索引值会被截断,例如256会被截断为0,257会被截断为1,相当于循环使用
|
||||
key_t key2 = ftok("/", 26);
|
||||
printf("key = %d\n", key2);
|
||||
|
||||
int mask = 0xff; // 0b11111111 低8位掩码
|
||||
printf("mask = %d\n", mask);
|
||||
// 低8位掩码与key进行与运算,得到低8位
|
||||
printf("key & mask = %d\n", key & mask); // 用于获取低8位
|
||||
printf("key2 & mask = %d\n", key2 & mask); // 用于获取低8位
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/types.h> // 系统数据类型定义
|
||||
#include <sys/ipc.h> // IPC相关头文件
|
||||
#include <sys/msg.h> // 消息队列相关头文件
|
||||
|
||||
// msgget 函数用于创建消息队列,参数1是键值,参数2是权限
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/home/flykhan/", 200); // 获取消息队列的键值
|
||||
printf("key = %d\n", key);
|
||||
if (key == -1)
|
||||
{
|
||||
perror("ftok");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// msgget 函数用于创建消息队列,参数1是键值,参数2是权限
|
||||
// 返回值是消息队列的标识符,类似于文件描述符
|
||||
// IPC_CREAT 表示如果消息队列不存在则创建,如果存在则打开
|
||||
// 0644 表示权限,类似于文件权限,表示所有者可读写,其他人只读
|
||||
int msgqid = msgget(key, IPC_CREAT | 0666); // 创建消息队列
|
||||
if (msgqid == -1)
|
||||
{
|
||||
perror("msgget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// msgqid 只要不是 -1 就表示创建成功
|
||||
printf("msgqid = %d\n", msgqid); // 打印消息队列标识符
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/types.h> // 系统数据类型定义
|
||||
#include <sys/ipc.h> // IPC相关头文件
|
||||
#include <sys/msg.h> // 消息队列相关头文件
|
||||
#include <string.h> // 字符串操作
|
||||
#include <stdlib.h> // atol 函数
|
||||
#include <time.h> // 时间函数
|
||||
#include <unistd.h> // 头文件含义:unix standard,即unix标准的意思
|
||||
|
||||
// 消息结构体
|
||||
typedef struct msg_
|
||||
{
|
||||
long mType; // 消息类型,必须是 long ,必须在第一个位置
|
||||
char content[100]; // 消息内容,需要小于消息队列的限制值(8192)
|
||||
char title[32]; // 消息标题
|
||||
|
||||
} MSG;
|
||||
|
||||
// msgget 函数用于创建消息队列,参数1是键值,参数2是权限
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
key_t key = ftok("/", 200); // 获取消息队列的键值
|
||||
|
||||
int msgqid = msgget(key, IPC_CREAT | 0666); // 创建消息队列
|
||||
if (msgqid == -1)
|
||||
{
|
||||
perror("msgget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 查看 msgqid 消息队列的信息
|
||||
struct msqid_ds msginfo; // 消息队列信息结构体
|
||||
int ret = msgctl(msgqid, IPC_STAT, &msginfo); // 获取消息队列信息
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("msgctl");
|
||||
return 1;
|
||||
}
|
||||
|
||||
time_t st = msginfo.msg_stime; // 最后发送消息的时间
|
||||
time_t rt = msginfo.msg_rtime; // 最后接收消息的时间
|
||||
time_t ct = msginfo.msg_ctime; // 最后变更消息的时间
|
||||
|
||||
struct tm *stm = localtime(&st); // 转换为北京时间
|
||||
struct tm *rtm = localtime(&rt); // 转换为北京时间
|
||||
struct tm *ctm = gmtime(&ct); // 转换为北京时间
|
||||
|
||||
// // 手动转换为北京时间
|
||||
// st += 8 * 60 * 60;
|
||||
// rt += 8 * 60 * 60;
|
||||
// ct += 8 * 60 * 60;
|
||||
// // 把时间戳转换为字符串
|
||||
// char stime[32] = "";
|
||||
// char rtime[32] = "";
|
||||
// char ctime[32] = "";
|
||||
// ctime_r(&st, stime);
|
||||
// ctime_r(&rt, rtime);
|
||||
// ctime_r(&ct, ctime);
|
||||
// // 打印时间
|
||||
// printf("最后发送消息的时间: %s", stime);
|
||||
// printf("最后接收消息的时间: %s", rtime);
|
||||
// printf("最后变更消息的时间: %s", ctime);
|
||||
// printf("最后变更消息的时间: %s", ctime);
|
||||
|
||||
// + 1900 是因为 struct tm 结构体中的 tm_year 字段表示的是从1900年开始的年数的偏移量。
|
||||
// +1 是因为 struct tm 结构体中的 tm_mon 字段表示的是月份的偏移量,范围是0-11,其中0表示一月,11表示十二月
|
||||
printf("最后发送消息的时间: %d-%d-%d %d:%d:%d\n", stm->tm_year + 1900, stm->tm_mon + 1, stm->tm_mday, stm->tm_hour, stm->tm_min, stm->tm_sec);
|
||||
printf("最后接收消息的时间: %d-%d-%d %d:%d:%d\n", rtm->tm_year + 1900, rtm->tm_mon + 1, rtm->tm_mday, rtm->tm_hour, rtm->tm_min, rtm->tm_sec);
|
||||
printf("最后变更消息的时间: %d-%d-%d %d:%d:%d\n", ctm->tm_year + 1900, ctm->tm_mon + 1, ctm->tm_mday, ctm->tm_hour, ctm->tm_min, ctm->tm_sec);
|
||||
|
||||
// 打印消息队列的信息
|
||||
printf("\n消息队列的信息:\n");
|
||||
printf("消息队列的标识符: %d\n", msginfo.msg_perm.__key);
|
||||
printf("消息队列的权限: %04o\n", msginfo.msg_perm.mode); // %04o 是八进制输出,占4位,不足4位前面补0
|
||||
|
||||
// 修改消息队列的权限
|
||||
// msginfo.msg_perm.mode = 0644; // 修改权限
|
||||
msginfo.msg_perm.mode |= 0111; // 修改权限,增加可执行权限
|
||||
ret = msgctl(msgqid, IPC_SET, &msginfo);
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("msgctl");
|
||||
return 1;
|
||||
}
|
||||
printf("修改消息队列的权限为: %04o\n", msginfo.msg_perm.mode); // %04o 是八进制输出,占4位,不足4位前面补0
|
||||
|
||||
// execlp("ipcs", "ipcs", "-q", NULL); // 打印消息队列
|
||||
|
||||
// 减少权限
|
||||
msginfo.msg_perm.mode &= ~0101; // 修改权限,减少可执行权限
|
||||
ret = msgctl(msgqid, IPC_SET, &msginfo);
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("msgctl");
|
||||
return 1;
|
||||
}
|
||||
printf("修改消息队列的权限为: %04o\n", msginfo.msg_perm.mode); // %04o 是八进制输出,占4位,不足4位前面补0
|
||||
|
||||
execlp("ipcs", "ipcs", "-q", NULL); // 打印消息队列
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// 测试 msgctl ,用于删除消息队列
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 65); // 使用ftok函数生成一个唯一的键值
|
||||
int msqid = msgget(key, 0666 | IPC_CREAT); // 创建或获取消息队列
|
||||
|
||||
if (msqid == -1)
|
||||
{
|
||||
perror("msgget");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 控制操作:删除消息队列
|
||||
if (msgctl(msqid, IPC_RMID, NULL) == -1)
|
||||
{
|
||||
perror("msgctl");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Message queue removed successfully.\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// 生产者
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct data
|
||||
{
|
||||
char data[32];
|
||||
int flag;
|
||||
} Data;
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("producer\n");
|
||||
|
||||
key_t key = ftok("/", 15);
|
||||
if (key == -1)
|
||||
{
|
||||
perror("ftok");
|
||||
return 1;
|
||||
}
|
||||
int shmid = shmget(key, sizeof(Data), IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
Data *data_buf = (Data *)shmat(shmid, NULL, 0);
|
||||
if (data_buf == (Data *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
int num = 0;
|
||||
while (1)
|
||||
{
|
||||
|
||||
while (data_buf->flag == 1)
|
||||
;
|
||||
sprintf(data_buf->data, "hello, %d", num++);
|
||||
data_buf->flag = 1;
|
||||
printf("write data: %s\n", data_buf->data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// 共享内存
|
||||
/*
|
||||
是的,"shm"是共享内存(shared memory)的缩写,它通常用于表示共享内存相关的概念和操作。共享内存是一种进程间通信的机制,允许多个进程共享同一块内存区域,从而实现高效的数据交换和共享。
|
||||
|
||||
在Linux系统中,使用`shmget`函数创建或获取共享内存段(shared memory segment),进程可以通过该段共享内存进行通信。共享内存段是一个连续的内存区域,可以被多个进程映射到各自的地址空间中,从而实现共享数据的读写。
|
||||
|
||||
共享内存在进程间通信中具有高速和低开销的优势,因为进程可以直接读写共享内存,而无需进行复制或传输数据。但同时也需要注意正确地处理同步和互斥,以避免数据竞争和一致性问题。
|
||||
|
||||
因此,当你看到"shm"时,通常指的是共享内存,而"share mem"是它的完整表达形式。这两个术语可以互换使用,表示同一概念。
|
||||
*/
|
||||
#include <sys/shm.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
|
||||
// 获取共享内存的标识
|
||||
int shmid = shmget(key, 32, IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("shmid=%d\n", shmid);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// 共享内存
|
||||
#include <sys/shm.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
// 共享内存写数据
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
|
||||
// 获取共享内存的标识
|
||||
int shmid = shmget(key, 32, IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("shmid=%d\n", shmid);
|
||||
|
||||
// 获取共享内存的首地址
|
||||
char *buf = shmat(shmid, NULL, 0); // NULL表示让系统自动分配共享内存的首地址
|
||||
if (buf == (char *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(buf, "hi, shared memory");
|
||||
printf("write data ok\n");
|
||||
|
||||
/*
|
||||
// 删除共享内存
|
||||
int ret = shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("shmctl");
|
||||
return 1;
|
||||
}
|
||||
printf("shared memory deleted\n");
|
||||
*/
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// 共享内存
|
||||
#include <sys/shm.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
// 共享内存读数据
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
|
||||
// 获取共享内存的标识
|
||||
int shmid = shmget(key, 32, IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("shmid=%d\n", shmid);
|
||||
|
||||
// 获取共享内存的首地址
|
||||
char *buf = shmat(shmid, NULL, 0); // NULL表示让系统自动分配共享内存的首地址
|
||||
if (buf == (char *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("共享内存的数据:%s\n", buf);
|
||||
/*
|
||||
// 删除共享内存
|
||||
int ret = shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("shmctl");
|
||||
return 1;
|
||||
}
|
||||
printf("shared memory deleted\n");
|
||||
*/
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// 共享内存
|
||||
#include <sys/shm.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
// 解除映射
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
|
||||
// 获取共享内存的标识
|
||||
int shmid = shmget(key, 32, IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("shmid=%d\n", shmid);
|
||||
|
||||
// 获取共享内存的首地址
|
||||
char *buf = shmat(shmid, NULL, 0); // NULL表示让系统自动分配共享内存的首地址
|
||||
if (buf == (char *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("共享内存的数据:%s\n", buf);
|
||||
|
||||
// 解除映射
|
||||
int ret = shmdt(buf);
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("shmdt");
|
||||
return 1;
|
||||
}
|
||||
printf("解除映射成功 ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
// 共享内存
|
||||
#include <sys/shm.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
// 共享内存删除
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
|
||||
// 获取共享内存的标识
|
||||
int shmid = shmget(key, 32, IPC_CREAT | 0666);
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("shmid=%d\n", shmid);
|
||||
|
||||
// 获取共享内存的首地址
|
||||
char *buf = shmat(shmid, NULL, 0); // NULL表示让系统自动分配共享内存的首地址
|
||||
if (buf == (char *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("共享内存的数据:%s\n", buf);
|
||||
|
||||
// 删除共享内存
|
||||
// NULL 表示不关心共享内存的信息
|
||||
// int ret = shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
|
||||
|
||||
// 如果不写 NULL,应该写一个结构体,表示共享内存的信息
|
||||
struct shmid_ds ds;
|
||||
int ret = shmctl(shmid, IPC_RMID, &ds); // 删除共享内存
|
||||
if (ret == -1)
|
||||
{
|
||||
perror("shmctl");
|
||||
return 1;
|
||||
}
|
||||
printf("shared memory deleted\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
typedef struct data
|
||||
{
|
||||
int data;
|
||||
int flag;
|
||||
} Data;
|
||||
|
||||
int main()
|
||||
{
|
||||
key_t key = ftok("/", 28);
|
||||
int shmid = shmget(key, sizeof(Data), IPC_CREAT | 0666);
|
||||
|
||||
if (shmid == -1)
|
||||
{
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fork() == 0) // 生产者进程
|
||||
{
|
||||
Data *data = shmat(shmid, NULL, 0);
|
||||
if (data == (Data *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data->flag = 0; // 初始化为 0
|
||||
data->data = 0; // 初始化为 0
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// 等待消费者消费数据
|
||||
while (data->flag == 1)
|
||||
;
|
||||
data->data++; // 生产数据
|
||||
data->flag = 1;
|
||||
printf("生产者生产数据:%d\n", data->data);
|
||||
}
|
||||
|
||||
// 解除映射
|
||||
if (shmdt(data) == -1)
|
||||
{
|
||||
perror("shmdt");
|
||||
return 1;
|
||||
}
|
||||
_exit(0); // 子进程退出
|
||||
}
|
||||
|
||||
if (fork() == 0) // 消费者进程
|
||||
{
|
||||
Data *data = shmat(shmid, NULL, 0);
|
||||
if (data == (Data *)-1)
|
||||
{
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
data->flag = 0; // 初始化为 0
|
||||
data->data = 0; // 初始化为 0
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// 等待生产者生产数据
|
||||
while (data->flag == 0)
|
||||
{
|
||||
printf("等待生产者生产数据\n");
|
||||
}
|
||||
|
||||
printf("消费者消费数据:%d\n", data->data);
|
||||
// 消费到 100 时退出
|
||||
if (data->data == 10)
|
||||
break;
|
||||
sleep(1);
|
||||
data->flag = 0;
|
||||
}
|
||||
|
||||
// 解除映射
|
||||
if (shmdt(data) == -1)
|
||||
{
|
||||
perror("shmdt");
|
||||
return 1;
|
||||
}
|
||||
_exit(0); // 子进程退出
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
// WUNTRACED 不跟踪 ?
|
||||
int pid = waitpid(0, NULL, WUNTRACED);
|
||||
if (pid == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
printf("%d 子进程结束\n", pid);
|
||||
}
|
||||
|
||||
// 删除共享内存
|
||||
if (shmctl(shmid, IPC_RMID, NULL) == -1)
|
||||
{
|
||||
perror("shmctl");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue