当前位置: 首页 > web >正文

五一假期作业

sub_process.c

#include <stdio.h>         // 标准输入输出库
#include <pthread.h>       // POSIX线程库
#include <sys/ipc.h>       // IPC基础定义(如消息队列/共享内存)
#include <sys/msg.h>       // 消息队列操作相关
#include <sys/shm.h>        // 共享内存操作相关
#include <unistd.h>         // 标准符号常量和类型
#include <string.h>         // 字符串操作相关#define NUM_THREADS 4      // 定义线程数量为4
#define MAX_MSG_SIZE 1024  // 定义单条消息的最大长度// 消息队列数据结构
struct msg_buffer 
{long msg_type;          // 消息类型标识(必须非0)char msg_text[MAX_MSG_SIZE]; // 实际消息内容缓冲区
};// 共享内存数据结构
struct shm_data
{int char_count[256];    // ASCII字符频率统计数组(支持扩展ASCII)pthread_mutex_t lock;   // 互斥锁保护共享数据
};int shmid; // 全局共享内存ID,供子进程或线程使用// 线程处理函数:负责从消息队列读取日志并统计字符
void* process_log(void* arg) 
{int msgid = *(int*)arg; // 从参数获取消息队列ID(潜在问题:传递局部变量地址)struct msg_buffer msg;  // 定义接收消息的临时缓冲区// 阻塞式接收消息队列中类型为1的消息ssize_t bytes_received = msgrcv(msgid, &msg, MAX_MSG_SIZE, 1, 0);if (bytes_received == -1){perror("msgrcv"); // 如果接收失败则打印错误信息return NULL;}// 将共享内存附加到当前进程的地址空间struct shm_data* shm = shmat(shmid, NULL, 0);if (shm == (void*)-1) {perror("shmat"); // 如果附加失败则打印错误信息return NULL;}// 遍历接收到的消息内容进行字符统计for (int i = 0; i < bytes_received; i++) {   unsigned char c = msg.msg_text[i]; // 取当前字符(无符号避免负数索引)pthread_mutex_lock(&shm->lock);     // 加锁保护共享数据shm->char_count[c]++;              // 对应字符计数+1pthread_mutex_unlock(&shm->lock);  // 解锁}shmdt(shm); // 分离共享内存(不影响其他进程/线程的挂接)return NULL;
}int main() {// 生成IPC对象唯一键值(基于文件路径和项目ID)key_t key = ftok("/tmp/logfile", 65);if (key == -1){perror("ftok"); // 如果生成失败则退出程序return 1;}// 创建消息队列(权限0666,若不存在则创建)int msgid = msgget(key, 0666 | IPC_CREAT);if (msgid == -1) {perror("msgget"); // 如果获取失败则退出程序return 1;}// 创建共享内存段(大小为shm_data结构体,权限0666,若不存在则创建)shmid = shmget(key, sizeof(struct shm_data), 0666 | IPC_CREAT);if (shmid == -1){perror("shmget"); // 如果创建失败则退出程序return 1;}// 将共享内存附加到当前进程地址空间并进行初始化struct shm_data* shm = shmat(shmid, NULL, 0);memset(shm, 0, sizeof(struct shm_data)); // 清空共享内存内容pthread_mutex_init(&shm->lock, NULL);    // 初始化互斥锁// 创建线程池(NUM_THREADS个线程)pthread_t threads[NUM_THREADS];for (int i = 0; i < NUM_THREADS; i++) {// 创建线程并传递消息队列ID指针(潜在问题:msgid是栈变量)if (pthread_create(&threads[i], NULL, process_log, &msgid) != 0){perror("pthread_create"); // 如果线程创建失败则退出程序return 1;}}// 等待所有线程执行完毕for (int i = 0; i < NUM_THREADS; i++) {pthread_join(threads[i], NULL);}// 分离共享内存(主进程不再需要访问)shmdt(shm);return 0;
}

main_process.c

#include <stdio.h>         // 标准输入输出库
#include <sys/ipc.h>       // IPC基础定义(消息队列/共享内存等)
#include <sys/shm.h>        // 共享内存操作相关函数
#include <pthread.h>       // POSIX线程库
#include <unistd.h>         // 标准符号常量和类型// 共享内存结构体(与子进程保持一致)
struct shm_data 
{int char_count[256];    // ASCII字符频率统计数组(支持扩展ASCII)pthread_mutex_t lock;   // 互斥锁保护共享数据
};int main() 
{// 生成唯一键值(基于文件路径和项目ID)key_t key = ftok("/tmp/logfile", 65);if (key == -1){perror("ftok"); // 如果生成键值失败则退出程序return 1;}// 创建或获取共享内存段(大小为shm_data结构体)int shmid = shmget(key, sizeof(struct shm_data), 0666 | IPC_CREAT);if (shmid == -1) {perror("shmget"); // 如果获取共享内存失败则退出程序return 1;}// 将共享内存映射到当前进程地址空间struct shm_data* shm = shmat(shmid, NULL, 0);if (shm == (void*)-1) {perror("shmat"); // 如果映射失败则退出程序return 1;}// 实时监控循环(永久运行直到程序被强制终止)while (1) {sleep(1); // 每隔1秒更新一次统计信息// 加锁以保护共享数据pthread_mutex_lock(&shm->lock);printf("===== 字符统计 =====
");// 遍历所有可能的ASCII字符for (int i = 0; i < 256; i++) {if (shm->char_count[i] > 0) // 仅显示出现过的字符{if (i == ' ') {printf("空格: %d
", shm->char_count[i]); // 特殊处理空格字符} else {printf("%c: %d
", (char)i, shm->char_count[i]); // 显示可打印字符}}}// 解锁以允许其他线程访问pthread_mutex_unlock(&shm->lock);}// 分离共享内存(实际上不会执行到这里)shmdt(shm);return 0;
}

