第11章
这章主要讲了关于Linux和UNIX的系统资源的限制。
关于限制都存在一个最小值,这些最小值为<limits.h>文件中的常量。
通过cat 命令查看:
lancelot@debian:~/Code/tlpi$ cat /usr/include/limits.h /* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *//* * ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types <limits.h> */ #ifndef _LIBC_LIMITS_H_ #define _LIBC_LIMITS_H_ 1 #include <features.h> /* Maximum length of any multibyte character in any locale. We define this value here since the gcc header does not define the correct value. */#define MB_LEN_MAX 16 /* If we are not using GNU CC we have to define all the symbols ourself. Otherwise use gcc‘s definitions (see below). */#if !defined __GNUC__ || __GNUC__ < 2 /* We only protect from multiple inclusion here, because all the other #include‘s protect themselves, and in GCC 2 we may #include_next through multiple copies of this file before we get to GCC‘s. */ # ifndef _LIMITS_H # define _LIMITS_H 1 #include <bits/wordsize.h> /* We don‘t have #include_next. Define ANSI <limits.h> for standard 32-bit words. *//* These assume 8-bit `char‘s, 16-bit `short int‘s, and 32-bit `int‘s and `long int‘s. *//* Number of bits in a `char‘. */ # define CHAR_BIT 8/* Minimum and maximum values a `signed char‘ can hold. */ # define SCHAR_MIN (-128) # define SCHAR_MAX 127/* Maximum value an `unsigned char‘ can hold. (Minimum is 0.) */ # define UCHAR_MAX 255/* Minimum and maximum values a `char‘ can hold. */ # ifdef __CHAR_UNSIGNED__ # define CHAR_MIN 0 # define CHAR_MAX UCHAR_MAX # else # define CHAR_MIN SCHAR_MIN # define CHAR_MAX SCHAR_MAX # endif /* Minimum and maximum values a `signed short int‘ can hold. */ # define SHRT_MIN (-32768) # define SHRT_MAX 32767/* Maximum value an `unsigned short int‘ can hold. (Minimum is 0.) */ # define USHRT_MAX 65535/* Minimum and maximum values a `signed int‘ can hold. */ # define INT_MIN (-INT_MAX - 1) # define INT_MAX 2147483647/* Maximum value an `unsigned int‘ can hold. (Minimum is 0.) */ # define UINT_MAX 4294967295U/* Minimum and maximum values a `signed long int‘ can hold. */ # if __WORDSIZE == 64 # define LONG_MAX 9223372036854775807L # else # define LONG_MAX 2147483647L # endif # define LONG_MIN (-LONG_MAX - 1L) /* Maximum value an `unsigned long int‘ can hold. (Minimum is 0.) */ # if __WORDSIZE == 64 # define ULONG_MAX 18446744073709551615UL # else # define ULONG_MAX 4294967295UL # endif # ifdef __USE_ISOC99 /* Minimum and maximum values a `signed long long int‘ can hold. */ # define LLONG_MAX 9223372036854775807LL # define LLONG_MIN (-LLONG_MAX - 1LL) /* Maximum value an `unsigned long long int‘ can hold. (Minimum is 0.) */ # define ULLONG_MAX 18446744073709551615ULL # endif /* ISO C99 */ # endif /* limits.h */#endif /* GCC 2. */ #endif /* !_LIBC_LIMITS_H_ */ /* Get the compiler‘s limits.h, which defines almost all the ISO constants. We put this #include_next outside the double inclusion check because it should be possible to include this file more than once and still get the definitions from gcc‘s header. */#if defined __GNUC__ && !defined _GCC_LIMITS_H_ /* `_GCC_LIMITS_H_‘ is what GCC‘s file defines. */ # include_next <limits.h> #endif/* The <limits.h> files in some gcc versions don‘t define LLONG_MIN, LLONG_MAX, and ULLONG_MAX. Instead only the values gcc defined for ages are available. */#if defined __USE_ISOC99 && defined __GNUC__ # ifndef LLONG_MIN # define LLONG_MIN (-LLONG_MAX-1) # endif # ifndef LLONG_MAX # define LLONG_MAX __LONG_LONG_MAX__ # endif # ifndef ULLONG_MAX # define ULLONG_MAX (LLONG_MAX * 2ULL + 1) # endif #endif #ifdef __USE_POSIX /* POSIX adds things to <limits.h>. */ # include <bits/posix1_lim.h> #endif #ifdef __USE_POSIX2 # include <bits/posix2_lim.h> #endif #ifdef __USE_XOPEN # include <bits/xopen_lim.h> #endif
我们还可以通过在shell用getconf获取限制:
PS:OPEN_MAX为进程同时最多可以打开的文件描述符的数量。
lancelot@debian:~/Code/tlpi$ getconf OPEN_MAX 1024
第12章
这章主要将了系统和进程信息
/proc虚拟文件系统:维基
首先我们来看看/proc有些什么
lancelot@debian:~/Code/tlpi$ ls /proc/ 111994165220025227123238694156429744424577530 acpi execdomains kpageflags softirqs 10121720012551277533387041654299445145795318 asound fb loadavg stat1000212017192022628334539274168440144574580589 ati filesystems locks swaps 100081319120326092815334639641694403446445836 buddyinfo fs meminfo sys 1001014194212610286934441734404448345846410 bus interrupts misc sysrq-trigger 10235140195222612287934104041774407448546226415 cgroups iomem modules sysvipc 10575151956232641293540004179441044964627667 cmdline ioports mounts timer_list 111581962384266829703798408541814412450046327 consoles irq mtrr timer_stats 11377161982399266929803828410241864415450346377733 cpuinfo kallsyms net tty 116401644198724267029823864410341904422451146428 crypto kcore pagetypeinfo uptime11659164519922480267133865410741964424451646478167 devices keys partitions version 1170416461994252672303866410842044436451852488168 diskstats key-users sched_debug vmallocinfo 11967164722512730113867410942114438452652548169 dma kmsg self vmstat 119881651202515271031386841154217443945705299 driver kpagecount slabinfo zoneinfo
那些数字是进程ID(PID),每个进程ID都有其独自的子文件夹,里面包含进程的相关信息。
通过PID为1的进程(init)来说明。
lancelot@debian:~/Code/tlpi$ sudols -l /proc/1 [sudo] password for lancelot: 总用量 0 dr-xr-xr-x 2 root root 0 4月 2822:40 attr -rw-r--r-- 1 root root 0 4月 2822:40 autogroup -r-------- 1 root root 0 4月 2822:40 auxv -r--r--r-- 1 root root 0 4月 2822:40 cgroup --w------- 1 root root 0 4月 2822:40 clear_refs -r--r--r-- 1 root root 0 4月 2812:26 cmdline -rw-r--r-- 1 root root 0 4月 2822:40 comm -rw-r--r-- 1 root root 0 4月 2822:40 coredump_filter -r--r--r-- 1 root root 0 4月 2822:40 cpuset lrwxrwxrwx 1 root root 0 4月 2822:40 cwd -> / -r-------- 1 root root 0 4月 2822:40 environ lrwxrwxrwx 1 root root 0 4月 2812:26 exe -> /sbin/init dr-x------ 2 root root 0 4月 2822:40 fd dr-x------ 2 root root 0 4月 2822:40 fdinfo -r-------- 1 root root 0 4月 2822:40 io -r--r--r-- 1 root root 0 4月 2812:27 limits -rw-r--r-- 1 root root 0 4月 2822:40 loginuid -r--r--r-- 1 root root 0 4月 2822:40 maps -rw------- 1 root root 0 4月 2822:40 mem -r--r--r-- 1 root root 0 4月 2822:40 mountinfo -r--r--r-- 1 root root 0 4月 2822:40 mounts -r-------- 1 root root 0 4月 2822:40 mountstats dr-xr-xr-x 6 root root 0 4月 2822:40 net dr-x--x--x 2 root root 0 4月 2822:40 ns -r--r--r-- 1 root root 0 4月 2822:40 numa_maps -rw-r--r-- 1 root root 0 4月 2822:40 oom_adj -r--r--r-- 1 root root 0 4月 2822:40 oom_score -rw-r--r-- 1 root root 0 4月 2812:29 oom_score_adj -r--r--r-- 1 root root 0 4月 2822:40 pagemap -r--r--r-- 1 root root 0 4月 2822:40 personality lrwxrwxrwx 1 root root 0 4月 2822:40 root -> / -rw-r--r-- 1 root root 0 4月 2822:40 sched -r--r--r-- 1 root root 0 4月 2822:40 sessionid -r--r--r-- 1 root root 0 4月 2822:40 smaps -r--r--r-- 1 root root 0 4月 2822:40 stack -r--r--r-- 1 root root 0 4月 2812:26stat -r--r--r-- 1 root root 0 4月 2822:40 statm -r--r--r-- 1 root root 0 4月 2812:26 status -r--r--r-- 1 root root 0 4月 2822:40 syscall dr-xr-xr-x 3 root root 0 4月 2822:40 task -r--r--r-- 1 root root 0 4月 2822:40 wchan
其中
cmdline是以‘ ‘分隔的命令参数
cwd是指向当前工作目录的符号链接,可以看出init当前工作目录为根目录。
environ是环境列表,以‘ ‘分隔
HOME=/init=/sbin/initTERM=linuxBOOT_IMAGE=/vmlinuz-3.2.0-4-amd64PATH=/sbin:/usr/sbin:/bin:/usr/binPWD=/rootmnt=/root
exe是指向正在执行文件的符号链接,正在执行文件为/sbin/init。
fd是文件目录,包含指向由该进程打开文件的符号链接
lancelot@debian:~/Code/tlpi$ sudols -l /proc/1/fd 总用量 0 lrwx------ 1 root root 64 4月 2822:5210 -> /run/initctl
maps为内存映射
lancelot@debian:~/Code/tlpi$ sudocat /proc/1/maps 00400000-00409000 r-xp 0000000008:089306173 /sbin/init 00608000-00609000 rw-p 0000800008:089306173 /sbin/init 01e15000-01e36000 rw-p 0000000000:000 [heap] 7f5109159000-7f510915b000 r-xp 0000000008:081838382 /lib/x86_64-linux-gnu/libdl-2.13.so 7f510915b000-7f510935b000 ---p 0000200008:081838382 /lib/x86_64-linux-gnu/libdl-2.13.so 7f510935b000-7f510935c000 r--p 0000200008:081838382 /lib/x86_64-linux-gnu/libdl-2.13.so 7f510935c000-7f510935d000 rw-p 0000300008:081838382 /lib/x86_64-linux-gnu/libdl-2.13.so 7f510935d000-7f51094df000 r-xp 0000000008:081835094 /lib/x86_64-linux-gnu/libc-2.13.so 7f51094df000-7f51096de000 ---p 0018200008:081835094 /lib/x86_64-linux-gnu/libc-2.13.so 7f51096de000-7f51096e2000 r--p 0018100008:081835094 /lib/x86_64-linux-gnu/libc-2.13.so 7f51096e2000-7f51096e3000 rw-p 0018500008:081835094 /lib/x86_64-linux-gnu/libc-2.13.so 7f51096e3000-7f51096e8000 rw-p 0000000000:000 7f51096e8000-7f5109706000 r-xp 0000000008:081835054 /lib/x86_64-linux-gnu/libselinux.so.1 7f5109706000-7f5109905000 ---p 0001e000 08:081835054 /lib/x86_64-linux-gnu/libselinux.so.1 7f5109905000-7f5109906000 r--p 0001d000 08:081835054 /lib/x86_64-linux-gnu/libselinux.so.1 7f5109906000-7f5109907000 rw-p 0001e000 08:081835054 /lib/x86_64-linux-gnu/libselinux.so.1 7f5109907000-7f5109908000 rw-p 0000000000:000 7f5109908000-7f5109947000 r-xp 0000000008:081835059 /lib/x86_64-linux-gnu/libsepol.so.1 7f5109947000-7f5109b46000 ---p 0003f000 08:081835059 /lib/x86_64-linux-gnu/libsepol.so.1 7f5109b46000-7f5109b47000 r--p 0003e000 08:081835059 /lib/x86_64-linux-gnu/libsepol.so.1 7f5109b47000-7f5109b48000 rw-p 0003f000 08:081835059 /lib/x86_64-linux-gnu/libsepol.so.1 7f5109b48000-7f5109b68000 r-xp 0000000008:081838390 /lib/x86_64-linux-gnu/ld-2.13.so 7f5109d4a000-7f5109d4e000 rw-p 0000000000:000 7f5109d65000-7f5109d67000 rw-p 0000000000:000 7f5109d67000-7f5109d68000 r--p 0001f000 08:081838390 /lib/x86_64-linux-gnu/ld-2.13.so 7f5109d68000-7f5109d69000 rw-p 0002000008:081838390 /lib/x86_64-linux-gnu/ld-2.13.so 7f5109d69000-7f5109d6a000 rw-p 0000000000:000 7fffc8fe9000-7fffc900a000 rw-p 0000000000:000 [stack] 7fffc9191000-7fffc9192000 r-xp 0000000000:000 [vdso] ffffffffff600000-ffffffffff601000 r-xp 0000000000:000 [vsyscall]
mem为进程虚拟内存
mounts为进程的安装点
lancelot@debian:~/Code/tlpi$ sudocat /proc/1/mounts rootfs / rootfs rw 00 sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 00 proc /proc proc rw,nosuid,nodev,noexec,relatime 00 udev /dev devtmpfs rw,relatime,size=10240k,nr_inodes=958260,mode=75500 devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=00000 tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=767824k,mode=75500 /dev/disk/by-uuid/c2a06636-4fcf-4701-8f46-6415015254a0 / ext4 rw,relatime,errors=remount-ro,user_xattr,barrier=1,data=ordered 00 tmpfs /run/lock tmpfs rw,nosuid,nodev,noexec,relatime,size=5120k 00 tmpfs /run/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=1535640k 00 /dev/sda7 /boot ext4 rw,relatime,user_xattr,barrier=1,stripe=4,data=ordered 00 /dev/sda5 /home ext4 rw,relatime,user_xattr,barrier=1,data=ordered 00 /dev/sda6 /opt ext4 rw,relatime,user_xattr,barrier=1,data=ordered 00 rpc_pipefs /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 00 binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatime 00
root为指向根目录的符号链接
status记录着进程的ID、内存使用情况、信号等信息。
lancelot@debian:~/Code/tlpi$ sudocat /proc/1/status Name: init State: S (sleeping) Tgid: 1 Pid: 1 PPid: 0 TracerPid: 0 Uid: 0000 Gid: 0000 FDSize: 64 Groups: VmPeak: 10652 kB VmSize: 10648 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 788 kB VmRSS: 788 kB VmData: 188 kB VmStk: 136 kB VmExe: 36 kB VmLib: 2052 kB VmPTE: 44 kB VmSwap: 0 kB Threads: 1 SigQ: 0/59891 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: fffffffe57f0d8fc SigCgt: 00000000280b2603 CapInh: 0000000000000000 CapPrm: ffffffffffffffff CapEff: ffffffffffffffff CapBnd: ffffffffffffffff Cpus_allowed: f Cpus_allowed_list: 0-3 Mems_allowed: 00000000,00000001 Mems_allowed_list: 0 voluntary_ctxt_switches: 7947 nonvoluntary_ctxt_switches: 33
task下存放着该进程的每个线程的子目录(记录线程的信息)
lancelot@debian:~/Code/tlpi$ sudols -l /proc/1/task 总用量 0 dr-xr-xr-x 6 root root 0 4月 2823:071
子目录的信息:
lancelot@debian:~/Code/tlpi$ sudols -l /proc/1/task/1 总用量 0 dr-xr-xr-x 2 root root 0 4月 2823:08 attr -r-------- 1 root root 0 4月 2823:08 auxv -r--r--r-- 1 root root 0 4月 2823:08 cgroup --w------- 1 root root 0 4月 2823:08 clear_refs -r--r--r-- 1 root root 0 4月 2823:08 cmdline -rw-r--r-- 1 root root 0 4月 2823:08 comm -r--r--r-- 1 root root 0 4月 2823:08 cpuset lrwxrwxrwx 1 root root 0 4月 2823:08 cwd -> / -r-------- 1 root root 0 4月 2823:08 environ lrwxrwxrwx 1 root root 0 4月 2823:08 exe -> /sbin/init dr-x------ 2 root root 0 4月 2823:08 fd dr-x------ 2 root root 0 4月 2823:08 fdinfo -r-------- 1 root root 0 4月 2823:08 io -r--r--r-- 1 root root 0 4月 2823:08 limits -rw-r--r-- 1 root root 0 4月 2823:08 loginuid -r--r--r-- 1 root root 0 4月 2823:08 maps -rw------- 1 root root 0 4月 2823:08 mem -r--r--r-- 1 root root 0 4月 2823:08 mountinfo -r--r--r-- 1 root root 0 4月 2823:08 mounts dr-x--x--x 2 root root 0 4月 2823:08 ns -r--r--r-- 1 root root 0 4月 2823:08 numa_maps -rw-r--r-- 1 root root 0 4月 2823:08 oom_adj -r--r--r-- 1 root root 0 4月 2823:08 oom_score -rw-r--r-- 1 root root 0 4月 2823:08 oom_score_adj -r--r--r-- 1 root root 0 4月 2823:08 pagemap -r--r--r-- 1 root root 0 4月 2823:08 personality lrwxrwxrwx 1 root root 0 4月 2823:08 root -> / -rw-r--r-- 1 root root 0 4月 2823:08 sched -r--r--r-- 1 root root 0 4月 2823:08 sessionid -r--r--r-- 1 root root 0 4月 2823:08 smaps -r--r--r-- 1 root root 0 4月 2823:08 stack -r--r--r-- 1 root root 0 4月 2823:08stat -r--r--r-- 1 root root 0 4月 2823:08 statm -r--r--r-- 1 root root 0 4月 2823:08 status -r--r--r-- 1 root root 0 4月 2823:08 syscall -r--r--r-- 1 root root 0 4月 2823:08 wchan
通过访问/proc文件可以获取很多有用的信息。
练习:
12-1.编写一个程序,以用户名作为命令行参数,列表显示该用户下所有正在运行的进程ID和命令名。通过分析系统中/proc/PID/status文件的Name和UID各行信息,可以思想此功能。
1
/*
2
* =====================================================================================
3
*
4
* Filename: 12.1.c
5
*
6
* Description:
7
*
8
* Version: 1.0
9
* Created: 2014年05月01日 21时03分09秒
10
* Revision: none
11
* Compiler: gcc
12
*
13
* Author: alan (), alan19920626@gmail.com
14
* Organization:
15
*
16
* =====================================================================================
17
*/
18
19 #include <fcntl.h>
20 #include <dirent.h>
21 #include <pwd.h>
22 #include <ctype.h>
23 #include <sys/stat.h>
24 #include "tlpi_hdr.h"25 #include "ugid_functions.h"2627#define MAX_LINE 1000
2829int main(int argc, char *argv[]){
30 DIR *dirp;
31struct dirent *dp;
32int fd;
33 FILE *fp;
34char path[MAX_LINE], cmd[MAX_LINE], line[MAX_LINE];
35char *p, *q;
36int numRead;
37 uid_t id, p_uid;
38 pid_t pid;
3940if(argc != 2 || strcmp(argv[1], "--help") == 0)
41 usageErr("%s username");
4243 id = userIdFromName(argv[1]); //获取用户名对应的UID44if(id == -1)
45 errExit("userIdFromName");
4647 dirp = opendir("/proc"); //打开/proc文件48if(dirp == NULL)
49 errExit("opendir");
5051 printf("Uid: %ldn", id);
52while((dp = readdir(dirp)) != NULL){
53if(dp->d_type != DT_DIR || !isdigit((unsigned char) dp->d_name[0])) //跳过类型文件类型不是目录和文件名不是数字的54continue;
5556 snprintf(path, MAX_LINE, "/proc/%s/status", dp->d_name);
57 fp = fopen(path, "r"); //打开进程对应的status文件的文件流58 p_uid = 0;
59while(fgets(line, MAX_LINE, fp) != NULL){ //逐行获取信息60if(strncmp(line, "Name:", 5) == 0){ //当字符串的开始包含Name:为进程名61for(p = line + 5; *p != ‘