Linux一切皆文件,如果你没做到这一步,那这就是句话而已
前言
相信当你接触Linux的时候,身边的人就向你灌输一个概念,或者说你就总是听到一句话:Linux系统中一切皆文件
Linux下“一切皆文件”是Unix/Linux的基本哲学之一。不信,看下面这张图
普通文件、目录、字符设备、块设备和网络设备(套接字)等在Unix/Linux都被当做文件来对待。虽然他们的类型不同,但是linux系统为它们提供了一套统一的操作接口。
Linux的一切皆文件是指,Linux世界中的所有、任意、一切东西都可以通过文件的方式访问、管理。
反过来说,是Linux和GNU世界定的规范,任何东西都挂在文件系统之上,即使它们不是文件,也以文件的形式来呈现。
比如我们经常会讲的进程(/proc)、设备(/dev)、Socket等等,实际上都不是文件,但是你可以以文件系统的规范来访问它,修改属主和属性。
那你对这句话的理解是不是仅仅止步于此呢?那我想,下面的这些内容你真的要看一下了
实际操作认证
Linux下有lsof命令,可以查看所有已经打开的文件,你使用lsof -p [pid]的方式就可以查看对应的进程都打开了什么文件,而其中的type字段就是表明它是什么类型,通过man losf 命令你可以查看到它有下面这么多种。
TYPE is the type of the node associated with the file - e.g., GDIR, GREG, VDIR, VREG, etc.
or ``IPv4'' for an IPv4 socket;
or ``IPv6'' for an open IPv6 network file - even if its address is IPv4, mapped in an IPv6 address;
or ``ax25'' for a Linux AX.25 socket;
or ``inet'' for an Internet domain socket;
or ``lla'' for a HP-UX link level access file;
or ``rte'' for an AF_ROUTE socket;
or ``sock'' for a socket of unknown domain;
or ``unix'' for a UNIX domain socket;
or ``x.25'' for an HP-UX x.25 socket;
or ``BLK'' for a block special file;
or ``CHR'' for a character special file;
or ``DEL'' for a Linux map file that has been deleted;
or ``DIR'' for a directory;
or ``DOOR'' for a VDOOR file;
or ``FIFO'' for a FIFO special file;
or ``KQUEUE'' for a BSD style kernel event queue file;
or ``LINK'' for a symbolic link file;
or ``MPB'' for a multiplexed block file;
or ``MPC'' for a multiplexed character file;
or ``NOFD'' for a Linux /proc/<PID>/fd directory that can't be opened -- the directory path appears in the NAME column, followed by an error message;
or ``PAS'' for a /proc/as file;
or ``PAXV'' for a /proc/auxv file;
or ``PCRE'' for a /proc/cred file;
or ``PCTL'' for a /proc control file;
or ``PCUR'' for the current /proc process;
or ``PCWD'' for a /proc current working directory;
or ``PDIR'' for a /proc directory;
or ``PETY'' for a /proc executable type (etype);
or ``PFD'' for a /proc file descriptor;
or ``PFDR'' for a /proc file descriptor directory;
or ``PFIL'' for an executable /proc file;
or ``PFPR'' for a /proc FP register set;
or ``PGD'' for a /proc/pagedata file;
or ``PGID'' for a /proc group notifier file;
or ``PIPE'' for pipes;
or ``PLC'' for a /proc/lwpctl file;
or ``PLDR'' for a /proc/lpw directory;
or ``PLDT'' for a /proc/ldt file;
or ``PLPI'' for a /proc/lpsinfo file;
or ``PLST'' for a /proc/lstatus file;
or ``PLU'' for a /proc/lusage file;
or ``PLWG'' for a /proc/gwindows file;
or ``PLWI'' for a /proc/lwpsinfo file;
or ``PLWS'' for a /proc/lwpstatus file;
or ``PLWU'' for a /proc/lwpusage file;
or ``PLWX'' for a /proc/xregs file;
or ``PMAP'' for a /proc map file (map);
or ``PMEM'' for a /proc memory image file;
or ``PNTF'' for a /proc process notifier file;
or ``POBJ'' for a /proc/object file;
or ``PODR'' for a /proc/object directory;
or ``POLP'' for an old format /proc light weight process file;
or ``POPF'' for an old format /proc PID file;
or ``POPG'' for an old format /proc page data file;
or ``PORT'' for a SYSV named pipe;
or ``PREG'' for a /proc register file;
or ``PRMP'' for a /proc/rmap file;
or ``PRTD'' for a /proc root directory;
or ``PSGA'' for a /proc/sigact file;
or ``PSIN'' for a /proc/psinfo file;
or ``PSTA'' for a /proc status file;
or ``PSXSEM'' for a POSIX semaphore file;
or ``PSXSHM'' for a POSIX shared memory file;
or ``PTS'' for a /dev/pts file;
or ``PUSG'' for a /proc/usage file;
or ``PW'' for a /proc/watch file;
or ``PXMP'' for a /proc/xmap file;
or ``REG'' for a regular file;
or ``SMT'' for a shared memory transport file;
or ``STSO'' for a stream socket;
or ``UNNM'' for an unnamed type file;
or ``XNAM'' for an OpenServer Xenix special file of unknown type;
or ``XSEM'' for an OpenServer Xenix semaphore file;
or ``XSD'' for an OpenServer Xenix shared data file;
or the four type number octets if the corresponding name isn't known.
这里我也添加一些实例给大家更好地展示一下
# 进到proc目录
[root@k8s ~]# cd /proc
[root@k8s proc]# ls
1 1063 1077 11 12 1504 19 2175 24 280 297 301 317 39 407 413 49 519 726 737 bus devices filesystems kallsyms kpageflags modules partitions softirqs timer_list vmstat
10 1066 1078 1100 13 16 2 2176 25 281 298 302 36 391 408 414 495 52 729 743 cgroups diskstats fs kcore loadavg mounts sched_debug stat timer_stats zoneinfo
102 1068 1083 1102 14 1746 20 2177 26 282 299 303 37 392 409 415 5 53 733 8 cmdline dma interrupts keys locks mpt schedstat swaps tty
1038 1071 1085 1110 15 1748 2005 2178 27 29 3 304 38 4 410 416 50 6 734 9 consoles driver iomem key-users mdstat mtrr scsi sys uptime
1061 1072 1097 1113 1502 1749 2007 22 279 294 30 305 380 405 411 47 51 66 735 acpi cpuinfo execdomains ioports kmsg meminfo net self sysrq-trigger version
1062 1073 1099 1164 1503 18 21 23 28 296 300 31 381 406 412 48 511 7 736 buddyinfo crypto fb irq kpagecount misc pagetypeinfo slabinfo sysvipc vmallocinfo
# 可以看到上面有很多以数字为名称的目录,而这些目录就对应每一个进程
# 使用ps -ef|grep nginx可以找到Nginx主进程的PID是2175
[root@k8s proc]# ps -ef|grep nginx
root 2175 1 0 10:23 ? 00:00:00 nginx: master process /usr/sbin/nginx
nginx 2176 2175 0 10:23 ? 00:00:00 nginx: worker process
nginx 2177 2175 0 10:23 ? 00:00:00 nginx: worker process
root 2182 2007 0 10:24 pts/0 00:00:00 grep --color=auto nginx
# 进入/proc/2175目录,可以看到这个进程相关的目录
[root@k8s 2175]# ls
attr cgroup comm cwd fd io map_files mountinfo net oom_adj pagemap projid_map schedstat smaps statm task wchan
autogroup clear_refs coredump_filter environ fdinfo limits maps mounts ns oom_score patch_state root sessionid stack status timers
auxv cmdline cpuset exe gid_map loginuid mem mountstats numa_maps oom_score_adj personality sched setgroups stat syscall uid_map
# 这里面的内容就是2175进程的全部内容了,非常多的命令实际上都是从这个目录读取的信息,比如上面的ps命令
# 上面的文件我举几个例子解释一下
# 1. fd目录,里面是此进程打开的文件的情况,每个均链接至实际的文件或设备
[root@k8s 2175]# ll fd
总用量 0
lrwx------ 1 root root 64 9月 29 10:53 0 -> /dev/null
lrwx------ 1 root root 64 9月 29 10:53 1 -> /dev/null
lrwx------ 1 root root 64 9月 29 10:53 10 -> socket:[26530]
l-wx------ 1 root root 64 9月 29 10:53 2 -> /var/log/nginx/error.log
lrwx------ 1 root root 64 9月 29 10:53 3 -> socket:[26527]
l-wx------ 1 root root 64 9月 29 10:53 4 -> /var/log/nginx/error.log
l-wx------ 1 root root 64 9月 29 10:53 5 -> /var/log/nginx/access.log
lrwx------ 1 root root 64 9月 29 10:53 6 -> socket:[27700]
lrwx------ 1 root root 64 9月 29 10:53 7 -> socket:[27701]
lrwx------ 1 root root 64 9月 29 10:53 8 -> socket:[26528]
lrwx------ 1 root root 64 9月 29 10:53 9 -> socket:[26529]
# 2. limits,内容是此进程的系统限制信息
[root@k8s 2175]# cat limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 14889 14889 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 14889 14889 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
# 3. stack,此进程的内核调用栈信息
[root@k8s 2175]# cat stack
[<ffffffff958b5859>] sigsuspend+0x39/0x70
[<ffffffff958b58ee>] SyS_rt_sigsuspend+0x5e/0x80
[<ffffffff95f92ed2>] system_call_fastpath+0x25/0x2a
[<ffffffffffffffff>] 0xffffffffffffffff
# 这些内容都不是普通的文件,你通过文件系统看,它们的大小都是0,但你看我能输出上面的这么多信息
[root@k8s 2175]# ll
总用量 0
dr-xr-xr-x 2 root root 0 9月 29 10:25 attr
-rw-r--r-- 1 root root 0 9月 29 10:25 autogroup
-r-------- 1 root root 0 9月 29 10:25 auxv
-r--r--r-- 1 root root 0 9月 29 10:23 cgroup
--w------- 1 root root 0 9月 29 10:25 clear_refs
-r--r--r-- 1 root root 0 9月 29 10:24 cmdline
-rw-r--r-- 1 root root 0 9月 29 10:25 comm
-rw-r--r-- 1 root root 0 9月 29 10:25 coredump_filter
-r--r--r-- 1 root root 0 9月 29 10:25 cpuset
...
[root@k8s 2175]# du -sh
0
另外,我们经常会使用到的/dev/null, /dev/random,都是可以在文件目录中看到,但它们都不是普通的文件,而是Linux Kernel为了实现某些功能,同时存在everything is a file的约定,才把它们体现在了文件系统上。
另外补一个我觉得挺有用的,且应该不少人不知道的一个小技巧
man 5 proc命令会输出/proc目录的帮助信息,它里面包含/proc/[pid]目录中每个目录和文件的说明信息
PROC(5) Linux Programmer's Manual PROC(5)
NAME
proc - process information pseudo-file system
DESCRIPTION
The proc file system is a pseudo-file system which is used as an interface to kernel data structures. It is commonly mounted at /proc. Most of it is read-only, but some files allow kernel variables to be changed.
The following outline gives a quick tour through the /proc hierarchy.
/proc/[pid]
There is a numerical subdirectory for each running process; the subdirectory is named by the process ID. Each such subdirectory contains the following pseudo-files and directories.
/proc/[pid]/auxv (since 2.6.0-test7)
This contains the contents of the ELF interpreter information passed to the process at exec time. The format is one unsigned long ID plus one unsigned long value for each entry. The last entry contains two zeros.
/proc/[pid]/cgroup (since Linux 2.6.24)
This file describes control groups to which the process/task belongs. For each cgroup hierarchy there is one entry containing colon-separated fields of the form:
5:cpuacct,cpu,cpuset:/daemons
The colon-separated fields are, from left to right:
1. hierarchy ID number
2. set of subsystems bound to the hierarchy
3. control group in the hierarchy to which the process belongs
This file is present only if the CONFIG_CGROUPS kernel configuration option is enabled.
/proc/[pid]/cmdline
This holds the complete command line for the process, unless the process is a zombie. In the latter case, there is nothing in this file: that is, a read on this file will return 0 characters. The command-line arguments appear in this file as a set
of strings separated by null bytes ('\0'), with a further null byte after the last string.
/proc/[pid]/coredump_filter (since kernel 2.6.23)
See core(5).
/proc/[pid]/cpuset (since kernel 2.6.12)
See cpuset(7).
/proc/[pid]/cwd
This is a symbolic link to the current working directory of the process. To find out the current working directory of process 20, for instance, you can do this:
$ cd /proc/20/cwd; /bin/pwd
Note that the pwd command is often a shell built-in, and might not work properly. In bash(1), you may use pwd -P.
In a multithreaded process, the contents of this symbolic link are not available if the main thread has already terminated (typically by calling pthread_exit(3)).
其实,这就是Linux最让人着迷的地方,总是感觉很多东西都很简单,一个命令行就可以解决问题,但是深入去研究一下,你又会发现,真的有很多更神秘的地方再等待着你去探索,越深入学习越觉得兴奋,起码我个人是这样觉得
加油吧,程序员
文章首发公众号:Java架构师联盟,每日更新技术好文