在多線程環境下,有時需要讓每條線程擁有獨立的資料副本。POSIX 提供 pthread_key_t 機制:同一個鍵在不同線程中可指向不同的記憶體區塊。
pthread_key_create(&key, destructor):建立鍵,指定銷毀回調。pthread_setspecific(key, value):設定當前線程該鍵對應的值。pthread_getspecific(key):取得當前線程該鍵的值。pthread_key_delete(key):刪除鍵(不釋放值記憶體,線程結束時由 destructor 清理)。#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
struct mydata { int x; char c[4]; };
pthread_key_t datakey;
void *cleanup_mydata(void *ptr) { free((struct mydata*)ptr); }
void *anum1(void *arg) {
struct mydata *mdata = malloc(sizeof(struct mydata));
mdata->x = 1; mdata->c[0] = 'a'; mdata->c[1] = '\0';
pthread_setspecific(datakey, mdata);
sleep(1);
struct mydata *mmdata = pthread_getspecific(datakey);
printf("-%d-%s\n", mmdata->x, mmdata->c);
return NULL;
}
void *bnum2(void *arg) {
struct mydata *mdata = malloc(sizeof(struct mydata));
mdata->x = 2; mdata->c[0] = 'b'; mdata->c[1] = '\0';
pthread_setspecific(datakey, mdata);
sleep(1);
struct mydata *mmdata = pthread_getspecific(datakey);
printf("-%d-%s\n", mmdata->x, mmdata->c);
return NULL;
}
int main() {
pthread_key_create(&datakey, cleanup_mydata);
pthread_t ta, tb;
pthread_create(&ta, NULL, anum1, NULL);
pthread_create(&tb, NULL, bnum2, NULL);
sleep(3);
pthread_join(ta, NULL); pthread_join(tb, NULL);
pthread_key_delete(datakey);
return 0;
}
輸出顯示兩線程各自擁有獨立的 mydata 實例,互不干擾。
利用 fork() 建立子進程,子進程呼叫 execlp() 執行使用者輸入的指令,父進程以 waitpid() 等待子進程結束並取得退出碼。
int execlp(const char *file, const char *arg0, ..., NULL);
pid_t waitpid(pid_t pid, int *stat_loc, int options);
#include <stdio.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define MAXLINE 100
int main() {
int pid, status, len;
char buf[MAXLINE];
printf("\n##myhaspl~~");
while (fgets(buf, MAXLINE, stdin)) {
len = strlen(buf) - 1;
if (buf[len] == '\n') buf[len] = 0;
pid = fork();
if (pid < 0) { perror("fork"); continue; }
else if (pid == 0) { // 子進程
if (buf[0] == 'Q' && strlen(buf) == 1) exit(200);
if (execlp(buf, buf, (char*)0) == -1) {
printf("不能執行:%s\n", buf); exit(127);
}
}
// 父進程
if (waitpid(pid, &status, 0) < 0) perror("waitpid");
if (WEXITSTATUS(status) == 200) { printf("退出....\n"); break; }
printf("\n##myhaspl~~");
}
return 0;
}
##myhaspl~~ls
...檔案列表...
##myhaspl~~xx
不能執行:xx
##myhaspl~~Q
退出....
| 參數 | 說明 |
|---|---|
| pid | -1: 任一子進程; >0: 指定 PID; 0: 同進程組; <-1: 進程組 ID 絕對值 |
| stat_loc | 儲存退出狀態,配合 WIFEXITED、WEXITSTATUS 等巨集解析 |
| options | WNOHANG 非阻塞; WUNTRACED 報告已停止子進程 |
execlp 在 PATH 中尋找可執行檔,適合實作命令列解析器。waitpid 提供靈活的子進程狀態回收機制,是 Shell 父進程的核心。