Post

proc文件系统

proc文件系统

/proc/self/exe 是 Linux 系统中一个特殊的符号链接,它指向 当前进程的可执行文件 的绝对路径。这个机制在多种场景下非常有用,以下是它的主要用法和示例:


1. 获取当前程序的绝对路径

最常见的用途是 动态获取当前运行程序的完整路径,无需硬编码路径或依赖 argv[0](可能不准确)。

C 语言示例

c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <unistd.h>
#include <stdio.h>

int main() {
    char exe_path[1024];
    ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
    if (len != -1) {
        exe_path[len] = '\0';
        printf("Current executable path: %s\n", exe_path);
    } else {
        perror("readlink");
    }
    return 0;
}

输出示例

text

1
Current executable path: /home/user/my_program

2. 检查程序是否被符号链接调用

通过比较 /proc/self/exeargv[0],可以判断程序是否通过符号链接启动:

c

1
2
3
if (strcmp(exe_path, argv[0]) != 0) {
    printf("Called via symlink: %s\n", argv[0]);
}

3. 重新执行自身(Self-Exec)

某些程序需要 重新启动自己(如升级后),此时可以通过 /proc/self/exe 获取自己的路径:

c

1
execl(exe_path, exe_path, NULL);

4. 安全验证

在安全敏感场景中,验证程序的真实路径是否未被篡改:

c

1
2
3
4
if (strstr(exe_path, "/expected/path/") == NULL) {
    fprintf(stderr, "Security alert: Binary path mismatch!\n");
    exit(1);
}

5. 动态库中获取主程序路径

动态库(.so)可以通过 /proc/self/exe 获取加载它的主程序路径,用于插件或依赖管理。


6. 容器环境中的注意事项

在 Docker 或容器中,/proc/self/exe 仍然指向容器内的路径,但需注意:

  • 如果容器内路径与宿主机不同,可能需要额外处理。
  • 某些容器安全策略(如 proc 文件系统只读)可能限制访问。
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
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  static int count = 0;

  printf("Process started, count = %d\n", count);
  count++;

  if (count < 3) {
    char exe_path[PATH_MAX];
    ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
    if (len == -1) {
      perror("readlink");
      exit(EXIT_FAILURE);
    }
    exe_path[len] = '\0';

    printf("Re-executing: %s\n", exe_path);
    execv(exe_path, argv);  // argv[0] 是程序名,argv 传递原始参数
    perror("execv failed");
    exit(EXIT_FAILURE);
  }

  printf("Final run complete. Exiting.\n");
  return 0;
}
1
2
3
4
5
6
7
8
9
10
Re-executing: /home/gc/Desktop/test
Process started, count = 0
Re-executing: /home/gc/Desktop/test
Process started, count = 0
Re-executing: /home/gc/Desktop/test
Process started, count = 0
Re-executing: /home/gc/Desktop/test
Process started, count = 0
Re-executing: /home/gc/Desktop/test
...
This post is licensed under CC BY 4.0 by the author.