《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

时间:2024-01-19 08:40:08

《Linux/Unix系统编程手册》读书笔记 目录

第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 #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 /* Minimum and maximum values a `signed char' can hold. */
# define SCHAR_MIN (-)
# define SCHAR_MAX /* Maximum value an `unsigned char' can hold. (Minimum is 0.) */
# define UCHAR_MAX /* Minimum and maximum values a `char' can hold. */
# ifdef __CHAR_UNSIGNED__
# define CHAR_MIN
# 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 (-)
# define SHRT_MAX /* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */
# define USHRT_MAX /* Minimum and maximum values a `signed int' can hold. */
# define INT_MIN (-INT_MAX - )
# define INT_MAX /* 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 ==
# 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 ==
# 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-)
# endif
# ifndef LLONG_MAX
# define LLONG_MAX __LONG_LONG_MAX__
# endif
# ifndef ULLONG_MAX
# define ULLONG_MAX (LLONG_MAX * 2ULL + )
# 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

第12章

这章主要将了系统和进程信息

/proc虚拟文件系统:维基

首先我们来看看/proc有些什么

lancelot@debian:~/Code/tlpi$ ls /proc/
acpi execdomains kpageflags softirqs
asound fb loadavg stat
ati filesystems locks swaps
buddyinfo fs meminfo sys
bus interrupts misc sysrq-trigger
cgroups iomem modules sysvipc
cmdline ioports mounts timer_list
consoles irq mtrr timer_stats
cpuinfo kallsyms net tty
crypto kcore pagetypeinfo uptime
devices keys partitions version
diskstats key-users sched_debug vmallocinfo
dma kmsg self vmstat
driver kpagecount slabinfo zoneinfo

那些数字是进程ID(PID),每个进程ID都有其独自的子文件夹,里面包含进程的相关信息。

通过PID为1的进程(init)来说明。

lancelot@debian:~/Code/tlpi$ sudo ls -l /proc/
[sudo] password for lancelot:
总用量
dr-xr-xr-x root root 4月 : attr
-rw-r--r-- root root 4月 : autogroup
-r-------- root root 4月 : auxv
-r--r--r-- root root 4月 : cgroup
--w------- root root 4月 : clear_refs
-r--r--r-- root root 4月 : cmdline
-rw-r--r-- root root 4月 : comm
-rw-r--r-- root root 4月 : coredump_filter
-r--r--r-- root root 4月 : cpuset
lrwxrwxrwx root root 4月 : cwd -> /
-r-------- root root 4月 : environ
lrwxrwxrwx root root 4月 : exe -> /sbin/init
dr-x------ root root 4月 : fd
dr-x------ root root 4月 : fdinfo
-r-------- root root 4月 : io
-r--r--r-- root root 4月 : limits
-rw-r--r-- root root 4月 : loginuid
-r--r--r-- root root 4月 : maps
-rw------- root root 4月 : mem
-r--r--r-- root root 4月 : mountinfo
-r--r--r-- root root 4月 : mounts
-r-------- root root 4月 : mountstats
dr-xr-xr-x root root 4月 : net
dr-x--x--x root root 4月 : ns
-r--r--r-- root root 4月 : numa_maps
-rw-r--r-- root root 4月 : oom_adj
-r--r--r-- root root 4月 : oom_score
-rw-r--r-- root root 4月 : oom_score_adj
-r--r--r-- root root 4月 : pagemap
-r--r--r-- root root 4月 : personality
lrwxrwxrwx root root 4月 : root -> /
-rw-r--r-- root root 4月 : sched
-r--r--r-- root root 4月 : sessionid
-r--r--r-- root root 4月 : smaps
-r--r--r-- root root 4月 : stack
-r--r--r-- root root 4月 : stat
-r--r--r-- root root 4月 : statm
-r--r--r-- root root 4月 : status
-r--r--r-- root root 4月 : syscall
dr-xr-xr-x root root 4月 : task
-r--r--r-- root root 4月 : wchan

其中

cmdline是以'\0'分隔的命令参数

cwd是指向当前工作目录的符号链接,可以看出init当前工作目录为根目录。