monitor.c

#include <stdio.h>         // 标准输入输出库
#include <sys/ipc.h>       // IPC基础定义(消息队列/共享内存等)
#include <sys/shm.h>        // 共享内存操作相关函数
#include <pthread.h>       // POSIX线程库
#include <unistd.h>         // 标准符号常量和类型// 共享内存结构体(与子进程保持一致)
struct shm_data 
{int char_count[256];    // ASCII字符频率统计数组(支持扩展ASCII)pthread_mutex_t lock;   // 互斥锁保护共享数据
};int main() 
{// 生成唯一键值(基于文件路径和项目ID)key_t key = ftok("/tmp/logfile", 65);if (key == -1){perror("ftok"); // 如果生成键值失败则退出程序return 1;}// 创建或获取共享内存段(大小为shm_data结构体)int shmid = shmget(key, sizeof(struct shm_data), 0666 | IPC_CREAT);if (shmid == -1) {perror("shmget"); // 如果获取共享内存失败则退出程序return 1;}// 将共享内存映射到当前进程地址空间struct shm_data* shm = shmat(shmid, NULL, 0);if (shm == (void*)-1) {perror("shmat"); // 如果映射失败则退出程序return 1;}// 实时监控循环(永久运行直到程序被强制终止)while (1) {sleep(1); // 每隔1秒更新一次统计信息// 加锁以保护共享数据pthread_mutex_lock(&shm->lock);printf("===== 字符统计 =====
");// 遍历所有可能的ASCII字符for (int i = 0; i < 256; i++) {if (shm->char_count[i] > 0) // 仅显示出现过的字符{if (i == ' ') {printf("空格: %d
", shm->char_count[i]); // 特殊处理空格字符} else {printf("%c: %d
", (char)i, shm->char_count[i]); // 显示可打印字符}}}// 解锁以允许其他线程访问pthread_mutex_unlock(&shm->lock);}// 分离共享内存(实际上不会执行到这里)shmdt(shm);return 0;
}
编译和运行
# 创建共享内存键值文件
touch /tmp/logfile# 编译代码
gcc main_process.c -o main_process
gcc sub_process.c -o sub_process -lpthread
gcc monitor.c -o monitor -lpthread# 生成测试日志
base64 /dev/urandom | head -n 1000 > test.log# 按顺序启动进程
./sub_process &
./monitor &
./main_process

手动终止进程

  1. 查找进程ID
    在终端中执行以下命令,找到相关进程的PID:

    ps aux | grep -E 'main_process|sub_process|monitor'
    
  2. 终止进程
    使用 kill 命令逐个终止进程:

     

牛客网刷题

http://www.xdnf.cn/news/4012.html

相关文章:

  • springboot单体项目的执行流程
  • LFU算法解析
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】4.5 清洗流程自动化(存储过程/定时任务)
  • 【中间件】brpc_基础_单例
  • FreeRTOS学习系列·二值信号量
  • Linux查询日志常用命令
  • 解锁现代健康密码:科学养生新主张
  • 基于PLC的换热器温度控制系统设计
  • 状态模式(State Pattern)
  • 电子商务商家后台运营专员模板
  • C++ 中二级指针的正确释放方法
  • 【KWDB 创作者计划】_Ubuntu 22.04系统KWDB数据库安装部署使用教程
  • Qt中的UIC
  • Amazon Bedrock Converse API:开启对话式AI新体验
  • Qt开发:容器组控件的介绍和使用
  • 20、数据可视化:魔镜报表——React 19 图表集成
  • 408考研逐题详解:2009年第8题
  • Java后端程序员学习前端之CSS
  • Python matplotlib 成功使用SimHei 中文字体
  • 详解RabbitMQ工作模式之发布订阅模式
  • 基于C++实现的深度学习(cnn/svm)分类器Demo
  • Baklib知识中台:智能服务架构新实践
  • 【算法学习】递归、搜索与回溯算法(一)
  • python函数复习(形参实参,收集参数,关键字参数)
  • uniapp中用canvas绘制简单柱形图,小容量,不用插件——简单使用canvas
  • QT 在圆的边界画出圆
  • IP属地是我的定位吗?——解析两者区别
  • Python异步编程入门:从同步到异步的思维转变
  • VBA信息获取与处理专题五:VBA利用CDO发送电子邮件
  • 【外围电路】按键电路设计外接信号输入设计