diff --git a/day5/consumer.c b/day5/consumer.c new file mode 100644 index 0000000..cb9bec9 --- /dev/null +++ b/day5/consumer.c @@ -0,0 +1,46 @@ +// 消费者 +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day5/ftok1.c b/day5/ftok1.c new file mode 100644 index 0000000..8eec287 --- /dev/null +++ b/day5/ftok1.c @@ -0,0 +1,25 @@ +#include +#include +#include + +// 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; +} \ No newline at end of file diff --git a/day5/msgque1.c b/day5/msgque1.c new file mode 100644 index 0000000..d7c83d9 --- /dev/null +++ b/day5/msgque1.c @@ -0,0 +1,31 @@ +#include +#include // 系统数据类型定义 +#include // IPC相关头文件 +#include // 消息队列相关头文件 + +// 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; +} \ No newline at end of file diff --git a/day5/msgque4.c b/day5/msgque4.c new file mode 100644 index 0000000..3bad6b3 --- /dev/null +++ b/day5/msgque4.c @@ -0,0 +1,102 @@ +#include +#include // 系统数据类型定义 +#include // IPC相关头文件 +#include // 消息队列相关头文件 +#include // 字符串操作 +#include // atol 函数 +#include // 时间函数 +#include // 头文件含义: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; +} \ No newline at end of file diff --git a/day5/msgque_msgctl_test.c b/day5/msgque_msgctl_test.c new file mode 100644 index 0000000..a00db20 --- /dev/null +++ b/day5/msgque_msgctl_test.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +// 测试 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; +} diff --git a/day5/producer.c b/day5/producer.c new file mode 100644 index 0000000..a238320 --- /dev/null +++ b/day5/producer.c @@ -0,0 +1,47 @@ +// 生产者 +#include +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day5/shm1.c b/day5/shm1.c new file mode 100644 index 0000000..28dff97 --- /dev/null +++ b/day5/shm1.c @@ -0,0 +1,30 @@ +// 共享内存 +/* +是的,"shm"是共享内存(shared memory)的缩写,它通常用于表示共享内存相关的概念和操作。共享内存是一种进程间通信的机制,允许多个进程共享同一块内存区域,从而实现高效的数据交换和共享。 + +在Linux系统中,使用`shmget`函数创建或获取共享内存段(shared memory segment),进程可以通过该段共享内存进行通信。共享内存段是一个连续的内存区域,可以被多个进程映射到各自的地址空间中,从而实现共享数据的读写。 + +共享内存在进程间通信中具有高速和低开销的优势,因为进程可以直接读写共享内存,而无需进行复制或传输数据。但同时也需要注意正确地处理同步和互斥,以避免数据竞争和一致性问题。 + +因此,当你看到"shm"时,通常指的是共享内存,而"share mem"是它的完整表达形式。这两个术语可以互换使用,表示同一概念。 +*/ +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/day5/shm2.c b/day5/shm2.c new file mode 100644 index 0000000..2e84fb7 --- /dev/null +++ b/day5/shm2.c @@ -0,0 +1,44 @@ +// 共享内存 +#include +#include +#include +#include + +// 共享内存写数据 +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; +} \ No newline at end of file diff --git a/day5/shm3.c b/day5/shm3.c new file mode 100644 index 0000000..5fb2315 --- /dev/null +++ b/day5/shm3.c @@ -0,0 +1,42 @@ +// 共享内存 +#include +#include +#include +#include + +// 共享内存读数据 +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; +} \ No newline at end of file diff --git a/day5/shm4.c b/day5/shm4.c new file mode 100644 index 0000000..08d6ff6 --- /dev/null +++ b/day5/shm4.c @@ -0,0 +1,42 @@ +// 共享内存 +#include +#include +#include +#include + +// 解除映射 +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; +} \ No newline at end of file diff --git a/day5/shm5.c b/day5/shm5.c new file mode 100644 index 0000000..a6e07ae --- /dev/null +++ b/day5/shm5.c @@ -0,0 +1,47 @@ +// 共享内存 +#include +#include +#include +#include + +// 共享内存删除 +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; +} \ No newline at end of file diff --git a/day5/shm6.c b/day5/shm6.c new file mode 100644 index 0000000..63f8842 --- /dev/null +++ b/day5/shm6.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include + +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; +} \ No newline at end of file