environ是环境列表,以'\0'分隔

HOME=/init=/sbin/initTERM=linuxBOOT_IMAGE=/vmlinuz-3.2.--amd64PATH=/sbin:/usr/sbin:/bin:/usr/binPWD=/rootmnt=/root

exe是指向正在执行文件的符号链接,正在执行文件为/sbin/init。

fd是文件目录,包含指向由该进程打开文件的符号链接

lancelot@debian:~/Code/tlpi$ sudo ls -l /proc//fd
总用量
lrwx------ root root 4月 : -> /run/initctl

maps为内存映射

lancelot@debian:~/Code/tlpi$ sudo cat /proc//maps
- r-xp : /sbin/init
- rw-p : /sbin/init
01e15000-01e36000 rw-p : [heap]
7f5109159000-7f510915b000 r-xp : /lib/x86_64-linux-gnu/libdl-2.13.so
7f510915b000-7f510935b000 ---p : /lib/x86_64-linux-gnu/libdl-2.13.so
7f510935b000-7f510935c000 r--p : /lib/x86_64-linux-gnu/libdl-2.13.so
7f510935c000-7f510935d000 rw-p : /lib/x86_64-linux-gnu/libdl-2.13.so
7f510935d000-7f51094df000 r-xp : /lib/x86_64-linux-gnu/libc-2.13.so
7f51094df000-7f51096de000 ---p : /lib/x86_64-linux-gnu/libc-2.13.so
7f51096de000-7f51096e2000 r--p : /lib/x86_64-linux-gnu/libc-2.13.so
7f51096e2000-7f51096e3000 rw-p : /lib/x86_64-linux-gnu/libc-2.13.so
7f51096e3000-7f51096e8000 rw-p :
7f51096e8000-7f5109706000 r-xp : /lib/x86_64-linux-gnu/libselinux.so.
7f5109706000-7f5109905000 ---p 0001e000 : /lib/x86_64-linux-gnu/libselinux.so.
7f5109905000-7f5109906000 r--p 0001d000 : /lib/x86_64-linux-gnu/libselinux.so.
7f5109906000-7f5109907000 rw-p 0001e000 : /lib/x86_64-linux-gnu/libselinux.so.
7f5109907000-7f5109908000 rw-p :
7f5109908000-7f5109947000 r-xp : /lib/x86_64-linux-gnu/libsepol.so.
7f5109947000-7f5109b46000 ---p 0003f000 : /lib/x86_64-linux-gnu/libsepol.so.
7f5109b46000-7f5109b47000 r--p 0003e000 : /lib/x86_64-linux-gnu/libsepol.so.
7f5109b47000-7f5109b48000 rw-p 0003f000 : /lib/x86_64-linux-gnu/libsepol.so.
7f5109b48000-7f5109b68000 r-xp : /lib/x86_64-linux-gnu/ld-2.13.so
7f5109d4a000-7f5109d4e000 rw-p :
7f5109d65000-7f5109d67000 rw-p :
7f5109d67000-7f5109d68000 r--p 0001f000 : /lib/x86_64-linux-gnu/ld-2.13.so
7f5109d68000-7f5109d69000 rw-p : /lib/x86_64-linux-gnu/ld-2.13.so
7f5109d69000-7f5109d6a000 rw-p :
7fffc8fe9000-7fffc900a000 rw-p : [stack]
7fffc9191000-7fffc9192000 r-xp : [vdso]
ffffffffff600000-ffffffffff601000 r-xp : [vsyscall]

mem为进程虚拟内存

mounts为进程的安装点

