"proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。"
这里将介绍如何从/proc文件系统中获取与防火墙相关的一些性能参数,以及如何通过/proc文件系统修改内核的相关配置。
1、从/proc文件系统获取相关的性能参数
cpu使用率:/proc/stat
内存使用情况: /proc/meminfo
网络负载信息:/proc/net/dev
相应的计算方法:
(1) 处理器使用率
(2) 内存使用率
(3) 流入流出数据包
(4) 整体网络负载
这些数据分别要从/proc/stat、/proc/net/dev、/proc/meminfo三个文件中提取。
(1) 处理器使用率
这里要从/proc/stat中提取四个数据:用户模式(user)、低优先级的用户模式(nice)、内核模式(system)以及空闲的处理器时间(idle)。它们均位于/proc/stat文件的第一行。
这个是通过cat命令获取的Android的CUP信息。
以上数据对应的意义为:
(User)5215 (nice)170 (System)3640 (Idle)5001 (iowait)63 (Irq)5 (sotfirq)18 0 0
CPU利用率 = 100 *(user + nice + system)/(user + nice + system + idle)
(2) 内存使用率
这里需要从/proc/meminfo文件中提取两个数据,当前内存的使用量(cmem)以及内存总量(amem)。
内存使用百分比 = 100 * (cmem / umem)
(3) 网络利用率
为了得到网络利用率的相关数据,需要从/proc/net/dev文件中获得两个数据:从本机输出的数据包数,流入本机的数据包数。它们都位于这个文件的第四行。
性能收集程序开始记录下这两个数据的初始值,以后每次获得这个值后均减去这个初始值即为从集群启动开始从本节点通过的数据包。
利用上述数据计算出网络的平均负载,方法如下:
平均网络负载 = (输出的数据包+流入的数据包) / 2
2. 通过/proc文件系统调整相关的内核配置
允许ip转发 /proc/sys/net/ipv4/ip_forward
禁止ping/proc/sys/net/ipv4/icmp_echo_ignore_all
可以在命令行下直接往上述两个“文件”里头写入"1"来实现相关配置,如果写入"0"将取消相关配置。不过在系统重启以后,这些配置将恢复默认设置,所以,如果想让这些修改生效,可以把下面的配置直接写入/etc/profile文件,或者其他随系统启动而执行的程序文件中。
1. echo 1 > /proc/sys/net/ipv4/ip_forward
2. echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
如果需要获取其他的性能参数,或者需要对内核进行更多的配置,可以参考proc文件系统介绍,也可以直接通过man proc查看相关的信息。
这些也同样适合Android系统,如果要获取Android系统的Cpu、内存、网络的利用情况,就可以通过读取proc文件系统中的文件。
网络的数据格式
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 31456 705 0 0 0 0 0 0 31456 705 0 0 0 0 0 0
usb0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
tunl0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
gre0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
svnet0: 6016 290 0 0 0 0 0 0 2129 130 0 0 0 0 0 0
eth0: 177509 677 0 0 0 0 0 0 33802 291 0 0 0 0 0 0
android手机流量信息系统是LINUX内核 记录在/proc/self/net/dev文件里面
我们可以看看dev文件的格式
Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
D:/Program Files/Java/sdk/android-sdk-windows/tools>adb shell
# cd proc
cd proc
# cd net
cd net
# cat dev
cat dev
Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packe ts errs drop fifo colls carrier compressed
lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth0: 7069733 86239 0 0 0 0 0 0 12512463 741 79 0 0 0 0 0 0
tunl0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
gre0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 #
我们要获取流量可以通过这个文件进行读取
我读取的源代码如下
1. import java.io.BufferedReader;
2. import java.io.File;
3. import java.io.FileInputStream;
4. import java.io.FileNotFoundException;
5. import java.io.FileOutputStream;
6. import java.io.FileReader;
7. import java.io.IOException;
8. import java.util.Calendar;
9. import org.apache.http.util.EncodingUtils;
10. import android.app.Service;
11. import android.content.Intent;
12. import android.os.Handler;
13. import android.os.IBinder;
14. import android.widget.Toast;
15.
16. /* */
17.
18. public class mService1 extends Service
19. {
20. private Handler objHandler = new Handler();
21. private int intCounter = 0;
22. private int mHour;
23. private int mMinute;
24. private int mYear;
25. private int mMonth;
26. private int mDay;
27. private String mdate;
28.
29. final public String DEV_FILE = "/proc/self/net/dev";// 系统流量文件
30. "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
31. "0", "0", "0", "0", "0" };
32. "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
33. "0", "0", "0", "0", "0", "0" };
34. "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
35. "0", "0", "0", "0", "0", "0" };
36. "0,0,0,0,0,0,0,0,0,0,0,0";// 对应on.txt里面的格式
37.
38. final String ETHLINE = " eth0";// eth是以太网信息 tiwlan0 是 Wifi rmnet0 是 GPRS
39. final String GPRSLINE = "rmnet0";
40. //转载时此处为tiwlan0, 但发现在我的2.1的手机上为wlan0
41. final String WIFILINE = " wlan0";
42. final String TEXT_ENCODING = "UTF-8";
43. final public String ONPATH = "/data/data/zy.dnh/on.txt";
44. final public String LOGPATH = "/data/data/zy.dnh/log.txt";
45.
46. private Runnable mTasks = new Runnable()
47. {
48. public void run()// 运行该服务执行此函数
49. {
50. refresh();
51. intCounter++;
52. // DisplayToast("Counter:"+Integer.toString(intCounter));
53. 3000);// 每3000毫秒执行一次
54. }
55. };
56.
57. @Override
58. public void onStart(Intent intent, int startId)
59. {
60. // TODO Auto-generated method stub
61. 0);
62. super.onStart(intent, startId);
63. }
64.
65. @Override
66. public void onCreate()
67. {
68. // TODO Auto-generated method stub
69. super.onCreate();
70. }
71.
72. @Override
73. public IBinder onBind(Intent intent)
74. {
75. // TODO Auto-generated method stub
76. return null;
77. }
78.
79. @Override
80. public void onDestroy()
81. {
82. // TODO Auto-generated method stub
83. /* */
84. objHandler.removeCallbacks(mTasks);
85. super.onDestroy();
86. }
87.
88. public void DisplayToast(String str)
89. {
90. this, str, Toast.LENGTH_SHORT).show();
91. }
92.
93. public void readdev()
94. {
95. null;
96. try {
97. new FileReader(DEV_FILE);
98. }
99. catch (FileNotFoundException e) {
100. "Could not read " + DEV_FILE);
101. }
102.
103. new BufferedReader(fstream, 500);
104. String line;
105. String[] segs;
106. String[] netdata;
107. int count = 0;
108. int k;
109. int j;
110. try {
111. while ((line = in.readLine()) != null) {
112. ":");
113. if (line.startsWith(ETHLINE))
114. {
115. 1].trim().split(" ");
116. for (k = 0, j = 0; k < netdata.length; k++)
117. {
118. if (netdata[k].length() > 0)
119. {
120. ethdata[j] = netdata[k];
121. j++;
122. }
123. }
124. }
125. else if (line.startsWith(GPRSLINE))
126. {
127. 1].trim().split(" ");
128. for (k = 0, j = 0; k < netdata.length; k++)
129. {
130. if (netdata[k].length() > 0)
131. {
132. gprsdata[j] = netdata[k];
133. j++;
134. }
135. }
136. }
137. else if (line.startsWith(WIFILINE))
138. {
139. 1].trim().split(" ");
140. for (k = 0, j = 0; k < netdata.length; k++)
141. {
142. if (netdata[k].length() > 0)
143. {
144. wifidata[j] = netdata[k];
145. j++;
146. }
147. }
148. }
149. count++;
150. }
151.
152. fstream.close();
153. }
154. catch (IOException e) {
155. DisplayToast(e.toString());
156. }
157.
158. }
159.
160. public String getinfo(String path)
161. {
162. File file;
163. "";
164. FileInputStream in;
165. try {
166. // 打开文件file的InputStream
167. new File(path);
168. new FileInputStream(file);
169. // 将文件内容全部读入到byte数组
170. int length = (int) file.length();
171. byte[] temp = new byte[length];
172. 0, length);
173. // 将byte数组用UTF-8编码并存入display字符串中
174. str = EncodingUtils.getString(temp, TEXT_ENCODING);
175. // 关闭文件file的InputStream
176. in.close();
177. }
178. catch (IOException e) {
179. DisplayToast(e.toString());
180. }
181.
182. return str;
183. }
184.
185. public void writefile(String str, String path)
186. {
187. File file;
188. FileOutputStream out;
189. try {
190. // 创建文件
191. new File(path);
192. file.createNewFile();
193. // 打开文件file的OutputStream
194. new FileOutputStream(file);
195. String infoToWrite = str;
196. // 将字符串转换成byte数组写入文件
197. out.write(infoToWrite.getBytes());
198. // 关闭文件file的OutputStream
199. out.close();
200. catch (IOException e) {
201. // 将出错信息打印到Logcat
202. DisplayToast(e.toString());
203. }
204. }
205.
206. public void refresh()
207. {
208. // 读取本次开机之后直到当前系统的总流量
209. 0] + "," + ethdata[1] + "," + ethdata[8] + ","
210. 9] + ","
211. 0] + "," + gprsdata[1] + "," + gprsdata[8] + ","
212. 9] + ","
213. 0] + "," + wifidata[1] + "," + wifidata[8] + ","
214. 9];
215.
216. // 读取on.txt记录到onstr里
217. ",");// 将onstr各项分离 放到ondata里
218. // 计算增量
219.
220. int[] delta = new int[12];
221. 0] = Integer.parseInt(ethdata[0]) - Integer.parseInt(ondata[0]);
222. 1] = Integer.parseInt(ethdata[1]) - Integer.parseInt(ondata[1]);
223. 2] = Integer.parseInt(ethdata[8]) - Integer.parseInt(ondata[2]);
224. 3] = Integer.parseInt(ethdata[9]) - Integer.parseInt(ondata[3]);
225. 4] = Integer.parseInt(gprsdata[0]) - Integer.parseInt(ondata[4]);
226. 5] = Integer.parseInt(gprsdata[1]) - Integer.parseInt(ondata[5]);
227. 6] = Integer.parseInt(gprsdata[8]) - Integer.parseInt(ondata[6]);
228. 7] = Integer.parseInt(gprsdata[9]) - Integer.parseInt(ondata[7]);
229. 8] = Integer.parseInt(wifidata[0]) - Integer.parseInt(ondata[8]);
230. 9] = Integer.parseInt(wifidata[1]) - Integer.parseInt(ondata[9]);
231. 10] = Integer.parseInt(wifidata[8])- Integer.parseInt(ondata[10]);
232. 11] = Integer.parseInt(wifidata[9])- Integer.parseInt(ondata[11]);
233.
234. // 读取log.txt
235. // 获取当前时间
236. final Calendar c = Calendar.getInstance();
237. // 获取当前年份
238. 1;// 获取当前月份
239. // 获取当前月份的日期号码
240. // 获取当前的小时数
241. // 获取当前的分钟数
242. "-" + mMonth + "-" + mDay;
243. // 将log.txt的内容读到text字符串中
244. "/n");
245. 1];// 获得今日已记录流量
246. ",");
247.
248. // 检查文件最后一行是否为今天的流量记录信息
249. if (!beToday[0].equals(mdate))// 如果文件只有一行,表明目前日志为空,将当前日期加入
250. // 判断今日流量是否已经记录,如果今日流量没有记录
251. {
252. ",0,0,0,0,0,0,0,0,0,0,0,0/n";
253. writefile(text, LOGPATH);
254. "/n");
255. 1];// 获得今日已记录流量
256. ",");
257. }
258.
259. int i;
260. // 处理今日流量
261. int[] newTodaydata = new int[12];// 表示今日流量
262. String newtoday = mdate;
263. for (i = 0; i <= 11; i++)
264. {
265. 1]) + delta[i];
266. "," + newTodaydata[i];
267. }
268.
269. "/n";
270. 0].split(",");
271. int[] newTotaldata = new int[12];// 表示总流量数值
272. // 更新第一行
273. "total";
274. for (i = 0; i <= 11; i++)
275. {
276. 1]) + delta[i];// 总流量数值+delta[i]更新
277. "," + newTotaldata[i];
278. }
279.
280. "/n";
281. // 处理中间不变的部分
282. "";// before为之前的从第1行到昨天的流量记录
283. for (i = 1; i <= line.length - 2; i++)
284. "/n";// 代表中间不变的部分
285.
286. String newlog = newtotal + before + newtoday;
287. // 更新流量记录
288. // 更新log*/
289. }
290. }