Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 程式設計入門:執行緒 (pthread) 建立、同步與檔案複製實戰範例

編輯:Linux 教學

執行緒是行程內的輕量級執行單元,共享程式碼區、資料區、檔案描述符,建立/切換成本遠低於行程。本文介紹 POSIX 執行緒庫 (pthread.h) 核心 API:pthread_create、pthread_exit、pthread_join,並以「多執行緒並行複製目前目錄下所有檔案,副檔名改為 .bak」為完整實戰範例,展示執行緒參數傳遞、錯誤處理、資源釋放、主執行緒等待回收流程。

核心 API 速查

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);
// thread: 輸出建立的執行緒 ID
// attr: 屬性 (NULL 表預設)
// start_routine: 執行緒入口函式,回傳 void*
// arg: 傳遞給入口函式的單一參數

void pthread_exit(void *retval);          // 執行緒結束,傳回 retval
int pthread_join(pthread_t thread, void **retval); // 等待指定執行緒結束,取得 retval

實戰範例:多執行緒檔案備份程式

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFFER 512

struct copy_file { int infile; int outfile; };

void *copy(void *arg) {
    struct copy_file *file = (struct copy_file *)arg;
    int infile = file->infile, outfile = file->outfile;
    int bytes_read, bytes_write, *bytes_copy_p;
    char buffer[BUFFER], *buffer_p;

    if ((bytes_copy_p = malloc(sizeof(int))) == NULL) pthread_exit(NULL);
    *bytes_copy_p = 0;

    while ((bytes_read = read(infile, buffer, BUFFER)) > 0) {
        buffer_p = buffer;
        while (bytes_read > 0) {
            bytes_write = write(outfile, buffer_p, bytes_read);
            if (bytes_write <= 0) break;
            buffer_p += bytes_write;
            bytes_read -= bytes_write;
        }
        *bytes_copy_p += bytes_write;
    }
    close(infile); close(outfile);
    pthread_exit(bytes_copy_p);
}

int main(int argc, char **argv) {
    struct dirent **namelist;
    int num = scandir(".", &namelist, NULL, alphasort);
    if (num < 0) { perror("scandir"); exit(1); }

    pthread_t *threads = malloc(num * sizeof(pthread_t));
    struct copy_file *files = malloc(num * sizeof(struct copy_file));

    for (int i = 0; i < num; i++) {
        if (namelist[i]->d_type != DT_REG) continue; // 僅處理一般檔案
        char src[BUFFER], dst[BUFFER];
        snprintf(src, BUFFER, "%s", namelist[i]->d_name);
        snprintf(dst, BUFFER, "%s.bak", namelist[i]->d_name);

        files[i].infile = open(src, O_RDONLY);
        files[i].outfile = open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0644);
        if (files[i].infile < 0 || files[i].outfile < 0) continue;

        pthread_create(&threads[i], NULL, copy, &files[i]);
    }

    // 等待所有執行緒結束
    for (int i = 0; i < num; i++) {
        void *ret;
        pthread_join(threads[i], &ret);
        if (ret) { printf("Copied %d bytes\n", *(int*)ret); free(ret); }
    }

    free(threads); free(files);
    // 釋放 scandir 記憶體
    for (int i = 0; i < num; i++) free(namelist[i]);
    free(namelist);
    return 0;
}

關鍵細節解析

  • 參數傳遞: 使用結構體 copy_file 封裝檔案描述符,避免多參數麻煩。
  • 動態分配回傳值: 執行緒結束時區域變數會釋放,故 bytes_copy_p 必須 malloc,由主執行緒 pthread_join 取得後 free。
  • 錯誤處理: read/write 遇 EINTR 需重試;write 可能部分寫入需迴圈處理。
  • 資源回收: 主執行緒必須 pthread_join 否則產生殭屍執行緒洩漏資源。

編譯與執行

gcc -o mtcopy mtcopy.c -lpthread
./mtcopy

掌握 pthread 基礎,即可進入高併發、多核心程式設計的大門。

Copyright © Windows教程網 All Rights Reserved