Linux进程阅读
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux进程阅读相关的知识,希望对你有一定的参考价值。
文章目录
Linux进程阅读
0.疑惑
僵尸进程、还有COW(Copy On Write)、Flock(File Lock)、Epoll和Namespace的概念又是否了解过呢?
1.Docker环境进行
docker run -i -t tobegit3hub/understand_linux_process_examp
2.进程基础
PPID 就是父进程ID 第一个P是Parent
为什么进程都会有父进程ID呢?因为进程都是由父进程衍生出来的,后面会详细介绍几种衍生的方法。那么跟人类起源问题一样,父进程的父进程的父进程又是什么呢?实际上有一个PID为1的进程是由内核创建的init进程,其他子进程都是由它衍生出来,所以前面的描述并不准确,进程号为1的进程并没有PPID。
因为所有进程都来自于一个进程,所以Linux的进程模型也叫做进程树。
要想获得进程的PPID,可以通过以下Getppid()
这个函数来获得
有趣的事情发生了,有没有发现每次运行的父进程ID都不一样,这不符合我们的预期啊,原来我们通过
go run
每次都会启动一个新的Go虚拟机来执行进程。
拿到PID后,我们就可以通过kill
命令来结束进程了,也可以通过kill -9
或其他数字向进程发送不同的信号。
信号是个很重要的概念,我们后面会详细介绍,那么有了进程ID,我们也可以看看进程名字。
每个进程都一定有进程名字,例如我们运行top
,进程名就是“top”,如果是自定义的程序呢?
其实进程名一般都是进程参数的第一个字符串,在Go中可以这样获得进程名。
获取进程参数
获得进程Flag
使用Flag可以更容易得将命令行参数转化成我们需要的数据类型,其中flag.go代码如下
a.进程输入与输出
每个进程操作系统都会分配三个文件资源,分别是标准输入(STDIN)、标准输出(STDOUT)和错误输出(STDERR)。通过这些输入流,我们能够轻易得从键盘获得数据,然后在显示器输出数据。
来自管道(Pipe)的数据也是标准输入的一种,我们写了以下的实例来输出标注输入的数据。
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
bytes, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}
3.并发与并行
并发(Concurrently)和并行(Parallel)是两个不同的概念。借用Go创始人Rob Pike的说法,并发不是并行,并发更好。并发是一共要处理(deal with)很多事情,并行是一次可以做(do)多少事情。
举个简单的例子,华罗庚泡茶,必须有烧水、洗杯子、拿茶叶等步骤。现在我们想尽快做完这件事,也就是“一共要处理很多事情”,有很多方法可以实现并发,例如请多个人同时做,这就是并行。并行是实现并发的一种方式,但不是唯一的方式。我们一个人也可以实现并发,例如先烧水、然后不用等水烧开就去洗杯子,所以通过调整程序运行方式也可以实现并发。
前面提到多进程的并行可以提高并发度,那么进程是越多越好?一般遇到这种问题都回答不是,事实上,很多大型项目都不会同时开太多进程。
下面以支持100K并发量的nginx服务器为例。
举个例子: Nginx
Nginx是一个高性能、高并发的Web服务器,也就是说它可以同时处理超过10万个HTTP请求,而它建议的启动的进程数不要超过CPU个数,为什么呢?
我们首先要知道Nginx是Master-worker模型,Master进程只负责管理Worker进程,而Worker进程是负责处理真实的请求。每个Worker进程能够处理的请求数跟内存有关,因为在Linux上Nginx使用了epoll这种多路复用的IO接口,所以不需要多线程做并行也能实现并发。
而多进程有一个坏处就是带来了CPU上下文切换时间,所以一味提高进程个数反而使系统系能下降。当然如果当前进程小于CPU个数,就没有充分利用多核的资源,所以Nginx建议Worker数应该等于CPU个数。
4.进程状态
5.查看状态
通过ps aux
可以看到进程的状态。
O:进程正在处理器运行,这个状态从来没有见过.
S:休眠状态(sleeping)
R:等待运行(runable)R Running or runnable (on run queue) 进程处于运行或就绪状态
I:空闲状态(idle)
Z:僵尸状态(zombie)
T:跟踪状态(Traced)
B:进程正在等待更多的内存页
D: 不可中断的深度睡眠,一般由IO引起,同步IO在做读或写操作时,cpu不能做其它事情,只能等待,这时进程处于这种状态,如果程序采用异步IO,这种状态应该就很少见到了
其中就绪状态表示进程已经分配到除CPU以外的资源,等CPU调度它时就可以马上执行了。运行状态就是正在运行了,获得包括CPU在内的所有资源。等待状态表示因等待某个事件而没有被执行,这时候不耗CPU时间,而这个时间有可能是等待IO、申请不到足够的缓冲区或者在等待信号。
6.进程文件
7.POSIX
POSIX(Portable Operation System Interface)听起来好高端,就是一种操作系统的接口标准,至于谁遵循这个标准呢?就是大名鼎鼎的Unix和Linux了,有人问Mac OS是否兼容POSIX呢,答案是Yes苹果的操作系统也是Unix-based的。
有了这个规范,你就可以调用通用的API了,Linux提供的POSIX系统调用在Unix上也能执行,因此学习Linux的底层接口最好就是理解POSIX标准。
补充一句,目前很多编程语言(Go、Java、Python、Ruby等)都是天生跨平台的,因此我们很少注意系统调用的兼容性。实际上POSIX提供了这些语言上跨平台的语义,而且这是源码级别的保证。
8.NuHup
每个开发者都会躺过这个坑,在命令行跑一个后台程序,关闭终端后发现进程也退出了,网上搜一下发现要用
nohup
,究竟什么原因呢?原来普通进程运行时默认会绑定TTY(虚拟终端),关闭终端后系统会给上面所有进程发送TERM信号,这时普通进程也就退出了。当然还有些进程不会退出,这就是后面将会提到的守护进程。
Nohup
的原理也很简单,终端关闭后会给此终端下的每一个进程发送SIGHUP信号,而使用nohup
运行的进程则会忽略这个信号,因此终端关闭后进程也不会退出。
10.源文地址
https://tobegit3hub1.gitbooks.io/understanding-linux-processes/content/go_example/README.html
以上是关于Linux进程阅读的主要内容,如果未能解决你的问题,请参考以下文章
Linux。 C 中的管道。将数据发送到另一个进程。写作和阅读