get_robust_list - 获取进程的健壮互斥锁列表
1. 函数介绍
get_robust_list 是一个 Linux 系统调用,用于获取指定进程的健壮互斥锁(robust futex)列表。健壮互斥锁是 Linux 提供的一种特殊类型的 futex,能够在持有锁的进程异常终止时自动清理锁状态,防止其他进程无限期等待。
data-ad-format="fluid"
data-ad-layout-key="-7k+ex-4a-9w+4a">
这个机制主要用于解决多线程程序中,当持有互斥锁的线程意外崩溃时,其他等待该锁的线程可能会永远阻塞的问题。
https://blog.csdn.net/zidier215/article/details/151332225?sharetype=blogdetail&sharerId=151332225&sharerefer=PC&sharesource=zidier215&spm=1011.2480.3001.8118
https://www.calcguide.tech/2025/09/08/get-robust-list系统调用及示例/
2. 函数原型
1 2 3 4 5 6
| #include <linux/futex.h> #include <sys/syscall.h> #include <unistd.h>
long get_robust_list(int pid, struct robust_list_head **head_ptr, size_t *len_ptr);
|
注意:该函数不是标准 C 库的一部分,需要通过 syscall() 调用。
3. 功能
获取指定进程的健壮互斥锁列表信息。返回的信息包括指向健壮列表头的指针和列表的长度。
4. 参数
int pid: 进程 ID
0: 获取当前进程的健壮列表
正整数: 获取指定进程的健壮列表
struct robust_list_head **head_ptr: 指向指针的指针,用于接收健壮列表头的地址
size_t *len_ptr: 指向 size_t 的指针,用于接收列表长度
5. robust_list_head 结构体定义
1 2 3 4 5 6 7 8 9 10
| struct robust_list { struct robust_list *next; };
struct robust_list_head { struct robust_list list; long futex_offset; unsigned long list_op_pending; };
|
6. 返回值
成功时返回 0
失败时返回 -1,并设置 errno
7. 常见 errno 错误码
8. 相似函数,或关联函数
set_robust_list(): 设置当前进程的健壮互斥锁列表
futex(): futex 系统调用
pthread_mutexattr_setrobust(): 设置 pthread 互斥锁为健壮类型
pthread_mutex_consistent(): 标记健壮互斥锁为一致状态
/proc/[pid]/maps: 查看进程内存映射
/proc/[pid]/status: 查看进程状态信息
9. 示例代码
示例1:基本使用 - 获取当前进程的健壮列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> #include <linux/futex.h> #include <errno.h> #include <string.h>
#ifndef SYS_get_robust_list # define SYS_get_robust_list 275 // x86_64 架构下的系统调用号 #endif
int main() { struct robust_list_head *head; size_t len; long result; printf("=== 获取当前进程的健壮互斥锁列表 ===\n"); printf("当前进程 PID: %d\n", getpid()); // 获取当前进程的健壮列表 result = syscall(SYS_get_robust_list, 0, &head, &len); if (result == -1) { printf("get_robust_list 调用失败\n"); printf("errno = %d: %s\n", errno, strerror(errno)); switch (errno) { case EPERM: printf("权限不足\n"); break; case ENOSYS: printf("系统不支持健壮互斥锁功能\n"); break; default: printf("其他错误\n"); break; } return 1; } printf("成功获取健壮列表信息:\n"); printf(" 列表头地址: %p\n", (void*)head); printf(" 列表长度: %zu 字节\n", len); if (head == NULL) { printf(" 当前进程没有设置健壮列表\n"); } else { printf(" 已设置健壮列表\n"); } return 0; }
|
示例2:健壮互斥锁的实际使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <errno.h> #include <string.h> #include <sys/syscall.h> #include <linux/futex.h>
#ifndef SYS_get_robust_list # define SYS_get_robust_list 275 #endif #ifndef SYS_set_robust_list # define SYS_set_robust_list 275 #endif
pthread_mutex_t robust_mutex = PTHREAD_MUTEX_INITIALIZER;
void* worker_thread(void *arg) { int thread_id = *(int*)arg; int ret; printf("线程 %d: 尝试获取健壮互斥锁\n", thread_id); ret = pthread_mutex_lock(&robust_mutex); if (ret == EOWNERDEAD) { printf("线程 %d: 检测到锁持有者已死亡\n", thread_id); printf("线程 %d: 标记互斥锁为一致状态\n", thread_id); pthread_mutex_consistent(&robust_mutex); } else if (ret != 0) { printf("线程 %d: 获取锁失败: %s\n", thread_id, strerror(ret)); return NULL; } printf("线程 %d: 成功获取锁,执行临界区代码\n", thread_id); // 模拟一些工作 sleep(2); printf("线程 %d: 释放锁\n", thread_id); pthread_mutex_unlock(&robust_mutex); return NULL; }
void check_robust_list() { struct robust_list_head *head; size_t len; long result; result = syscall(SYS_get_robust_list, 0, &head, &len); if (result == 0) { printf("健壮列表状态:\n"); printf(" 列表头: %p\n", (void*)head); printf(" 长度: %zu 字节\n", len); } }
int main() { pthread_t thread1, thread2; int id1 = 1, id2 = 2; int ret; printf("=== 健壮互斥锁演示 ===\n"); // 设置互斥锁为健壮类型 pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); pthread_mutex_init(&robust_mutex, &attr); printf("已创建健壮互斥锁\n"); check_robust_list(); // 创建第一个线程 ret = pthread_create(&thread1, NULL, worker_thread, &id1); if (ret != 0) { printf("创建线程1失败: %s\n", strerror(ret)); return 1; } // 等待一段时间,让第一个线程获取锁 sleep(1); // 创建第二个线程 ret = pthread_create(&thread2, NULL, worker_thread, &id2); if (ret != 0) { printf("创建线程2失败: %s\n", strerror(ret)); return 1; } // 等待线程完成 pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("所有线程执行完成\n"); check_robust_list(); // 清理 pthread_mutex_destroy(&robust_mutex); pthread_mutexattr_destroy(&attr); return 0; }
|
示例3:获取其他进程的健壮列表信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/syscall.h> #include <linux/futex.h> #include <errno.h> #include <string.h> #include <sys/wait.h>
#ifndef SYS_get_robust_list # define SYS_get_robust_list 275 #endif
void check_process_robust_list(pid_t pid) { struct robust_list_head *head; size_t len; long result; printf("检查进程 %d 的健壮列表:\n", pid); result = syscall(SYS_get_robust_list, pid, &head, &len); if (result == -1) { printf(" 获取失败: %s\n", strerror(errno)); switch (errno) { case EPERM: printf(" 权限不足,无法查看其他进程信息\n"); break; case ESRCH: printf(" 进程不存在\n"); break; default: break; } } else { printf(" 成功获取信息:\n"); printf(" 列表头地址: %p\n", (void*)head); printf(" 列表长度: %zu 字节\n", len); if (head == NULL) { printf(" 该进程未设置健壮列表\n"); } else { printf(" 该进程已设置健壮列表\n"); } } printf("\n"); }
int main() { pid_t child_pid; int status; printf("=== 进程健壮列表检查 ===\n"); // 检查当前进程 check_process_robust_list(0); // 当前进程 // 检查 init 进程 check_process_robust_list(1); // 创建子进程进行测试 child_pid = fork(); if (child_pid == -1) { perror("fork 失败"); return 1; } if (child_pid == 0) { // 子进程 printf("子进程 PID: %d\n", getpid()); // 子进程睡眠一段时间 sleep(5); exit(0); } else { // 父进程 printf("父进程 PID: %d\n", getpid()); printf("子进程 PID: %d\n", child_pid); // 检查子进程 sleep(1); // 等待子进程启动 check_process_robust_list(child_pid); // 等待子进程结束 waitpid(child_pid, &status, 0); printf("子进程已结束\n"); // 再次检查已结束的进程 check_process_robust_list(child_pid); } return 0; }
|
10. 健壮互斥锁的工作原理
健壮互斥锁的核心机制:
列表维护: 每个进程维护一个健壮互斥锁列表
异常检测: 当持有锁的进程异常终止时,内核检测到
自动清理: 内核自动将锁标记为”所有者死亡”状态
状态恢复: 下一个尝试获取锁的线程收到 EOWNERDEAD 错误
一致性标记: 获得锁的线程必须调用 pthread_mutex_consistent() 标记锁为一致状态
11. pthread 健壮互斥锁使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <pthread.h> #include <stdio.h> #include <errno.h> #include <string.h>
pthread_mutex_t robust_mutex;
void setup_robust_mutex() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST); pthread_mutex_init(&robust_mutex, &attr); pthread_mutexattr_destroy(&attr); }
void use_robust_mutex(int thread_id) { int ret; ret = pthread_mutex_lock(&robust_mutex); switch (ret) { case 0: printf("线程 %d: 成功获取锁\n", thread_id); break; case EOWNERDEAD: printf("线程 %d: 检测到锁所有者死亡\n", thread_id); // 检查数据一致性并恢复 // ... 数据恢复代码 ... pthread_mutex_consistent(&robust_mutex); printf("线程 %d: 锁状态已恢复\n", thread_id); break; case ENOTRECOVERABLE: printf("线程 %d: 锁不可恢复,需要重新初始化\n", thread_id); pthread_mutex_destroy(&robust_mutex); setup_robust_mutex(); return; default: printf("线程 %d: 获取锁失败: %s\n", thread_id, strerror(ret)); return; } // 临界区代码 printf("线程 %d: 执行临界区操作\n", thread_id); sleep(1); pthread_mutex_unlock(&robust_mutex); printf("线程 %d: 释放锁\n", thread_id); }
|
12. 实际应用场景
健壮互斥锁主要用于:
多进程共享内存: 防止进程崩溃导致其他进程死锁
关键系统服务: 提高系统稳定性和可靠性
数据库系统: 保护共享数据结构
实时系统: 确保系统的可预测性
高可用性应用: 减少单点故障影响
总结
get_robust_list 是管理健壮互斥锁的重要系统调用,关键要点:
健壮性保障: 防止进程崩溃导致的死锁问题
异常处理: 提供 EOWNERDEAD 机制处理锁所有者死亡情况
权限控制: 访问其他进程信息需要适当权限
现代替代: pthread 提供了更高层的健壮互斥锁接口
系统安全: 需要谨慎使用,避免安全风险
在编写高可靠性多线程程序时,健壮互斥锁是一个重要的同步原语,能够显著提高程序的健壮性。