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

五一假期作业

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 命令逐个终止进程:

     

牛客网刷题

相关文章:

  • android-ndk开发(4): linux开发机有线连接android设备
  • Go小技巧易错点100例(二十九)
  • 关于毕业论文,查重,AIGC
  • 【漫话机器学习系列】240.真正类率(True Positive Rate,TPR)
  • C++演讲比赛案例代码
  • AI日报 · 2025年5月05日|雅诗兰黛与微软合作成立 AI 创新实验室,加速美妆产品研发与营销
  • LCD,LED
  • AI笔记-1
  • 稀疏性预测算法初步
  • 文心一言开发指南13——文心一言API两种调用方式的区别
  • cpp学习笔记1--class
  • 【QT】QT安装
  • Python生活手册-NumPy数组创建:从快递分拣到智能家居的数据容器
  • Springboot循环依赖
  • React-router v7 第八章(边界处理)
  • AI向量检索
  • DeepSeek提示词的技巧
  • URL混淆与权限绕过技术
  • Linux | WEB服务器的部署及优化
  • Doo全自动手机壳定制系统
  • 体坛联播|米兰逆转热那亚豪取3连胜,阿诺德官宣离开利物浦
  • 特朗普要征100%关税,好莱坞这批境外摄制新片能躲过吗?
  • 五一车市消费观察:政策赋能、企业发力,汽车消费火热
  • 贵州游船侧翻248名消防员已在搜救
  • 今晚上海地铁1、2、10、17号线加开定点班车至次日0点
  • G40迎来返程大车流,今明两日预计超13万辆车经长江隧桥进沪