lancelot@debian:~/Code/tlpi$ sudo cat /proc//mounts
rootfs / rootfs rw
sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime
proc /proc proc rw,nosuid,nodev,noexec,relatime
udev /dev devtmpfs rw,relatime,size=10240k,nr_inodes=,mode=
devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=,mode=,ptmxmode=
tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=767824k,mode=
/dev/disk/by-uuid/c2a06636-4fcf--8f46-6415015254a0 / ext4 rw,relatime,errors=remount-ro,user_xattr,barrier=,data=ordered
tmpfs /run/lock tmpfs rw,nosuid,nodev,noexec,relatime,size=5120k
tmpfs /run/shm tmpfs rw,nosuid,nodev,noexec,relatime,size=1535640k
/dev/sda7 /boot ext4 rw,relatime,user_xattr,barrier=,stripe=,data=ordered
/dev/sda5 /home ext4 rw,relatime,user_xattr,barrier=,data=ordered
/dev/sda6 /opt ext4 rw,relatime,user_xattr,barrier=,data=ordered
rpc_pipefs /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime
binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,nosuid,nodev,noexec,relatime

root为指向根目录的符号链接

status记录着进程的ID、内存使用情况、信号等信息。

lancelot@debian:~/Code/tlpi$ sudo cat /proc//status
Name: init
State: S (sleeping)
Tgid:
Pid:
PPid:
TracerPid:
Uid:
Gid:
FDSize:
Groups:
VmPeak: kB
VmSize: kB
VmLck: kB
VmPin: kB
VmHWM: kB
VmRSS: kB
VmData: kB
VmStk: kB
VmExe: kB
VmLib: kB
VmPTE: kB
VmSwap: kB
Threads:
SigQ: /
SigPnd:
ShdPnd:
SigBlk:
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
CapInh:
CapPrm: ffffffffffffffff
CapEff: ffffffffffffffff
CapBnd: ffffffffffffffff
Cpus_allowed: f
Cpus_allowed_list: -
Mems_allowed: ,
Mems_allowed_list:
voluntary_ctxt_switches:
nonvoluntary_ctxt_switches:

task下存放着该进程的每个线程的子目录(记录线程的信息)

lancelot@debian:~/Code/tlpi$ sudo ls -l /proc//task
总用量
dr-xr-xr-x root root 4月 :

子目录的信息:

lancelot@debian:~/Code/tlpi$ sudo ls -l /proc//task/
总用量
dr-xr-xr-x root root 4月 : attr
-r-------- root root 4月 : auxv
-r--r--r-- root root 4月 : cgroup
--w------- root root 4月 : clear_refs
-r--r--r-- root root 4月 : cmdline
-rw-r--r-- root root 4月 : comm
-r--r--r-- root root 4月 : cpuset
lrwxrwxrwx root root 4月 : cwd -> /
-r-------- root root 4月 : environ
lrwxrwxrwx root root 4月 : exe -> /sbin/init
dr-x------ root root 4月 : fd
dr-x------ root root 4月 : fdinfo
-r-------- root root 4月 : io
-r--r--r-- root root 4月 : limits
-rw-r--r-- root root 4月 : loginuid
-r--r--r-- root root 4月 : maps
-rw------- root root 4月 : mem
-r--r--r-- root root 4月 : mountinfo
-r--r--r-- root root 4月 : mounts
dr-x--x--x root root 4月 : ns
-r--r--r-- root root 4月 : numa_maps
-rw-r--r-- root root 4月 : oom_adj
-r--r--r-- root root 4月 : oom_score
-rw-r--r-- root root 4月 : oom_score_adj
-r--r--r-- root root 4月 : pagemap
-r--r--r-- root root 4月 : personality
lrwxrwxrwx root root 4月 : root -> /
-rw-r--r-- root root 4月 : sched
-r--r--r-- root root 4月 : sessionid
-r--r--r-- root root 4月 : smaps
-r--r--r-- root root 4月 : stack
-r--r--r-- root root 4月 : stat
-r--r--r-- root root 4月 : statm
-r--r--r-- root root 4月 : status
-r--r--r-- root root 4月 : syscall
-r--r--r-- root root 4月 : wchan

通过访问/proc文件可以获取很多有用的信息。

练习:

