get_robust_list系统调用及示例

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 错误码

  • EPERM: 权限不足(尝试获取其他进程信息时需要适当权限)

  • ESRCH: 指定的进程不存在

  • EINVAL: 无效的参数

  • EFAULT: 指针参数指向无效内存地址

  • ENOSYS: 系统不支持该功能

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 提供了更高层的健壮互斥锁接口

系统安全: 需要谨慎使用,避免安全风险

在编写高可靠性多线程程序时,健壮互斥锁是一个重要的同步原语,能够显著提高程序的健壮性。

data-ad-format="auto" data-full-width-responsive="true">