博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
特殊文件(下)
阅读量:4648 次
发布时间:2019-06-09

本文共 6311 字,大约阅读时间需要 21 分钟。

 

特殊文件这一章讲了两种特殊文件,一种是符号链接一种是proc文件系统。/proc目录下的文件是系统运行进程的映像,它是一个伪文件系统,这些文件只存在于内存之中,不占用外部存储空间。

proc文件系统不是普通意义上的文件系统,它既是一个到运行进程地址空间的访问接口,同时又是一个访问内核数据的结构。用户和应用程序可以通过proc得到系统的信息和运行中的进程信息,这是两个主要的功能。能够访问系统内核的信息,同时也能修改内核的信息,达到配置系统的目的。

对于proc文件系统两个不同的功能,设计了两个不同的程序进行测试。

1、读取内核信息

内核信息包括很多,其中包括:

(1)CPU型号和类型

(2)使用的Linux内核版本

(3)从系统最后一次启动以来经历的时间

(4)总共有多少CPU时间执行在用户态、系统态和空闲态。

(5)配置内存大小

(6)当前可用内存数

(7)磁盘读写请求数

(8)内核已经进行多少次进程上下文切换

(9)从系统创建以来创建的进程数

(10)平均系统负载列表

(11)系统最后的启动时间

测试程序分为三个版本,STANDARD版本、SHORT版本和LONG版本。STANDARD版本输出(1)、(2)、(3);SHORT版本输出(4)、(7)、(8)、(9)、(11);LONG版本输出(5)、(6)、(10)。

int get_load_avg(){       char line_buf[MAX];       int fd;       int n;       int res = -1;       if((fd = open("/proc/loadavg", O_RDONLY)) == -1){ /* 打开存储系统平均负载的porc文件 */              perror("fail to loadavg");              return -1;}       if((n = read(fd, line_buf, MAX)) == -1){ /* 读取系统平均负载的内容 */              perror("fail to read");             goto err;       }       line_buf[n] = '\0';       printf("Average Load: %s", line_buf); /* 输出系统的负载 */       res = 0;err:       close(fd); /* 关闭文件 */       return res;}/* 在指定的proc文件中查找需要的内核信息,成功返回0,失败返回-1。* path : 指定的proc文件的路径* name : 所要查找的内核信息 */int search(char *path, char *name){       int fd;       char char_all[MAX] = "\0";       char line_buf[MAX] = "\0";       char *p;       char *s;       int n;       int res = -1;       if((fd = open(path ,O_RDONLY)) == -1){ /* 打开指定的proc文件 */              perror("fail to open");              return -1;       }       if((n = read(fd, char_all, MAX)) == -1){ /* 将文件内容读入缓冲区 */              perror("fail to read");              goto err;       }       char_all[n] = '\0';       p = strstr(char_all, name);    /* 搜索name表示的内核信息,strstr函数查找字符串,返回该字符串的地址 */       s = strstr(p, "\n");         /* 这一行就是所需要的内核信息 */       n = s - p + 1;       strncpy(line_buf, p, n);       printf("%s\n",line_buf);   /* 输出缓冲区的内容 */       res = 0;err:       close(fd);       return res;}

上边的代码中也可以看出来对于proc文件的操作就是用到文件操作的read函数、open函数和write函数等。上边自己写的代码中search函数是先将内容读到一个字符串中,然后根据寻找字符串中需要查找的字符串返回要查找字符串的首地址,从该首地址往后一直读,直到换行符号,这一段都是要读取的信息,这个对于字符串的操作是一个很好的例子,以后程序中可以借鉴。

主函代码如下:

#include "common.h"int main(int argc,char *argv[]){       char c1,c2;       int interval;       int duration;       int intervation = 0;       int reportType = 0;             char repTypeName[16];       struct timeval now;       reportType = STANDARD;                              /* 该程序默认使用STANDARD版本 */       strcpy(repTypeName,"Standard");       if(argc>1){              sscanf(argv[1],"%c%c",&c1,&c2);   /* 得到该程序的命令行参数 */              if(c1 != '-'){ /* 命令行参数出错 */                     printf("wrong command]\n");                     exit(1);              }              if(c2 == 's'){ /* -s使用SHORT版本 */                     reportType = SHORT;                     strcpy(repTypeName,"Short");              }else if(c2 == 'l'){ /* -l 使用LONG版本 */                     reportType = LONG;                     strcpy(repTypeName,"Long");                     interval = atoi(argv[2]); /* 得到两个参数,分别是取平均系统负载的时间间隔和总时长 */                     duration = atoi(argv[3]);              }       }       gettimeofday(&now,NULL);                      /* 得到当前的系统时间 */       /* 输出版本的类型,standard、short和long */       printf("Status report:  %s\nat the time of : %s\n", TypeName,(char *)ctime(&(now.tv_sec)));       /* 输出主机名,该信息存储在/proc/sys/kernel/hostname文件中 */       printf("the hostname is: ");       search( "/proc/sys/kernel/hostname" , "" );       switch(reportType){       case 0:                                                    /* STANDARD版本 */            search( "/proc/cpuinfo" , "model name" ); /* CPU的类型和型号 */              search( "/proc/version" , "" );       /* 所使用的Linux内核的版本 */              break;       case 1:                                                    /* SHORT版本 */              search( "/proc/stat" , "cpu" ); /* 总共有多少CPU时间执行在用户态、系统态和空闲态 */              search( "/proc/stat" , "intr" ); /* 磁盘读写请求数 */              search( "/proc/stat" , "ctxt" ); /* 内核已经进行了多少次进程上下文的切换 */              search( "/proc/stat" , "btime" ); /*系统最后的启动时间*/              search( "/proc/stat" , "processes" ); /* 从系统启动以来创建的进程数 */              break;       case 2: /* LONG版本 */              search( "/proc/meminfo" , "MemTotal" ); /* 配置内存的大小 */              search( "/proc/meminfo" , "MemFree" ); /* 当前可用内存数 */              while(intervation < duration){ /* 取得平均系统负载 */                     sleep(interval);                     if(get_load_avg() == -1)                            exit(1);                     intervation += interval;              }              break;       default:              printf("should not be here\n");       }       return 0;}

主函数主要判断输入是否错误,不同输入对应不同的输出版本,这种对于外部输入的判断在以后程序中也会经常遇到,可以作为一种参考。

头文件common.h如下:

#include 
#include
#include
#include
#include
#include
#define MAX 4096#define STANDARD 0#define SHORT 1#define LONG 2extern int search(char *path,char *name);extern int get_load_avg();

2、读取进程状态

proc文件系统下有一个self的子目录,该目录中存储的就是当前正在执行的进程的状态信息,这些状态信息存储在数据结构中,proc文件系统提供了一个和这些信息交互的接口,如果需要知道当前正在运行的进程的信息,可以通过proc文件系统来获取,需要访问/proc/self/task/“进程号”/status文件可以得到这些信息。

下面是一个实例代码显示当前进程的信息:

#include 
#include
#include
#include
#include
#define MAX 1024#define PID 6#define PATH_SIZE 128int main(void){ FILE *fp; pid_t pid; char pid_str[PID]; char path[PATH_SIZE]; char buf[MAX]; pid = getpid(); /* 得到进程ID */ sprintf(pid_str, "%d", pid); /* 将进程ID由数字转换为字符串 */ strcpy(path, "/proc/self/task/"); /* 拼接路径,打开"/proc/self/task/进程ID"目录下的status文件 */ strcat(path, pid_str); strcat(path, "/status"); fp = fopen(path, "r"); /* 打开该文件,以只读的方式打开 */ if(fp == NULL){ perror("fail to open"); exit(1); } while(fgets(buf, MAX, fp) != NULL) /* 顺序读取每一行,并且打印 */ printf("%s", buf); fclose(fp); /* 关闭文件 */ return 0;}

这个实例程序中对于文件的操作还是基本的文件操作,关键在于路径的拼接,先要获得进程ID,将进程ID转换成字符串,将进程ID字符串拼接到路径中,然后根据这个路径去打开文件,逐行打印。这也是一种对于字符串的操作,这种处理方法应该记下来,以后会用得到。

转载于:https://www.cnblogs.com/Mr--Yang/p/6540122.html

你可能感兴趣的文章
java多线程详解(8)-volatile,Atomic比较
查看>>
硬质合金销售真的有那么难么?
查看>>
Struts2(十二)使用验证框架验证数据较验
查看>>
Greenplum-概念篇
查看>>
Thrift 个人实战--Thrift 网络服务模型
查看>>
Day24-Ajax文件上传
查看>>
第五天、LAMP架构
查看>>
【bzoj2060】[Usaco2010 Nov]Visiting Cows拜访奶牛 树形dp
查看>>
【bzoj5110】[CodePlus2017]Yazid 的新生舞会 Treap
查看>>
[archlinux] linux boot process/order/stage
查看>>
[LeetCode]Power
查看>>
ARM处理器详解(2)-Cortex R系列
查看>>
单KEY业务,数据库水平切分架构实践
查看>>
绩效考核如何快速评分
查看>>
ssm项目启动,加载数据库连接池时卡住
查看>>
CGRect包含交错,边缘,中心的检测
查看>>
respondsToSelector的相关使用
查看>>
zabbix 自定义监控项 获取nginx监控状态
查看>>
python 并发编程 多线程 目录
查看>>
C main()参数
查看>>