十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
1、首先打开xshell软件,连接上linux服务器,使用指令ps查看系统进程,参数a表示全部,u表示以用户格式显示,x表示进程参数。
站在用户的角度思考问题,与客户深入沟通,找到阜平网站设计与阜平网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都网站建设、网站设计、企业官网、英文网站、手机端网站、网站推广、域名与空间、网站空间、企业邮箱。业务覆盖阜平地区。
2、接着通过符号|加上grep查找具体的某个进程,如下图所示。
3、然后输入ps -ef用于查看进程的父进程id,如下图所示。
4、最后使用pstree指令查看进程树结构,如下图所示就完成了。
在Linux下一切资源皆文件,普通文件是文件,磁盘打印机是文件,socket 当然也是文件。
关于Linux下系统,进程能最大能打开的文件描述符数看过好多文章,但大都没有完整,详细说明每个值表示什么意思,在实践中该怎么设置?
如何通过最简单的设置来实现最有效的性能调优,如何在有限资源的条件下保证程序的运作?
max-file 表示系统级别的能够打开的文件句柄的数量,是对整个系统的限制,并不是针对用户的。
ulimit -n 控制进程级别能够打开的文件句柄的数量,提供对shell及其启动的进程的可用文件句柄的控制,这是进程级别的。
对于服务器来说,file-max和ulimit都需要设置,否则会出现文件描述符耗尽的问题。
一般如果遇到文件句柄达到上限时,会碰到"Too many open files"或者Socket/File: Can’t open so many files等错误。
相关的3个文件:
/proc/sys/fs/file-max
/proc/sys/fs/file-nr
/etc/security/limits.conf
/proc/sys/fs/file-max
Linux系统级别限制所有用户进程能打开的文件描述符总数。
max-file 表示系统级别的能够打开的文件句柄的数量,是对整个系统的限制,并不是针对用户的。
/etc/security/limits.conf
用户级别的限制是通过可以通过命令ulimit命令和文件/etc/security/limits.conf
/proc/sys/fs/file-nr 该参数是只读的,不能修改。
file-nr的值由3部分组成:
1,已经分配的文件描述符数;
2,已经分配但未使用的文件描述符数;
3,内核最大能分配的文件描述符数
/proc/${pid}/fd
众所周知,在相应进程的/proc/$pid/fd 目录下存放了此进程所有打开的fd。
当然有些可能不是本进程自己打开的,如通过fork()从父进程继承而来的。
那么这个socket:后面的一串数字是什么呢?其实是该socket的inode号。
那么,知道了某个进程打开的socket的inode号后,我们可以做什么呢?
这就涉及到/proc/net/tcp(udp对应/proc/net/udp)文件了,其中也列出了相应socket的inode号通过比对此字段,我们能在/proc/net/tcp下获得此套接口的其他信息,如对应的本地地址:端口号,远端地址:端口号对,窗口大小,状态等信息。
具体字段含义详见net/ipv4/tcp_ipv4.c 中的 tcp4_seq_show 函数。
如果socket创建了,没有被使用,那么就只会在/proc/pid/fd下面有,而不会在/proc/net/下面有相关数据。
目录中的每一项都是一个符号链接,指向打开的文件,数字则代表文件描述符。
其中0 = /dev/null ,1 = stdout, 2 = stderr,用cat或tail查看即可。
Number of file descriptors: different between /proc/sys/fs/file-nr and /proc/$pid/fd?
Linux中最大文件描述符数
How do linux file descriptor limits work?
limits.conf(5) - Linux man page
Why can't I tail -f /proc/$pid/fd/1 ?
Linux查看进程运行输出(/proc/<pid>/fd)
linux系统下查看进程打开文件在/proc下,对应每个进程有一个以进程号命名的目录,该目录下有一个fd目录,该目录下面的每个文件是一个符号连接,其文件名对应该进程占用的一个文件描述符,而连接指向的内容表示文件描述符对应的实际文件,有多少个文件描述符表示该进程打开了多少文件。
另外Linux
默认的进程打开文件上限是1024个,可以通过ulimit
-n查看。很多系统上限可以通过修改/etc/security/limits.conf文件改变,这个文件有详细的注释,对如何修改做了说明。如果希望
把所有用户的进程打开文件上限改为65536,可以加入下面两行
* soft nofile 65535
* hard nofile 65535
还可以只真对某个用户或某个组做修改,具体方法参见文件注释。修改后需要重新启动系统才能生效。
Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux。这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同。现在的大部分Linux系统都是可以同时使用这两种方式的。
ps -ef 是用标准的格式显示进程的、其格式如下:
其中各列的内容意思如下
UID //用户ID、但输出的是用户名
PID //进程的ID
PPID //父进程ID
C //进程占用CPU的百分比
STIME //进程启动到现在的时间
TTY //该进程在那个终端上运行,若与终端无关,则显示? 若为pts/0等,则表示由网络连接主机进程。
CMD //命令的名称和参数
ps aux 是用BSD的格式来显示、其格式如下:
同ps -ef 不同的有列有
USER //用户名
%CPU //进程占用的CPU百分比
%MEM //占用内存的百分比
VSZ //该进程使用的虚拟内存量(KB)
RSS //该进程占用的固定内存量(KB)(驻留中页的数量)
STAT //进程的状态
START //该进程被触发启动时间
TIME //该进程实际使用CPU运行的时间
其中STAT状态位常见的状态字符有
D //无法中断的休眠状态(通常 IO 的进程); uninterruptible sleep (usually IO)不可中断
R //正在运行可中在队列中可过行的;
S //处于休眠状态;
T //停止或被追踪; traced or stopped
W //进入内存交换 (从内核2.6开始无效);
X //死掉的进程 (基本很少见);
Z //僵尸进程; a defunct (”zombie”) process
//优先级高的进程
N //优先级较低的进程
L //有些页被锁进内存;
s //进程的领导者(在它之下有子进程);
l //多线程,克隆线程(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ //位于后台的进程组;
开发十年经验总结,阿里架构师的手写Spring boot原理实践文档
阿里架构师的这份:Redis核心原理与应用实践,带你手撕Redis
Tomcat结构原理详解
说到进程,恐怕面试中最常见的问题就是线程和进程的关系了,那么先说一下答案: 在 Linux 系统中,进程和线程几乎没有区别 。
Linux 中的进程其实就是一个数据结构,顺带可以理解文件描述符、重定向、管道命令的底层工作原理,最后我们从操作系统的角度看看为什么说线程和进程基本没有区别。
首先,抽象地来说,我们的计算机就是这个东西:
这个大的矩形表示计算机的 内存空间 ,其中的小矩形代表 进程 ,左下角的圆形表示 磁盘 ,右下角的图形表示一些 输入输出设备 ,比如鼠标键盘显示器等等。另外,注意到内存空间被划分为了两块,上半部分表示 用户空间 ,下半部分表示 内核空间 。
用户空间装着用户进程需要使用的资源,比如你在程序代码里开一个数组,这个数组肯定存在用户空间;内核空间存放内核进程需要加载的系统资源,这一些资源一般是不允许用户访问的。但是注意有的用户进程会共享一些内核空间的资源,比如一些动态链接库等等。
我们用 C 语言写一个 hello 程序,编译后得到一个可执行文件,在命令行运行就可以打印出一句 hello world,然后程序退出。在操作系统层面,就是新建了一个进程,这个进程将我们编译出来的可执行文件读入内存空间,然后执行,最后退出。
你编译好的那个可执行程序只是一个文件,不是进程,可执行文件必须要载入内存,包装成一个进程才能真正跑起来。进程是要依靠操作系统创建的,每个进程都有它的固有属性,比如进程号(PID)、进程状态、打开的文件等等,进程创建好之后,读入你的程序,你的程序才被系统执行。
那么,操作系统是如何创建进程的呢? 对于操作系统,进程就是一个数据结构 ,我们直接来看 Linux 的源码:
task_struct 就是 Linux 内核对于一个进程的描述,也可以称为「进程描述符」。源码比较复杂,我这里就截取了一小部分比较常见的。
我们主要聊聊 mm 指针和 files 指针。 mm 指向的是进程的虚拟内存,也就是载入资源和可执行文件的地方; files 指针指向一个数组,这个数组里装着所有该进程打开的文件的指针。
先说 files ,它是一个文件指针数组。一般来说,一个进程会从 files[0] 读取输入,将输出写入 files[1] ,将错误信息写入 files[2] 。
举个例子,以我们的角度 C 语言的 printf 函数是向命令行打印字符,但是从进程的角度来看,就是向 files[1] 写入数据;同理, scanf 函数就是进程试图从 files[0] 这个文件中读取数据。
每个进程被创建时, files 的前三位被填入默认值,分别指向标准输入流、标准输出流、标准错误流。我们常说的「文件描述符」就是指这个文件指针数组的索引 ,所以程序的文件描述符默认情况下 0 是输入,1 是输出,2 是错误。
我们可以重新画一幅图:
对于一般的计算机,输入流是键盘,输出流是显示器,错误流也是显示器,所以现在这个进程和内核连了三根线。因为硬件都是由内核管理的,我们的进程需要通过「系统调用」让内核进程访问硬件资源。
PS:不要忘了,Linux 中一切都被抽象成文件,设备也是文件,可以进行读和写。
如果我们写的程序需要其他资源,比如打开一个文件进行读写,这也很简单,进行系统调用,让内核把文件打开,这个文件就会被放到 files 的第 4 个位置,对应文件描述符 3:
明白了这个原理, 输入重定向 就很好理解了,程序想读取数据的时候就会去 files[0] 读取,所以我们只要把 files[0] 指向一个文件,那么程序就会从这个文件中读取数据,而不是从键盘:
同理, 输出重定向 就是把 files[1] 指向一个文件,那么程序的输出就不会写入到显示器,而是写入到这个文件中:
错误重定向也是一样的,就不再赘述。
管道符其实也是异曲同工,把一个进程的输出流和另一个进程的输入流接起一条「管道」,数据就在其中传递,不得不说这种设计思想真的很巧妙:
到这里,你可能也看出「Linux 中一切皆文件」设计思路的高明了,不管是设备、另一个进程、socket 套接字还是真正的文件,全部都可以读写,统一装进一个简单的 files 数组,进程通过简单的文件描述符访问相应资源,具体细节交于操作系统,有效解耦,优美高效。
首先要明确的是,多进程和多线程都是并发,都可以提高处理器的利用效率,所以现在的关键是,多线程和多进程有啥区别。
为什么说 Linux 中线程和进程基本没有区别呢,因为从 Linux 内核的角度来看,并没有把线程和进程区别对待。
我们知道系统调用 fork() 可以新建一个子进程,函数 pthread() 可以新建一个线程。 但无论线程还是进程,都是用 task_struct 结构表示的,唯一的区别就是共享的数据区域不同 。
换句话说,线程看起来跟进程没有区别,只是线程的某些数据区域和其父进程是共享的,而子进程是拷贝副本,而不是共享。就比如说, mm 结构和 files 结构在线程中都是共享的,我画两张图你就明白了:
所以说,我们的多线程程序要利用锁机制,避免多个线程同时往同一区域写入数据,否则可能造成数据错乱。
那么你可能问, 既然进程和线程差不多,而且多进程数据不共享,即不存在数据错乱的问题,为什么多线程的使用比多进程普遍得多呢 ?
因为现实中数据共享的并发更普遍呀,比如十个人同时从一个账户取十元,我们希望的是这个共享账户的余额正确减少一百元,而不是希望每人获得一个账户的拷贝,每个拷贝账户减少十元。
当然,必须要说明的是, 只有 Linux 系统将线程看做共享数据的进程 ,不对其做特殊看待 ,其他的很多操作系统是对线程和进程区别对待的,线程有其特有的数据结构,我个人认为不如 Linux 的这种设计简洁,增加了系统的复杂度。
在 Linux 中新建线程和进程的效率都是很高的,对于新建进程时内存区域拷贝的问题,Linux 采用了 copy-on-write 的策略优化,也就是并不真正复制父进程的内存空间,而是等到需要写操作时才去复制。 所以 Linux 中新建进程和新建线程都是很迅速的 。