12-1.编写一个程序,以用户名作为命令行参数,列表显示该用户下所有正在运行的进程ID和命令名。通过分析系统中/proc/PID/status文件的Name和UID各行信息,可以思想此功能。

 /*
* =====================================================================================
*
* Filename: 12.1.c
*
* Description:
*
* Version: 1.0
* Created: 2014年05月01日 21时03分09秒
* Revision: none
* Compiler: gcc
*
* Author: alan (), alan19920626@gmail.com
* Organization:
*
* =====================================================================================
*/ #include <fcntl.h>
#include <dirent.h>
#include <pwd.h>
#include <ctype.h>
#include <sys/stat.h>
#include "tlpi_hdr.h"
#include "ugid_functions.h" #define MAX_LINE 1000 int main(int argc, char *argv[]){
DIR *dirp;
struct dirent *dp;
int fd;
FILE *fp;
char path[MAX_LINE], cmd[MAX_LINE], line[MAX_LINE];
char *p, *q;
int numRead;
uid_t id, p_uid;
pid_t pid; if(argc != || strcmp(argv[], "--help") == )
usageErr("%s username"); id = userIdFromName(argv[]); //获取用户名对应的UID
if(id == -)
errExit("userIdFromName"); dirp = opendir("/proc"); //打开/proc文件
if(dirp == NULL)
errExit("opendir"); printf("Uid: %ld\n", id);
while((dp = readdir(dirp)) != NULL){
if(dp->d_type != DT_DIR || !isdigit((unsigned char) dp->d_name[])) //跳过类型文件类型不是目录和文件名不是数字的
continue; snprintf(path, MAX_LINE, "/proc/%s/status", dp->d_name);
fp = fopen(path, "r"); //打开进程对应的status文件的文件流
p_uid = ;
while(fgets(line, MAX_LINE, fp) != NULL){ //逐行获取信息
if(strncmp(line, "Name:", ) == ){ //当字符串的开始包含Name:为进程名
for(p = line + ; *p != '\0' && isspace((unsigned char)*p); ++p)
;
for(q = p; *q != '\0' && isgraph((unsigned char)*q); ++q)
;
strncpy(cmd, p, (int)(q-p));
cmd[(int)(q-p)] = '\0';
} if(strncmp(line, "Pid:", ) == ){ //获取进程号
pid = strtol(line+, NULL, );
} if(strncmp(line, "Uid:", ) == ){ //获取有效用户号
p_uid = strtol(line+, NULL, );
break;
}
}
fclose(fp);
if(p_uid == id)
printf("%5ld %s\n", p_uid, cmd);
}
exit(EXIT_SUCCESS);
}

刚开始打算用open和read来读取status的信息,但是不知道为什么只能测试是否包含"Name:",不能获取进程号和有效用户号,所以修改成通过fopen和fgets来读取status文件的信息。感觉这个练习比之前的难度大了,综合了比较多的系统调用和库函数,感觉还是用得不熟练。除了把书上的练习做了,还要找些东东来搞搞,练习一下。

测试结果:

lancelot@debian:~/Code/tlpi$ ./12.1 lancelot
Uid:
bash
startx
xinit
Xorg
ck-launch-sessi
ssh-agent
x-session-manag
dbus-launch
dbus-daemon
ibus-daemon
ibus-gconf
python
ibus-x11
gvfsd
gconfd-
ibus-engine-sun
gnome-settings-
gnome-keyring-d
pulseaudio
gvfs-gdu-volume
gvfs-afc-volume
gvfs-gphoto2-vo
gnome-shell
gsd-printer
nm-applet
tracker-miner-f
gdu-notificatio
nautilus
tracker-store
gnome-screensav
evolution-alarm
gvfsd-trash
evolution-calen
gvfsd-burn
evolution-addre
goa-daemon
gvfsd-metadata
gnome-shell-cal
mission-control
chrome
chrome
chrome-sandbox
chrome
nacl_helper
chrome
chrome
chrome
chrome
chrome
chrome
chrome
chrome
chrome
chrome
dconf-service
guake
gnome-pty-helpe
bash
gvim
gedit
gnome-pty-helpe
bash
bash
12.1

-----------------------还有两题。。。又来挖坑了-------感觉对这些系统调用和库函数的熟练程度严重不够

-----------------------还要继续努力啊!!!!加油!!!!!---------------------------------------------------

-----------------------要把学习记录的进度加快,下册也快看了一个月,还有一大部分没看,而且代码也很多没实现