You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下C语言多线程CPU使用率监控程序编译链接错误求助

C语言多线程CPU使用率程序编译未定义引用问题

编写了一个多线程C程序,用于读取并打印Linux系统所有CPU核心的使用率。单线程状态下运行正常,但改为多线程后,编译时出现大量未定义引用错误,无法定位问题。期望程序实现三个线程循环执行(每次循环休眠1秒),并能通过Ctrl+C正常终止。

原代码文件

头文件(funkctions.h)

#include <pthread.h>

extern int cpu_user[16];
extern int cpu_sum[16];
extern float cpu_proc[16];

extern pthread_t t_reader;
extern pthread_t t_analyzer;
extern pthread_t t_printer;

extern pthread_mutex_t mutex_r;
extern pthread_mutex_t mutex_a;
extern pthread_mutex_t mutex_p;

void *reader();
void *analyzer();
void *printer();
//void *logger();
//void *watchdog();

主函数(main.c)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>

#include "funkctions.h"

void closing();

int main(){
    signal(SIGINT, closing);

    pthread_mutex_init(&mutex_r, NULL);
    pthread_mutex_init(&mutex_a, NULL);
    pthread_mutex_init(&mutex_p, NULL);

    pthread_create(&t_reader, NULL, reader, NULL);
    pthread_create(&t_analyzer, NULL, analyzer, NULL);
    pthread_create(&t_printer, NULL, printer, NULL);

    return 0;
}

void closing(){
    printf("\nCleaning and closing...\n");

    pthread_mutex_destroy(&mutex_r);
    pthread_mutex_destroy(&mutex_a);
    pthread_mutex_destroy(&mutex_p);

    pthread_join(t_reader, NULL);
    pthread_join(t_analyzer, NULL);
    pthread_join(t_printer, NULL);

    printf("\nDONE!\n");
    exit(0);
}

reader函数(reader.c)

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

#include "../funkctions.h"

int cpu_user[16];
int cpu_sum[16];

void *reader(){
    while(1){
        pthread_mutex_lock(&mutex_r);
        char buffer[255];

        FILE *pFile;
        pFile = fopen("/proc/stat", "r");
        fgets(buffer, sizeof(buffer), pFile); //discarding 1st line of /proc/stat

        for(int i = 0; i < 16 ; i++){ //reading lines form 2 do 17 (for 16 cpu cores)
            int temp = 0;  //setting temp to zero for every for loop
            fgets(buffer, sizeof(buffer), pFile); //reading next line of /proc/stat        
            sscanf(buffer, "%*s %d", &cpu_user[i]); //saving 2nd line of /proc/stat ---> to extern int array
            char *token = strtok(buffer, " "); //setting token for new buffer
            while(token != NULL){   //token in NULL when there is nothing more in string to process
                if (sscanf(token, "%d", &temp) == 1){ //finding next decimal (sscanf returns 1 when it finds a match)
                    cpu_sum[i] += temp; //sum of cpu usage for every core ---> to extern int array
                }
            token = strtok(NULL, " "); //going to next part of string when token found
        }
        pthread_mutex_unlock(&mutex_r);
        }

        fclose(pFile);
        sleep(1);
    }
}

analyzer函数(analyzer.c)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>


#include "../funkctions.h"

float cpu_proc[16];

void *analyzer(){
    while(1){
        pthread_mutex_lock(&mutex_a);
        for(int i = 0; i < 16; i++){
            cpu_proc[i] = ((float)cpu_user[i]/(float)cpu_sum[i])*100;
        }
        pthread_mutex_unlock(&mutex_a);
        sleep(1);
    }
}

printer函数(printer.c)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

#include "../funkctions.h"

void *printer(){
    while(1){
        pthread_mutex_lock(&mutex_p);
        printf("\n------------------------------");
        for(int i = 0; i < 16 ; i++){
            printf("\nCPU%d: %7.2lf%%", i, cpu_proc[i]);
        }
        printf("\n------------------------------");
        pthread_mutex_unlock(&mutex_p);
        sleep(1);
    }
}

原编译命令及错误输出

gcc -o main main.c functions_source/analyzer.c functions_source/printer.c functions_source/reader.c -lpthread

错误输出:

