文件目录

  • /bin
    bin是Binary的缩写, 这个目录存放着最经常使用的命令。
  • /boot:
    这里存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。
  • /dev :
    dev是Device(设备)的缩写, 该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
  • /etc:
    这个目录用来存放所有的系统管理所需要的配置文件和子目录。
  • /home
    用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。
  • /lib
    这个目录里存放着系统最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。
  • /lost+found
    这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。
  • /media
    linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后,linux会把识别的设备挂载到这个目录下。
  • /mnt
    系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/上,然后进入该目录就可以查看光驱里的内容了。
  • /opt
    这是给主机额外安装软件所摆放的目录。比如你安装一个ORACLE数据库则就可以放到这个目录下。默认是空的。
  • /proc
    这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。

Linux文件类型

  • 普通文件(-)
  • 目录(d)
  • 软链接(字符链接L)
  • 套接字文件(S)
  • 字符设备(S)
  • 块设备(B)
  • 管道文件(命名管道P)

通过ls -l的第一个字符可以判断。

常见命令

  • ls的参数有哪些以及作用
    1. -l
      列举目录内容的细节,包括权限,所有者,组群,大小,创建日期,文件是否是链接等。
    2. -a
      显示全部文件,包括隐藏文件。
  • vim回到第一行
    gg
  • 快速到命令的最左边和最右边
    Ctrl+a
    Ctrl+e
  • 查看头10行和末10行
    head -n 10 文件路径
    tail -n 10 文件路径
  • 查找线程
    ps -ef | grep "名字"
  • rpm包怎么安装?怎么卸载?
    rpm -ivh
    rpm -e
  • 如何查看文件的第3行到第9行?
    sed -n '3,9p' 文件名
  • netstat相关
    1. -a (all)
      显示所有选项,默认不显示LISTEN相关。
    2. -t (tcp)
      仅显示tcp相关选项。
    3. -u (udp)
      仅显示udp相关选项。
    4. -n
      拒绝显示别名,能显示数字的全部转化成数字。
    5. -l
      仅列出有在 Listen (监听) 的服务状态。

找出程序运行的端口:netstat -anp | grep "ssh"
找出运行在指定端口上的进程号:netstat -anp | grep ":3306";

  • 如何往文件写东西?
    追加命令:echo "hello" >> hello.txt
    覆盖命令:echo "hello" > hello.txt
  • awk打印内容
    awk '{print}' hello.txt

软链接和硬链接的作用与区别

作用

  • 软链接:ln -s 源文件 目标文件
    可以理解成快捷方式。它和windows下的快捷方式的作用是一样的。
  • 硬链接:ln 源文件 目标文件
    等于cp -p加同步更新。

区别

软链接 硬链接
incode 拥有不同的incode,说明是两个不同的文件 拥有相同的incode,是同一个文件
跨越文件系统建立 支持 不支持
存在形式 以路径的形式存在 以副本的形式存在,但不占用实际空间
是否能对不存在的文件链接 可以 不可以
是否能对目录进行链接 可以 不可以

特殊进程

idle(PID=0)

由系统自动创建,运行在内核态 ,它是唯一一个没有通过fork或者kernel_thread产生的进程。

kthreadd(PID=2,PPID=0)

由idle通过kernel_thread创建,并始终运行在内核空间,负责所有内核线程的调度和管理。

init(PID=1,PPID=0)

由idle通过kernel_thread创建,在内核空间完成初始化后,加载init程序,并最终用户空间创建。init进程由0进程创建,完成系统的初始化,是系统中所有其它用户进程的祖先进程。

加载过程为:0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程。

另外,init进程还会负责收集孤儿进程。

free命令中buffer与cache的区别

image-20200311165506618.png

  1. total:物理内存实际总量;
  2. used:这块千万注意,这里可不是实际已经使用了的内存哦,这里是总计分配给缓存(包含buffers 与cache )使用的数量,但其中可能部分缓存并未实际使用;
  3. free:未被分配的内存,实际可使用的内存;
  4. shared:共享内存;
  5. buffers:系统分配的,但未被使用的buffer剩余量。注意这不是总量,而是未分配的量;
  6. cached:系统分配的,但未被使用的cache 剩余量。buffer 与cache 的区别见后面;
  7. available:应用程序认为可用内存数量,available = free + buffer + cache 。(注:只是大概的计算方法)

Cache和Buffer

  • Cache
    高速缓存,主要用于查询,CPU的速度远高于内存速度,可以减少CPU的等待时间,提高效率。
    在free命令中是作为page cache的内存, 文件系统的cache。
  • Buffer
    缓冲区,主要用于写请求,当两个设备存储速度不同或者优先级不同,它可以使进程之间的相互等待变少,使速度快的操作不发生间断。
    在free命令中是作为buffer cache的内存,是块设备的读写缓冲区。

