观察Linux行为(通过/proc)

/proc虚拟文件系统(procfs)是Unix操作系统中用于访问内核数据的特殊文件系统。本篇详细介绍了/proc文件系统中几个关键文件的内容及其作用,如/proc/loadavg、/proc/meminfo等,这些文件提供了系统负载、内存使用情况等重要信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

节选自赛迪网
引用:
/proc虚拟文件系统

  /proc虚拟文件系统(也叫procfs)是Unix操作 系统所使用的虚拟文件系统的Linux实现,包括Sun Solaris、LinuxBSD。在/proc开始时,它以一个标准文件系统出现,并包含与正在运行的进程IDs同样名字的文件。然而,在/proc中的文件不占用磁盘空间,它们存在于工作存储器(内存)中。/proc最初的目的是便于进程信息的存取,但是现在,在Linux中,它可被内核的每一部分使用来报告某些事情。

  在/proc文件系统提供的成百上千的值当中,我们将集中考虑集群监控所需的最小集,它们包括?

  ◆ /proc/loadavg:包含系统负载平均值;

  ◆ /proc/meminfo:包含存储管理统计量;

  ◆ /proc/net/dev:包含网卡度量;

  ◆ /proc/stat:包含内核统计量;

  ◆ /proc/uptime:包含总的系统正常工作时间及空闲时间。

  每个文件提供的值的数量是不同的。这些文件的完整有效值列表如下。

  ◆ /proc/loadavg提供以下数据:

  1秒钟平均负载;

  5秒钟平均负载;

  15秒钟平均负载;

  总作业数;

  正在运行的作业总数。

  ◆ /proc/meminfo提供的存储器信息包括:

  活动存储器;

  不活动存储器;

  缓冲存储器;

  高速缓冲存储器;

  总的自由存储器;

  总的高位存储器;

  自由高位存储器;

  总的低位存储器;

  自由低位存储器;

  共享存储器;

  交换存储器;

  交换高速缓冲存储器;

  交换自由存储器;

  总存储器。

  ◆ /proc/net/dev中包括每个网卡的如下数据:

  接收到的字节;

  接收到的压缩字节;

  收到的误码数;

  收到的漏失误码;

  收到的FIFO误码;

  收到的帧误码;

  收到的多播误码;

  收到的总包数;

  已传输的字节;

  已传输的压缩字节;

  传输误码总数;

  传输载波误码;

  传输冲突误码;

  传输漏失误码;

  传输FIFO误码;

  传输的总包数。
◆ /proc/stat提供:

  引导时间;

  上下文切换数量;

  中断总量;

  进页面总数;

  出页面总数;

  进程总数;

  换入总数;

  换出总数;

  合计CPU空闲时间;

  合计CPU nice时间;

  合计CPU系统时间;

  合计CPU用户时间。

  同时提供对每个CPU的:

  单个CPU空闲时间;

  单个CPU nice时间;

  单个CPU系统时间;

  单个CPU用户时间。

  以及对每个磁盘驱动器的如下数据:

  单个磁盘块读;

  单个磁盘块写;

  单个磁盘I/O总数;

  单个磁盘I/O读;

  单个磁盘I/O写。

  ◆ /proc/uptime中包括:

  系统总工作时间;

  系统总空闲时间。


关于/proc的一些东西还可以参考:http://www.linuxfans.org/nuke/modules.php?name=News&file=article&op=view&sid=2609

在/proc,我们可以看到很多原来在内核理论里看到的东西,像时间片、上下文转换、进程的相关内容......它们现在就活生生的在我们面前,我们可以通过查看、修改这些值,来了解现在就在我们电脑上运行的这个linux。
下面是一个用C写的小程序,编译运行(如果还不会请参看公社的相关版面)以后运行,可以看到CPU型号和内核版本信息。这只是个小小小程序,你可以修改它打开的文件以显示其他的信息,也可以用程序来修改内核的一些参数。
redhat fc5

 

#include  < stdio.h >  

/*  get the NUMth line of a file  */  
char   * getN( char  line[ 200 ], int  n, FILE  * iop) 

   rewind(iop); 
   
int  i; 
   
for ( i  =   1 ; i  <=  n ; i ++  ) 
      fgets(line, 
1000 , iop); 
   
return  line; 


main(
int  argc, char   * argv[]) 

   FILE 
* fp; 
    
char  str[ 200 ]; 
    
   
if ((fp  =  fopen( " /proc/cpuinfo " , " r " )) == NULL){ 
      printf(
" Open Error " ); 
      
return
   } 
   getN(str,
5 ,fp); 
   printf(
" %s " ,str); 
   fclose(fp); 

   
if ((fp  =  fopen( " /proc/version " , " r " )) == NULL){ 
      printf(
" Open Error " ); 
      
return
   } 
   getN(str,
1 ,fp); 
   printf(
" %s " ,str); 
   fclose(fp); 

