Linux学习

参考链接:

inode

下载软件:

一、源码安装
软件的源代码,也就是软件的原始数据,任何人都可以通过源代码查看该软件的设计架构和实现方法,但软件源代码无法再计算机中直接运行安装,需要将源代码通过编译转换为计算机可以识别的机器语言,然后才可以安装。
Linux 系统中,绝大多数软件的源代码都是用 C 语言编写的,少部分用 C++(或其他语言)编写。因此要想安装源码包,必须安装 gcc 编译器(如果涉及 C++ 源码程序,还需要安装 gcc-c++)。
安装 gcc 之前,可先使用如下命令看看是否已经安装:
[root@localhost ~]# rpm -q gcc
gcc-4.4.6-4.el6.i686
如果未安装,考虑到安装 gcc 所依赖的软件包太多,推荐大家使用 yum 安装 gcc。
除了安装编译器,还需要安装 make 编译命令。要知道,编译源码包可不像编译一个 hello.c 文件那样轻松,包中含大量的源码文件,且文件之间有着非常复杂的关联,直接决定着各文件编译的先后顺序,因此手动编译费时费力,而使用 make 命令可以完成对源码包的自动编译。
同样,在安装 make 命令之前,可使用如下命令查看其是否已经安装:
[root@localhost yum. repos.d]# rpm -q make
make-3.81-20.el6.i686
如果未安装,可使用 yum -y install make 命令直接安装 make。
安装好了 gcc 编译器和 make 编译工具,接下来学习使用源码包安装软件。

安装步骤:
  1、下载源码包
  2、将源码包进行解压缩,使用命令如下:
    [root@localhost ~]#tar -zxvf httpd-2.2.9.tar.gz|more
  3、进入解压目录,执行命令:
    ./configure 软件配置与检查。这一步主要完成以下 3 项任务:
检测系统环境是否符合安装要求。
定义需要的功能选项。通过 "./configure--prefix=安装路径" 可以指定安装路径。注意,configure 不是系统命令,而是源码包软件自带的一个脚本程序,所以必须采用 "./configure" 方式执行("./" 代表在当前目录下)。
"./configure" 支持的功能选项较多,可执行 "./configure--help" 命令查询其支持的功能,例如:
[root@localhost httpd-2.2.9]#./configure --help|more
#查询apache支持的选项功能(不是必需步骤)
把系统环境的检测结果和定义好的功能选项写入 Makefile 文件,因为后续的编译和安装需要依赖这个文件的内容。
  4、make 编译。make 会调用 gcc 编译器,并读取 Makefile 文件中的信息进行系统软件编译。编译的目的就是把源码程序转变为能被 Linux 识别的可执行文件,这些可执行文件保存在当前目录下。
    执行的编译命令如下:
    [root@localhost httpd-2.2.9]# make
    编程过程较为耗时,需要有足够的耐心。
  5、正式开始安装软件,这里通常会写清程序的安装位置,如果没有,则建议读者把安装的执行过程保存下来,以备将来删除软件时使用。安装指令如下:
    [root@localhost httpd-2.2.9]# make install
    整个过程不报错,即为安装成功。
    安装源码包过程中,如果出现“error”(或“warning”)且安装过程停止,表示安装失败;反之,如果仅出现警告信息,但安装过程还在继续,这并不是安装失败,顶多使软件部分功能无法使用。
    注意,如果在 "./configure" 或 "make" 编译中报错,则在重新执行命令前一定要执行 make clean 命令,它会清空 Makefile 文件或编译产生的 ".o" 头文件。
nginx 下载安装
源码包安装:
https://www.jianshu.com/p/d5114a2a2052
安装依赖包:https://www.cnblogs.com/zrbfree/p/6419043.html
总流程:https://segmentfault.com/a/1190000007116797
1、官网下载nginx包,解压==>编译(可能需要下载gcc,若没有yum install gcc)
2、下载依赖包
3、进入nginx解压后文件,执行./configure(可能失败 执行yum install gcc)
4、make && make install(若失败 下载3个依赖包)
nginx 的安装目录。默认 /usr/local/nginx 配置文件也在里面
启动:在/usr/local/nginx/sbin
安装nginx
官网:http://nginx.org/
GCC 依赖包
  pcre-8.42.tar.gz (一个Perl库,包括 perl 兼容的正则表达式库)
  openssl-1.1.1.tar.gz(为网络通信提供安全及数据完整性的一种安全协议,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用)
  zlib-1.2.11.tar.gz(提供数据压缩用的函式库)
  nginx-1.15.4.tar.gz(这个是执行./configure --prefix=/usr/local/nginx;前面三个进入解压缩目录,执行./configure)
sudo apt install build-essential:
 解压缩openssl-xx.tar.gz包。 tar -zxvf openssl-1.1.1.tar.gz 进入解压缩目录,执行./config make && sudo make install
sudo apt install libtool
启动命令:sudo nginx # 指定conf文件启动 sudo nginx -c /FILE/PATH/nginx.conf
关闭命令:nginx -s stop
重新加载命令:nginx -s reload

内存管理:

原文地址:https://www.cnblogs.com/vamei/archive/2012/10/09/2715388.html https://www.cnblogs.com/vamei/p/9329278.html
在Linux文件管理中,我们知道,一个文件除了自身的数据之外,还有一个附属信息,即文件的元数据(metadata)。这个元数据用于记录文件的许多信息,比如文件大小,拥有人,所属的组,修改日期等等。元数据并不包含在文件的数据中,而是由操作系统维护的。事实上,这个所谓的元数据就包含在inode中。我们可以用$ls -l filename来查看这些元数据。正如我们上面看到的,inode所占据的区域与数据块的区域不同。每个inode有一个唯一的整数编号(inode number)表示。

在保存元数据,inode是“文件”从抽象到具体的关键。正如上一节中提到的,inode储存由一些指针,这些指针指向存储设备中的一些数据块,文件的内容就储存在这些数据块中。当Linux想要打开一个文件时,只需要找到文件对应的inode,然后沿着指针,将所有的数据块收集起来,就可以在内存中组成一个文件的数据了。

为什么iNode存储指针,指针再指向数据块(分散的)?
因为如果按照顺序放,DVD就是这样,但如果有删除操作,删除造成的空余空间夹杂在正常文件之间,很难利用和管理。
还可以使用链表,每个数据块都有一个指针,指向属于同一文件的下一个数据块。这样的好处是可以利用零散的空余空间,坏处是对文件的操作必须按照线性方式进行。如果想随机存取,那么必须遍历链表,直到目标位置。由于这一遍历不是在内存进行,所以速度很慢。
进程如何使用内存。当程序文件运行为进程时,进程在内存中获得空间。这个空间是进程自己的小屋子。
每个进程空间按照如下方式分为不同区域:

内存空间
Text区域用来储存指令(instruction),说明每一步的操作。Global Data用于存放全局变量,栈(Stack)用于存放局部变量,堆(heap)用于存放动态变量 (dynamic variable. 程序利用malloc系统调用,直接从内存中为dynamic variable开辟空间)。Text和Global data在进程一开始的时候就确定了,并在整个进程中保持固定大小。

栈(Stack)以帧(stack frame)为单位。当程序调用函数的时候,比如main()函数中调用inner()函数,stack会向下增长一帧。帧中存储该函数的参数和局部变量,以及该函数的返回地址(return address)。此时,计算机将控制权从main()转移到inner(),inner()函数处于激活(active)状态。位于栈最下方的帧,和全局变量一起,构成了当前的环境(context)。激活函数可以从环境中调用需要的变量。典型的编程语言都只允许你使用位于stack最下方的帧 ,而不允许你调用其它的帧 (这也符合stack结构“先进后出”的特征。但也有一些语言允许你调用栈的其它部分,相当于允许你在运行inner()函数的时候调用main()中声明的局部变量,比如Pascal)。当函数又进一步调用另一个函数的时候,一个新的帧会继续增加到栈的下方,控制权转移到新的函数中。当激活函数返回的时候,会从栈中弹出(pop,读取并从栈中删除)该帧,并根据帧中记录的返回地址,将控制权交给返回地址所指向的指令(比如从inner()函数中返回,继续执行main()中赋值给main2的操作)。

下图是栈在运行过程中的变化。箭头表示栈的增长方向。每个方块代表一帧。开始的时候我们有一个为main()服务的帧,随着调用inner(),我们为inner()增加一个帧。在inner()返回时,我们再次只有main()的帧,直到最后main()返回,其返回地址为空,所以进程结束。

stack变化
在进程运行的过程中,通过调用和返回函数,控制权不断在函数间转移。进程可以在调用函数的时候,原函数的帧中保存有在我们离开时的状态,并为新的函数开辟所需的帧空间。在调用函数返回时,该函数的帧所占据的空间随着帧的弹出而清空。进程再次回到原函数的帧中保存的状态,并根据返回地址所指向的指令继续执行。上面过程不断继续,栈不断增长或减小,直到main()返回的时候,栈完全清空,进程结束。

当程序中使用malloc的时候,堆(heap)会向上增长,其增长的部分就成为malloc从内存中分配的空间。malloc开辟的空间会一直存在,直到我们用free系统调用来释放,或者进程结束。一个经典的错误是内存泄漏(memory leakage), 就是指我们没有释放不再使用的堆空间,导致堆不断增长,而内存可用空间不断减少。

栈和堆的大小则会随着进程的运行增大或者变小。当栈和堆增长到两者相遇时候,也就是内存空间图中的蓝色区域(unused area)完全消失的时候,再无可用内存。进程会出现栈溢出(stack overflow)的错误,导致进程终止。在现代计算机中,内核一般会为进程分配足够多的蓝色区域,如果清理及时,栈溢出很容易避免。即便如此,内存负荷过大,依然可能出现栈溢出的情况。我们就需要增加物理内存了。

在高级语言中,这些内存管理的细节对于用户来说不透明。在编程的时候,我们只需要记住上一节中的变量作用域就可以了。但在想要写出复杂的程序或者debug的时候,我们就需要相关的知识了。

原文地址:https://www.cnblogs.com/luoyangyang/p/10635554.html