/usr/bin/ld: /tmp/cc6dGjI5.o: warning: relocation against `t_printer' in read-only section `.text'
/usr/bin/ld: /tmp/cc6dGjI5.o: in function `main':
main.c:(.text+0x24): undefined reference to `mutex_r'
/usr/bin/ld: main.c:(.text+0x38): undefined reference to `mutex_a'
/usr/bin/ld: main.c:(.text+0x4c): undefined reference to `mutex_p'
/usr/bin/ld: main.c:(.text+0x6f): undefined reference to `t_reader'
/usr/bin/ld: main.c:(.text+0x92): undefined reference to `t_analyzer'
/usr/bin/ld: main.c:(.text+0xb5): undefined reference to `t_printer'
/usr/bin/ld: /tmp/cc6dGjI5.o: in function `closing':
main.c:(.text+0xe2): undefined reference to `mutex_r'
/usr/bin/ld: main.c:(.text+0xf1): undefined reference to `mutex_a'
/usr/bin/ld: main.c:(.text+0x100): undefined reference to `mutex_p'
/usr/bin/ld: main.c:(.text+0x10f): undefined reference to `t_reader'
/usr/bin/ld: main.c:(.text+0x123): undefined reference to `t_analyzer'
/usr/bin/ld: main.c:(.text+0x137): undefined reference to `t_printer'
/usr/bin/ld: /tmp/ccH46vwi.o: in function `analyzer':
analyzer.c:(.text+0xf): undefined reference to `mutex_a'
/usr/bin/ld: analyzer.c:(.text+0x9b): undefined reference to `mutex_a'
/usr/bin/ld: /tmp/ccDXHFL5.o: in function `printer':
printer.c:(.text+0xf): undefined reference to `mutex_p'
/usr/bin/ld: printer.c:(.text+0x9d): undefined reference to `mutex_p'
/usr/bin/ld: /tmp/ccREn7jd.o: in function `reader':
reader.c:(.text+0x21): undefined reference to `mutex_r'
/usr/bin/ld: reader.c:(.text+0x18c): undefined reference to `mutex_r'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status

问题解决

1. 未定义引用的核心原因

头文件中用extern声明了互斥量和线程变量,但没有在任何源文件中实际定义这些变量。extern仅告知编译器变量存在,必须在某个文件中分配内存(即定义变量)。

2. 编译错误修复

在main.c中添加全局变量的定义(放在main函数外):

pthread_t t_reader, t_analyzer, t_printer;
pthread_mutex_t mutex_r, mutex_a, mutex_p;

3. 逻辑问题修复

  • 主线程退出问题:原main函数直接return 0会导致进程终止,子线程也会被强制结束。修改为主线程进入无限休眠循环:
    int main(){
        // ... 原有代码
        while(1) {
            sleep(1);
        }
    }
    
  • 互斥量解锁位置错误:原reader函数把解锁操作放在for循环内部,导致第一次循环后就释放锁,后续读取无保护。将pthread_mutex_unlock(&mutex_r)移到for循环外部。
  • CPU数据累加问题:原reader中cpu_sum[i]未清零,会持续累加历史数据,导致使用率计算失真。每次读取前清零cpu_user[i]和cpu_sum[i]。
  • 线程终止问题:原closing函数直接调用pthread_join无法终止无限循环的线程,添加pthread_cancel取消线程后再等待结束:
    void closing(){
        printf("\nCleaning and closing...\n");
    
        pthread_cancel(t_reader);
        pthread_cancel(t_analyzer);
        pthread_cancel(t_printer);
    
        pthread_join(t_reader, NULL);
        pthread_join(t_analyzer, NULL);
        pthread_join(t_printer, NULL);
    
        pthread_mutex_destroy(&mutex_r);
        pthread_mutex_destroy(&mutex_a);
        pthread_mutex_destroy(&mutex_p);
    
        printf("\nDONE!\n");
        exit(0);
    }
    
  • 数据同步问题:analyzer读取cpu_user和cpu_sum时需要持有mutex_r,避免reader修改数据导致脏读;printer读取cpu_proc时持有mutex_a即可。

4. 最终编译命令

保持原编译命令即可:

gcc -o main main.c functions_source/analyzer.c functions_source/printer.c functions_source/reader.c -lpthread

内容的提问来源于stack exchange,提问作者BartoszOlejarz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 07:45:54