<think>好的,我现在需要回答用户关于`openat /proc/self/exe`返回值的问题。首先,我得回忆一下Linux系统中/proc文件系统的基本知识。/proc是一个虚拟文件系统,提供了进程和系统信息。其中,/proc/self是一个符号链接,指向当前进程的目录。而/proc/self/exe则指向当前进程的可执行文件。 接下来,openat系统调用用于相对于目录文件描述符打开文件。当使用openat并传入AT_FDCWD作为dirfd参数时,它的行为类似于open,但允许相对路径。但用户的问题里没有指定dirfd,直接用了/proc/self/exe,所以可能需要确认参数结构。不过用户可能简化了问题,重点在于打开/proc/self/exe的行为。 当进程调用openat打开/proc/self/exe时,实际上是在尝试以某种方式访问当前进程的可执行文件。在Linux中,/proc/self/exe是一个符号链接,指向正在执行的程序路径。例如,如果运行的是/bin/bash,那么/proc/self/exe就指向/bin/bash。 使用openat打开这个路径时,系统会返回一个文件描述符,指向该可执行文件。但需要注意权限问题,如果进程没有权限读取自己的可执行文件,可能会失败。例如,如果可执行文件的权限不允许读,或者路径已经被卸载,这时候可能会返回错误,如EACCES或ENOENT。 此外,还有一个特殊情况:当进程执行后,如果原来的可执行文件被删除或替换,/proc/self/exe仍然会指向被删除的文件(inode仍然存在直到所有引用关闭)。这时候打开可能仍然成功,但文件内容可能已经改变,这需要看具体的文件系统行为。 还有可能用户的问题中的openat可能是指直接使用路径,比如dirfd是AT_FDCWD,然后路径是"/proc/self/exe"。这时候openat的行为类似于普通的open,返回可执行文件的文件描述符。 需要确认的是,当打开/proc/self/exe时,返回的是可执行文件本身,而不是符号链接。因为通常打开符号链接时,系统会跟随链接,除非使用O_NOFOLLOW标志。但/proc文件系统中的符号链接可能特殊处理,比如/proc/self/exe本身并不是普通的符号链接,而是一个特殊的入口,直接指向可执行文件。因此,即使使用O_NOFOLLOW,可能也无法阻止解析,或者可能返回其他错误。 另外,测试一下实际的情况可能会有帮助,例如编写一个小程序,调用openat并打印结果,观察返回的文件描述符和读取内容。例如: #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main() { int fd = openat(AT_FDCWD, "/proc/self/exe", O_RDONLY); if (fd == -1) { perror("openat"); return 1; } printf("Opened /proc/self/exe as fd %d\n", fd); close(fd); return 0; } 运行这个程序,应该能成功打开,并得到文件描述符。通过读取该文件描述符,可以获取到可执行文件的内容,即该程序本身的二进制。 但需要注意的是,某些情况下可能无法打开,例如在容器环境中,或者当程序被设置为不可读。例如,如果可执行文件的权限被改为0500(执行但不可读),则打开读取时会失败,返回EACCES。 此外,如果进程是通过execve执行的脚本文件(比如bash脚本),那么/proc/self/exe指向的是解释器的可执行文件,比如/bin/bash,而不是脚本本身。因为脚本是由解释器执行的,解释器才是实际运行的进程。 总结来说,openat打开/proc/self/exe的返回值是一个文件描述符,指向当前进程的可执行文件。成功时返回非负整数,失败时返回-1并设置errno。常见的错误包括权限不足(EACCES)、文件不存在(ENOENT,比如可执行文件被删除但未完全释放)等。 最后,需要将这些信息整理成用户容易理解的中文回答,结构清晰,分步骤说明。</think>`openat(/proc/self/exe)` 的返回值解析如下: --- ### **1. 基础概念** - **`/proc/self/exe`** 是 Linux 虚拟文件系统 `/proc` 中的一个符号链接,指向 **当前进程的可执行文件**。例如: - 若进程是 `/bin/bash`,则 `/proc/self/exe` 指向 `/bin/bash`。 - **`openat()`** 是系统调用,用于打开文件。当以 `/proc/self/exe` 为路径调用时,其行为类似于普通 `open()`,但允许更灵活的路径处理。 --- ### **2. 返回值详解** #### **成功情况** - 返回一个 **非负整数文件描述符**,指向当前进程的可执行文件。 ```c int fd = openat(AT_FDCWD, "/proc/self/exe", O_RDONLY); // 示例调用 ``` - 可通过此文件描述符 **读取可执行文件内容**(需有读权限)。 - 若可执行文件被删除但进程仍在运行,仍可能成功打开(文件 inode 未释放)。 #### **失败情况** - 返回 **-1**,并设置 `errno` 为错误码: - **`EACCES`**:权限不足(如可执行文件无读权限)。 - **`ENOENT`**:文件不存在(如路径错误或文件被彻底删除)。 - **`ELOOP`**:符号链接解析过多(若手动禁用跟随符号链接)。 --- ### **3. 特殊情况** - **脚本文件**:若进程是脚本(如 Bash 脚本),`/proc/self/exe` 指向 **解释器**(如 `/bin/bash`),而非脚本本身。 - **容器环境**:在容器中可能返回容器内的可执行文件路径,而非宿主机路径。 - **文件权限**:若可执行文件权限为 `0500`(仅执行,不可读),`openat()` 会失败。 --- ### **4. 验证示例** 编写测试程序验证行为: ```c #include <fcntl.h> #include <stdio.h> #include <unistd.h> int main() { int fd = openat(AT_FDCWD, "/proc/self/exe", O_RDONLY); if (fd == -1) { perror("openat"); return 1; } printf("成功打开,文件描述符:%d\n", fd); close(fd); return 0; } ``` 运行结果: ``` 成功打开,文件描述符:3 ``` --- ### **5. 应用场景** - **自检程序完整性**:读取自身可执行文件,进行哈希校验。 - **动态加载代码**:从自身文件映射内存(需结合 `mmap`)。 - **调试工具**:获取进程的原始执行文件路径。 --- ### **总结** `openat(/proc/self/exe)` 主要用于访问进程自身的可执行文件。返回值取决于文件是否存在、权限及环境配置,正确使用时能可靠获取文件描述符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值