Page Cache和Buffer Cache

  • page cache
    文件系统层级的缓存,从磁盘里读取的内容是存储到这里,这样程序读取磁盘内容就会非常快,比如使用grep和find等命令查找内容和文件时,第一次会慢很多,再次执行就快好多倍,几乎是瞬间。但如上所说,如果对文件的更新不关心,就没必要清cache,否则如果要实施同步,必须要把内存空间中的cache clean下。
  • buffer cache
    磁盘等块设备的缓冲,内存的这一部分是要写入到磁盘里的。这种情况需要注意,位于内存buffer中的数据不是即时写入磁盘,而是系统空闲或者buffer达到一定大小统一写到磁盘中,所以断电易失,为了防止数据丢失所以我们最好正常关机或者多执行几次sync命令,让位于buffer上的数据立刻写到磁盘里。

信号

linux下有很多信号,按可靠性分为可靠信号和非可靠信号,按时间分为实时信号和非实时信号,linux进程也有三种方式来处理收到的信号:

  1. 忽略信号,即对信号不做任何处理,其中,有两个信号不能忽略:SIGKILL及SIGSTOP;
  2. 捕捉信号。定义信号处理函数,当信号发生时,执行相应的处理函数;
  3. 执行缺省操作,Linux对每种信号都规定了默认操作。

常见的五个信号

  • SIGINT 终止进程,通常我们的Ctrl+C就发送的这个消息。
  • SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl- \ )来控制. 进程收到该消息退出时会产生core文件。
  • SIGKILL 消息编号为9,我们经常用kill -9来杀死进程发送的就是这个消息,程序收到这个消息立即终止,这个消息不能被捕获,封锁或这忽略,所以是杀死进程的终极武器。
  • SIGTERM 是不带参数时kill默认发送的信号,默认是杀死进程。

SIGINT与SIGTERM区别

前者与字符ctrl+c关联,后者没有任何控制字符关联。

前者只能结束前台进程,后者则不是。

SIGTERM与SIGKILL的区别

前者可以被阻塞、处理和忽略,但是后者不可以。

KILL命令的默认不带参数发送的信号就是SIGTERM,让程序有好的退出。

SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。

因为SIGTERM可以被阻塞,所以有的进程不能被结束时,需要用kill发送SIGKILL。即:kill-9 进程号。

Linux创建进程的过程

在Linux中主要提供了fork、vfork、clone三个进程创建方法。
在linux源码中这三个调用的执行过程是执行fork(),vfork(),clone()时,通过一个系统调用表映射到sys_fork(),sys_vfork(),sys_clone(),再在这三个函数中去调用do_fork()去做具体的创建进程工作。

fork

参考操作系统篇,这边省略,主要关注两个返回值以及写时复制。

vfork

vfork系统调用不同于fork,用vfork创建的子进程与父进程共享地址空间,也就是说子进程完全运行在父进程的地址空间上,如果这时子进程修改了某个变量,这将影响到父进程。
但此处有一点要注意的是用vfork()创建的子进程必须显示调用exit()来结束,否则子进程将不能结束,而fork()则不存在这个情况。Vfork也是在父进程中返回子进程的进程号,在子进程中返回0。
用 vfork创建子进程后,父进程会被阻塞直到子进程调用exec(exec,将一个新的可执行文件载入到地址空间并执行之。)或exit。vfork的好处是在子进程被创建后往往仅仅是为了调用exec执行另一个程序,因为它就不会对父进程的地址空间有任何引用,所以对地址空间的复制是多余的 ,因此通过vfork共享内存可以减少不必要的开销。由于fork有了写时复制,vfork就不怎么用了。

clone

系统调用fork()和vfork()是无参数的,而clone()则带有参数。fork()是全部复制,vfork()是共享内存,而clone() 是则可以将父进程资源有选择地复制给子进程,而没有复制的数据结构则通过指针的复制让子进程共享,具体要复制哪些资源给子进程,由参数列表中的 clone_flags来决定。另外,clone()返回的是子进程的pid。

三者区别

  1. fork出来的子进程是父进程的一个拷贝,即,子进程从父进程得到了数据段和堆栈段的拷贝,这些需要分配新的内存,而对于只读的代码段,通常使用共享内存的方式访问;而vfork则是子进程与父进程共享内存空间, 子进程对虚拟地址空间任何数据的修改同样为父进程所见;clone则由用户通过参clone_flags的设置来决定哪些资源共享,哪些资源拷贝。
  2. fork不对父子进程的执行次序进行任何限制,fork返回后,子进程和父进程都从调用fork函数的下一条语句开始行,但父子进程运行顺序是不定的,它取决于内核的调度算法;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制;clone中由标志CLONE_VFORK来决定子进程在执行时父进程是阻塞还是运行,若没有设置该标志,则父子进程同时运行,设置了该标志,则父进程挂起,直到子进程结束为止。

    Linux执行二进制文件的过程

    在安装软件的时候,通常使用./xxx运行二进制文件即可,其实背后是依赖了自带的c语言的编译-汇编-链接过程