Unix/Linux编程:/proc文件系统

/proc文件系统

在比较老的Unix实现中,通常并无简单方法来获取(或修改)内核属性并回答如下问题:

  • 系统中有多少进程正在运行,其属主是谁?
  • 一个进程已经打开了什么文件
  • 目前锁定了什么文件,哪些进程持有这些锁
  • 系统正在使用什么套接字(socket)

一些老版Unix实现解决这一问题的方法是允许特权级程序深入内核内存中的数据结构。然而,这会带来各种问题。特别是,这要求对内核数据结构具有专业知识,并且这些结构可能因为内核版本的演进而改变。

为了提供更为简便的方法来访问内核信息,很多现代Unix实现提供了一个/proc虚拟文件系统。该文件系统驻留在/proc目录中,包含了各种用于展示内核信息的文件,并允许进程通过常规IO系统调用来方便的读取、修改这些信息。之所以将/proc文件系统称为虚拟,是因为其包含的文件和子目录并未存储在磁盘上,而是由内核在进程访问此类信息时动态创建而成。

类似于Unix实现,Linux也提供了/proc文件系统,由一组目录和文件组成,挂载(mount)在/proc目录下

  • /proc文件系统是一种虚拟文件系统,以文件系统目录和文件组成,提供一个指向内核数据结构的接口。这为查看和改变系统属性开启了方便之门
  • 另外,还能通过一组以/proc/PID形式命名的目录(PID 即进程 ID)查看系统中运行各进程的相关信息

通常,/proc 目录下的文件内容都采取人类可读的文本形式,shell 脚本也能对其进行解析。程序可以打开、读取和写入/proc 目录下的既定文件。大多数情况下,只有特权级进程才能修改/proc 目录下的文件内容

文件系统是对文件和目录的组织集合

获取与进程有关的信息:/proc/PID

对于系统中的每个进程,内核都提供了相应的目录,命名为/proc/PID,其中PID是进程的ID。在此目录中各种文件和子目录包含了进程有关信息。比如,通过查看/proc/1目录下的文件,可以获取init进程的信息,该进程的ID总是为1

  • 每个/proc/PID目录中都存在一个名为status的文件,提供了有关该进程的一系列信息。该文件内容随着时间而改变。当这些文件由多个条目组成时,对其解析应当谨慎从事,在这种情况下,应查找包含特殊字符串(如,PPid)的匹配行记录,而非按照(逻辑)行号来处理文件。
    在这里插入图片描述

  • /proc/PID/fd 目录为进程打开的每个文件描述符都包含了一个符号链接,每个符号链接的名称都与描述符的数值相匹配。例如,/proc/1/fd/1 是 ID 为 1 的进程中指向标准输出的符号链接

  • 为方便起见,任何进程都可使用符号链接/proc/self来访问其自己的/proc/PID 目录

  • 线程:/proc/PID/task 目录

    • Linux2.4增加了线程组的概念,正式支持POSIX线程模型。因为线程组中的一些属性对于线程是唯一的,所以Linux 2.4在/proc/PID目录下增加了一个task子目录。针对进程中的每个线程,内核提供了以/proc/PID/task/TID命名的子目录,其中TID是该线程的线程ID(此值等同于在线程中调用 gettid()函数的返回值)
    • 每个/proc/PID/task/TID子目录中都有一套类似于/proc/PID目录内容的文件和目录。因为线程共享了多个属性,所以这些文件中的很多信息对进程中各个线程而言都是相同的。然而,这些文件也显示了每个线程的独特信息,故而是合理的。例如,在线程组的/proc/PID/task/TID/status文件中,存在那种对每个线程而言,内容都有可能不同的字段,State、Pid、SigPnd、SigBlk、CapInh、CapPrm、CapEff 和 CapBnd 就在此列

下表列举了在每个/proc/PID 目录中的部分其他文件。

文 件描述(进程属性)
cmdline以\0 分隔的命令行参数
cwd指向当前工作目录的符号链接
EnvironNAME=value 键值对环境列表,以\0 分隔
exe指向正在执行文件的符号链接
fd文件目录,包含了指向由进程打开文件的符号链接
maps内存映射
mem进程虚拟内存(在 I/O 操作之前必须调用 lseek()移至有效偏移量)
mounts进程的安装点
root指向根目录的符号链接
status各种信息(比如,进程 ID、凭证、内存使用量、信号)
task为进程中的每个线程均包含一个子目录(始自 Linux 2.6

/proc目录下的系统信息

proc 目录下的各种文件和子目录提供了对系统级信息的访问:
在这里插入图片描述

目录目录中文件表达的信息
/proc各种系统信息
/proc/net有关网络和套接字的状态信息
/proc/sys/fs文件系统相关设置
/proc/sys/kernel各种常规的内核设置
/proc/sys/net网络和套接字的设置
/proc/sys/vm内存管理设置
/proc/sysvipc有关 System V IPC 对象的信息

访问/proc文件

通常使用shell脚本来访问/proc目录下的文件。例如,使用如下 shell 命令,就可以修改和查看/proc 目录下的文件内容
在这里插入图片描述
也可以从程序中使用常规IO系统调用来访问/proc目录下的文件。但在访问这些文件时,有如下一些限制:

  • /proc目录下的一些文件是只读的,即这些文件仅用于显示内核信息,但无法对其进程修改。/proc/PID目录下的大多数文件就属于此类型
    -proc 目录下的一些文件仅能由文件拥有者(或特权级进程)读取。例如,/proc/PID目录下的所有文件都属于拥有相应进程的用户,而且即使是对文件的属主,其中的部分文件(如:proc/PID/environ 文件)也仅仅授予了读权限
  • 除了/proc/PID 子目录中的文件,/proc 目录的其他文件大多属于 root 用户,并且也仅有 root 用户能够修改那些可修改的文件。

访问/proc/PID目录中的文件

/proc/PID目录内容是变化的,每个目录都随着相应进程ID的进程创建而生,又随着进程的终止而灭。这意味着要确定特定/proc/PID目录的存在,,就需要干净利落地处理如下可能性:当打开此目录下的文件时,进程已经终止,并且也已经删除了相应的/proc/PID 目录。


#include <zconf.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <cstring>

#define MAX_LINE 100
int
main(int argc, char *argv[])
{
    int fd;
    char line[MAX_LINE];
    ssize_t n;

    fd = open("/proc/sys/kernel/pid_max", (argc > 1) ? O_RDWR : O_RDONLY);
    if (fd == -1){
        perror("open");
        exit(EXIT_FAILURE);
    }


    n = read(fd, line, MAX_LINE);
    if (n == -1){
        perror("read");
        exit(EXIT_FAILURE);
    }
    if (argc > 1)
        printf("Old value: ");
    printf("%.*s", (int) n, line);

    if (argc > 1) {
        if (lseek(fd, 0, SEEK_SET) == -1){
            perror("lseek");
            exit(EXIT_FAILURE);
        }

        if (write(fd, argv[1], strlen(argv[1])) != strlen(argv[1])){
            perror("write");
            exit(EXIT_FAILURE);
        }

        system("echo /proc/sys/kernel/pid_max now contains "
               "`cat /proc/sys/kernel/pid_max`");
    }

    exit(EXIT_SUCCESS);
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值