在Linux中,TTY也许是跟终端有关系的最为混乱的术语。TTY是TeleTYpe的一个老缩写
Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,和古老的电报机区别并不是很大。之后,当计算机只能以批处理方式运行时(当时穿孔卡片阅读器是唯一一种使程序载入运行的方式),电传打字机成为唯一能够被使用的“实时”输入/输出设备。最终,电传打字机被键盘和显示器终端所取代,但在终端或TTY接插的地方,操作系统仍然需要一个程序来监视串行端口。
一个getty“Get TTY”的处理过程是:一个程序监视物理的TTY/终端接口。对一个虚拟网络服务器(VNC)来说,一个伪装的TTY(Pseudo-TTY,即假冒的TTY,也叫做“PTY”)是等价的终端。
当你运行一个xterm(终端仿真程序)或GNOME终端程序时,PTY对虚拟的用户或者如xterm一样的伪终端来说,就像是一个TTY在运行。“Pseudo”的意思是“duplicating in a fake way”(用伪造的方法复制),它相比“virtual”或“emulated”更能真实的说明问题。而在的计算中,它却处于被放弃的阶段。
tty也是一个Unix命令,用来给出当前终端设备的名称。
终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。
在Linux系统的设备特殊文件目录/dev/下,终端特殊设备文件一般有以下几种:
1. 串行端口终端(/dev/ttySn)
串 行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。有段时间这些串行端口设备通常被称为终端设备,因为那时它的最大用途就是用来连接终端。
这些串行端口所对应的设备名称是/dev/tts/或/dev/ttyS0、/dev/tts/1(或/dev /ttyS1)等,设备号分别是(4,0)、(4,1)等,分别对应于DOS系统下的COM1、COM2等。
若要向一个端口发送数据,可以在命令行上把标 准输出重定向到这些特殊文件名上即可。例如,在命令行提示符下键入:echo test > /dev/ttyS1会把单词”test”发送到连接在ttyS1(COM2)端口的设备上。
2. 伪终端(/dev/pty/)
伪终端 (Pseudo Terminal)是成对的逻辑终端设备,例如/dev/ptyp3和/dev/ttyp3(或着在设备文件系统中分别是/dev/pty/m3和 /dev/pty/s3),它们与实际物理设备并不直接相关。
如果一个程序把ttyp3看作是一个串行端口设备,则它对该端口的读/写操作会反映在该逻辑终端设备对的另一个上面(ttyp3)。而ttyp3则是另一个程序用于读写操作的逻辑设备。
这样,两个程序就可以通过这种逻辑设备进行互相交流,而其中 一个使用ttyp3的程序则认为自己正在与一个串行端口进行通信。这很像是逻辑设备对之间的管道操作。
对于ttyp3(s3),任何设计成使用一个串行端口设备的程序都可以使用该逻辑设备。但对于使用ptyp3的程序,则需要专门设计来使用ptyp3(m3)逻辑设备。
例如,如果某人在网上使用telnet程序连接到你的计算机上,则telnet程序就可能会开始连接到设备ptyp2(m2)上(一个伪终端端口上)。此时 一个getty程序就应该运行在对应的ttyp2(s2)端口上。当telnet从远端获取了一个字符时,该字符就会通过m2、s2传递给getty程 序,而getty程序就会通过s2、m2和telnet程序往网络上返回”login:”字符串信息。这样,登录程序与telnet程序就通过“伪终端” 进行通信。通过使用适当的软件,就可以把两个甚至多个伪终端设备连接到同一个物理串行端口上。
在使用设备文件系统(device filesystem)之前,为了得到大量的伪终端设备特殊文件,HP-UX AIX等使用了比较复杂的文件名命名方式。
3. 控制终端(/dev/tty)
如果当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可以使用命令”ps –ax”来查看进程与哪个控制终端相连。
shell是一个命令行解释器,是Linux内核的一个外壳,负责外界与Linux内核的交互。shell接收用户或者其他应用程序的命令, 然后将这些命令转化成内核能理解的语言并传给内核, 内核执行命令完成后将结果返回给用户或者应用程序。当你打开一个terminal时,操作系统会将terminal和shell关联起来,当我们在terminal中输入命令后,shell就负责解释命令。
对于你登录的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”可以查看它具体对应哪个实际终端设备。/dev/tty有些类似于到实际所使用终端设备的一个联接。
4. 控制台终端(/dev/ttyn, /dev/console)
在 UNIX系统中,计算机显示器通常被称为控制台终端(Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特 殊文件与之相关联:tty0、tty1、tty2等。
当你在控制台上登录时,使用的是tty1。使用Alt+[F1-F6]组合键时,我们就可以切换到 tty2、tty3等上面。
tty1 –tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上。因此不管当前正在使用哪个虚拟终端,系统信 息都会发送到控制台终端上。
你可以登录到不同的虚拟终端上去,因而可以让系统同时有几个不同的会话期存在。只有系统或超级用户root可以向/dev/tty0进行写操作。
5. 虚拟终端
在Xwindow模式下的伪终端.如在Kubuntu下用konsole,就是用的虚拟终端,用tty命令可看到/dev/pts/name, name为当前用户名。
6. 其他类型
Linux系统中还针对很多不同的字符设备存在有很多其它种类的终端设备特殊文件。
例如针对ISDN设备的/dev/ttyIn终端设备等。tty设备包括虚拟控制台,串口以及伪终端设备。
/dev/tty代表当前tty设备,在当前的终端中输入 echo “hello” > /dev/tty ,都会直接显示在当前的终端中。
Text Telephones (TTY)
聋哑人电话,在手机插入专用设备后支持收发文本,需网络支持,中国网络不支持TTY。
除聋哑模式外,还支持只听不说(HCO)和只说不听(VCO)两种模式
tty只查看当前终端。
w命令w的功能最全面,能显示用户登录名、终端标志、星期几登录和具体登录时间、闲置时间、用户正在执行的程序、占用CPU时间、系统的运行时间和平均负载。
who命令的功能较简单,仅显示用户登录名、终端标志、和登录日期和时间。
切换图形界面: crtl+alt+F2
不同终端切换: Alt+F1-F6
打开终端:Ctrl+Alt+T
打开虚拟终端: crtl+shift+T
切换终端:ALT+1 2 3
关闭虚拟终端:Alt+F4
放大字体分辨率:crtl+shift+加号
1、Ctrl+C比较暴力,就是发送Terminal到当前的程序,比如你正在运行一个查找功能,文件正在查找中,Ctrl+C就会强制结束当前的这个进程。
2、Ctrl+Z是把当前的程序挂起(把程序放到后台返回终端),暂停执行这个程序,比如你正在mysql终端中,需要出来搞点其他的文件操作,又不想退出mysql终端(因为下次还得输入用户名密码进入,挺麻烦),于是可以从Ctrl+z将mysql挂起,然后进行其他操作,然后输入fg回车后就可以回来,当然可以挂起好多进程到后台,然后fg 加编号就能把挂起的进程返回到前台。当然,配合bg和fg命令进行前后台切换会非常方便。
3、Ctrl+D 退出当前 Shell,功能相当于命令 exit,没有那么强烈,类似Ctrl+C的操作,比如你从管理员root退回到你的普通用户就可以这么用。
4、Ctrl+L 清空屏幕 (功能相当于命令 clear)
5、Ctrl+U 剪切文本直到行的起始 (可以用于清空行)
6、Ctrl+K 剪切文本直到行的末尾
7、Ctrl+Y 粘贴最近剪切的文本
8、Ctrl+A 行首
9、Ctrl+E 行尾
10、Home/End 行首 / 行尾
11、Ctrl+F 向前移动一个字符
12、Ctrl+B 向后移动一个字符
13、Ctrl+P 或 Ctrl+N 上下历史记录
14、上下方向键 上下历史记录
15、Ctrl+Shift+C 复制
16、Ctrl+Shift+V 粘贴
17、Tab 智能自动补全 (相当强大)
18、按住 Ctrl 键进行块选择.
19、鼠标中键:粘贴
20、jobs 查看后台任务
21、fg NUM 切换到后台任务
Linux时钟分为系统时钟(System Clock)和硬件(Real Time Clock,简称RTC)时钟。系统时钟是指当前Linux Kernel中的时钟,而硬件时钟则是主板上由电池供电的时钟,这个硬件时钟可以在BIOS中进行设置。
Linux中的所有命令(包括函数)都是采用的系统时钟设置。Linux操作系统运行时间长了,系统时间就会存在一定的误差,一般情况下可以使用date命令进行时间设置,但在很多生产环境中对服务器的时间准确性是有严格要求的,此时就需要使用ntpdate进行时间同步。
time命令最常用的使用方式就是在其后面直接跟上命令和参数:
time <command> [<arguments...>]
在命令执行完成之后就会打印出CPU的使用情况:
- real 0m5.064s <== 实际使用时间(real time)
- user 0m0.020s <== 用户态使用时间(the process spent in user mode)
- sys 0m0.040s <== 内核态使用时间(the process spent in kernel mode)
手动修改时间
date : 查看当前时间,结果如下:
2015年 06月 08日 星期一 18:21:08 CST
date -s 19:38:40: 设置当前时间,结果如下:
2015年 06月 08日 星期一 19:38:40 CST
说明:
date –s:按字符串方式修改时间
可以只修改日期,不修改时间,输入:
- date -s 2015-06-18
- Or
- date -s 06/18/15
只修改时间,输入:
date -s 15:15:00
同时修改日期时间,注意要加双引号,日期与时间之间有一空格,输入:
sudo date -s "2015-06-18 15:15:00"
安装ntpdate工具:
yum -y install ntp ntpdate
网络时间同步命令:
ntpdate -u 202.120.2.101
注意:若不加上-u参数, 会出现以下提示:
no server suitable for synchronization found
-u:从man ntpdate中可以看出-u参数可以越过防火墙与主机同步;
ntp常用服务器:
- 202.120.2.101:上海交通大学网络中心NTP服务器地址
- 210.72.145.44:中国国家授时中心的官方服务器。(经测试目前有问题)
- ntp.sjtu.edu.cn 202.120.2.101: 上海交通大学网络中心NTP服务器地址
- cn.pool.ntp.org:中国教育科研机构
- time.nist.gov:美国
- ntp.fudan.edu.cn:复旦
- time.windows.com:微软公司授时主机(美国)
- asia.pool.ntp.org:台警大授时中心(台湾)
步骤一:修改Linux系统时间:linux系统时钟有两个,一个是硬件时钟,即BIOS时间,就是我们进行CMOS设置时看到的时间,另一个是系统时钟,是linux系统Kernel时间。当Linux启动时,系统Kernel会去读取硬件时钟的设置,然后系统时钟就会独立于硬件运作。有时我们会发现系统时钟和硬件时钟不一致,因此需要执行时间同步。
将时间设置为2014年6月18日14点16分30秒(MMDDhhmmYYYY.ss):
date 0618141614.30
步骤二:hwclock/clock 命令查看、设置硬件时间
查看系统硬件时钟:
- sudo hwclock
- Or
- hwclock --show
- Or
- clock --show
设置硬件时间:
- hwclock --set --date=“06/18/14 14:55” (月/日/年时:分:秒)
- Or
- clock --set --date=“06/18/14 14:55” (月/日/年时:分:秒)
步骤三:同步系统及硬件时钟。
下图中可以看到硬件和系统时钟相差半小时。可以使用hwclock或者clock进行同步,
硬件时钟与系统时钟同步:
- hwclock --hctosys
- Or
- clock --hctosys //hc代表硬件时间,sys代表系统时间,即用硬件时钟同步系统时钟
系统时钟和硬件时钟同步(系统时间同步到CMOS):
- hwclock --systohc
- Or
- clock --systohc //即用系统时钟同步硬件时钟
上述提到的是手动设置时间到一个时间点,可能与当前网络的时间有误差。可以用时间服务器上的时间同步的方法。
设置系统时间与网络时间同步:
ntpdate cn.pool.ntp.org or ntp1.aliyun.com
将系统时间写入硬件时间:
hwclock --systohc
步骤一:时区设置:
开始设置时区时,参考网上的资料,使用tzselect 命令来进行,结果发现tzselect命令只是告诉了设置时区的方法,而并不是真的去修改/etc/sysconfig/clock这个文件。
换句话说就是tzselect命令仅仅告诉我们通过设置TZ这个环境变量来选择的时区,然后将变量添加到.profile文件中。
下面就简单介绍一下如何使用tzselect命令设置时区,以及如何通过修改/etc/sysconfig/clock配置文件来设置时区。
步骤二:临时生效
执行tzselect命令–>选择Asia–>选择China–>选择east China - Beijing, Guangdong, Shanghai, etc–>然后输入1。
步骤三:执行完tzselect命令选择时区后,时区并没有更改,只是在命令最后提示你可以执行:
- tzselect
- export TZ='Asia/Shanghai';
- Or
- TZ=‘Asia/Shanghai’; export TZ
并将这行命令添加到.profile中,然后退出并重新登录。
使用date命令,最终时区显示为CST,即中国标准时间。
步骤四:修改配置文件来修改时区:
1、修改/etc/sysconfig/clock
- vi /etc/sysconfig/clock
- ZONE=Asia/Shanghai
2、rm /etc/localtime
3、链接到上海时区文件
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
执行完上述过程后,重启机器,即可看到时区已经更改。
使用 Linux 时,通过命令行输入 ls -l / 可以看到,在 Linux 根目录(/)下包含很多的子目录(称为一级目录),例如 bin、boot、dev 等。同时,各一级目录下还含有很多子目录(称为二级目录),比如 /bin/bash、/bin/ed 等。Linux 文件系统目录总体呈现树形结构,/ 根目录就相当于树根。
由于 Linux 系统免费开源,使得 Linux 发行版本有很多,利用 Linux 开发产品的团队也有很多,如果任由每个人都按照自己的想法来配置 Linux 系统文件目录,后期可能会产生诸多的管理问题。试想,如果你进入一家公司,所用 Linux 系统的文件目录结构与所学的完全不同,实在令人头疼。
为了避免诸多使用者对 Linux 系统目录结构天马行空,Linux 基金会发布了 FHS 标准。多数 Linux 发行版系统都遵循这一标准。
FHS(Filesystem Hierarchy Standard),文件系统层次化标准,该标准规定了 Linux 系统中所有一级目录以及部分二级目录(/usr 和 /var)的用途。发布此标准的主要目的就是为了让用户清楚地了解每个目录应该存放什么类型的文件。
FHS 认为,Linux 系统的根目录(/)最为重要(没有之一),其原因有以下 2 点:
1. 所有目录都是由根目录衍生出来的;
2. 根目录与系统的开机、修复、还原密切相关;
因此,根目录必须包含开机软件、核心文件、开机所需程序、函数库、修复系统程序等文件。
一级目录 | 功能(作用) |
---|---|
/bin/ | 存放系统命令,普通用户和 root 都可以执行。放在 /bin 下的命令在单用户模式下也可以执行 |
/boot/ | 系统启动目录,保存与系统启动相关的文件,如内核文件和启动引导程序(grub)文件等 |
/dev/ | 设备文件保存位置 |
/etc/ | 配置文件保存位置。系统内所有采用默认安装方式(rpm 安装)的服务配置文件全部保存在此目录中,如用户信息、服务的启动脚本、常用服务的配置文件等 |
/home/ | 普通用户的宿主目录。在创建用户时,每个用户要有一个默认登录和保存自己数据的位置,就是用户的宿主目录,所有普通用户的宿主目录是在 /home/ 下建立一个和用户名相同的目录。如用户 liming 的宿主目录就是 /home/liming |
/lib/ | 系统调用的函数库保存位置 |
/media/ | 挂载目录。系统建议用来挂载媒体设备,如软盘和光盘 |
/mnt/ | 挂载目录。早期 Linux 中只有这一个挂载目录,并没有细分。系统建议这个目录用来挂载额外的设备,如 U 盘、移动硬盘和其他操作系统的分区 |
/misc/ | 挂载目录。系统建议用来挂载 NFS 服务的共享目录。虽然系统准备了三个默认挂载目录 /media/、/mnt/、/misc/,但是到底在哪个目录中挂载什么设备可以由管理员自己决定。例如,笔者在接触 Linux 的时候,默认挂载目录只有 /mnt/,所以养成了在 /mnt/ 下建立不同目录挂载不同设备的习惯,如 /mnt/cdrom/ 挂载光盘、/mnt/usb/ 挂载 U 盘,都是可以的 |
/opt/ | 第三方安装的软件保存位置。这个目录是放置和安装其他软件的位置,手工安装的源码包软件都可以安装到这个目录中。不过笔者还是习惯把软件放到 /usr/local/ 目录中,也就是说,/usr/local/ 目录也可以用来安装软件 |
/root/ | root 的宿主目录。普通用户宿主目录在 /home/ 下,root 宿主目录直接在“/”下 |
/sbin/ | 保存与系统环境设置相关的命令,只有 root 可以使用这些命令进行系统环境设置,但也有些命令可以允许普通用户查看 |
/srv/ | 服务数据目录。一些系统服务启动之后,可以在这个目录中保存所需要的数据 |
/tmp/ | 临时目录。系统存放临时文件的目录,在该目录下,所有用户都可以访问和写入。建议此目录中不能保存重要数据,最好每次开机都把该目录清空 |
FHS 针对根目录中包含的子目录仅限于表 1,但除此之外,Linux 系统根目录下通常还包含表 2 中的几个一级目录。
一级目录 | 功能(作用) |
---|---|
/lost+found/ | 当系统意外崩溃或意外关机时,产生的一些文件碎片会存放在这里。在系统启动的过程中,fsck 工具会检查这里,并修复已经损坏的文件系统。这个目录只在每个分区中出现,例如,/lost+found 就是根分区的备份恢复目录,/boot/lost+found 就是 /boot 分区的备份恢复目录 |
/proc/ | 虚拟文件系统。该目录中的数据并不保存在硬盘上,而是保存到内存中。主要保存系统的内核、进程、外部设备状态和网络状态等。如 /proc/cpuinfo 是保存 CPU 信息的,/proc/devices 是保存设备驱动的列表的,/proc/filesystems 是保存文件系统列表的,/proc/net 是保存网络协议信息的...... |
/sys/ | 虚拟文件系统。和 /proc/ 目录相似,该目录中的数据都保存在内存中,主要保存与内核相关的信息 |
usr(注意不是 user),全称为 Unix Software Resource,此目录用于存储系统软件资源。FHS 建议所有开发者,应把软件产品的数据合理的放置在 /usr 目录下的各子目录中,而不是为他们的产品创建单独的目录。
Linux 系统中,所有系统默认的软件都存储在 /usr 目录下,/usr 目录类似 Windows 系统中 C:\Windows\ + C:\Program files\ 两个目录的综合体。
HS 建议,/usr 目录应具备表 3 所示的子目录。
子目录 | 功能(作用) |
---|---|
/usr/bin/ | 存放系统命令,普通用户和超级用户都可以执行。这些命令和系统启动无关,在单用户模式下不能执行 |
/usr/sbin/ | 存放根文件系统不必要的系统管理命令,如多数服务程序,只有 root 可以使用。 |
/usr/lib/ | 应用程序调用的函数库保存位置 |
/usr/XllR6/ | 图形界面系统保存位置 |
/usr/local/ | 手工安装的软件保存位置。我们一般建议源码包软件安装在这个位置 |
/usr/share/ | 应用程序的资源文件保存位置,如帮助文档、说明文档和字体目录 |
/usr/src/ | 源码包保存位置。我们手工下载的源码包和内核源码包都可以保存到这里。不过笔者更习惯把手工下载的源码包保存到 /usr/local/src/ 目录中,把内核源码保存到 /usr/src/linux/ 目录中 |
/usr/include | C/C++ 等编程语言头文件的放置目录 |
/var 目录用于存储动态数据,例如缓存、日志文件、软件运行过程中产生的文件等。通常,此目录下建议包含如表 4 所示的这些子目录。
/var子目录 | 功能(作用) |
---|---|
/var/lib/ | 程序运行中需要调用或改变的数据保存位置。如 MySQL 的数据库保存在 /var/lib/mysql/ 目录中 |
/var/log/ | 登陆文件放置的目录,其中所包含比较重要的文件如 /var/log/messages, /var/log/wtmp 等。 |
/var/run/ | 一些服务和程序运行后,它们的 PID(进程 ID)保存位置 |
/var/spool/ | 里面主要都是一些临时存放,随时会被用户所调用的数据,例如 /var/spool/mail/ 存放新收到的邮件,/var/spool/cron/ 存放系统定时任务。 |
/var/www/ | RPM 包安装的 Apache 的网页主目录 |
/var/nis和/var/yp | NIS 服务机制所使用的目录,nis 主要记录所有网络中每一个 client 的连接信息;yp 是 linux 的 nis 服务的日志文件存放的目录 |
/var/tmp | 一些应用程序在安装或执行时,需要在重启后使用的某些文件,此目录能将该类文件暂时存放起来,完成后再行删除 |
根据以上各表列举的各目录及作用,如果我们要做一些实验和练习,需要创建一些临时文件,应该保存在哪里呢?
答案是用户的宿主目录或 /tmp/ 临时目录。但是要小心有些目录中不能直接修改和保存数据,比如 /proc/fn/sys/ 目录,因为它们是保存在内存中的,如果在这里写入数据,那么你的内存会越来越小,直至死机;/boot/ 目录也不能保存额外数据,因为 /boot/ 目录会单独分区作为启动分区,如果没有空闲空间,则会导致系统不能正常启动。
总之,Linux 要在合理的目录下进行操作和修改。
1、从命令功能来看:
/sbin 下的命令属于基本的系统命令,如shutdown、reboot,用于启动系统,修复系统,/bin下存放一些普通的基本命令,如ls、chmod等,这些命令在Linux系统里的配置文件脚本里经常用到。
2、从用户权限的角度看:
/sbin目录下的命令通常只有管理员才可以运行,/bin下的命令管理员和一般的用户都可以使用。
3、从可运行时间角度看:
/sbin、/bin能够在挂载其他文件系统前就可以使用。
4、而/usr/bin、/usr/sbin与/sbin/bin目录的区别在于:
/bin、/sbin目录是在系统启动后挂载到根文件系统中的,所以/sbin、/bin目录必须和根文件系统在同一分区;
/usr/bin、usr/sbin可以和根文件系统不在一个分区;
/usr/sbin存放的一些非必须的系统命令;
/usr/bin存放一些用户命令;
转下一位网友的解读,个人认为诠释得很到位:
/bin是系统的一些指令。bin为binary的简写主要放置一些系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。
/sbin一般是指超级用户指令。主要放置一些系统管理的必备程式例如:cfdisk、dhcpcd、dump、e2fsck、fdisk、halt、ifconfig、ifup、 ifdown、init、insmod、lilo、lsmod、mke2fs、modprobe、quotacheck、reboot、rmmod、 runlevel、shutdown等。
/usr/bin 是你在后期安装的一些软件的运行脚本。主要放置一些应用软体工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 gzip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。
/usr/sbin 放置一些用户安装的系统管理的必备程式例如:dhcpd、httpd、imap、in.*d、inetd、lpd、named、netconfig、nmbd、samba、sendmail、squid、swap、tcpd、tcpdump等。
如果新装的系统,运行一些很正常的诸如:shutdown,fdisk的命令时,悍然提示:bash:command not found。
那么首先就要考虑root 的PATH里是否已经包含了这些环境变量。可以查看PATH,如果是:PATH=PATH:HOME/bin 则需要添加成如下:
PATH=PATH:$HOME/bin:/sbin:/usr/bin:/usr/sbin
什么是“Linux函数库”?
运行在Linux上的软件时常会调用Linux内核的某些功能或其他软件的某些功能,那么这些被软件调用的功能称为Linux的函数库。软件自身的函数库存放在软件安装目录下的lib中,而Linux的函数库存放在/usr/lib和/usr/include中,linux内核的函数库存放在/lib/modules中。
Linux函数库的分类
Linux函数库分为静态函数库 和 动态函数库:
1. 静态函数库
- 扩展名:xxx.a
- 在编译时会被整合到软件的二进制文件中去。因此拥有静态函数库的软件较为庞大。而且当系统的函数库更新时,引用该函数库的所有软件都需要重新编译才能正常使用。这是非常麻烦的!但拥有静态函数库的软件可以独立运行。
2. 动态函数库
- 扩展名:xxx.so
- 在编译时仅仅将函数库的路径整合到软件的二进制文件中去。由于软件中包含的是函数库的路径,因此该软件无法独立运行,且函数库的路径不能发生变化,一旦变化,该软件将无法找到函数库,从而无法运行!这是动态函数库的最大缺点。但当动态函数库更新时,软件无需重新编译,因此更新较为方便,这是动态函数库的最大优点。
目前大部分软件均使用动态函数库,就是因为动态函数库在更新时体现出的优势。
提升函数库读取效率
软件在运行某些功能时需要调用函数库中的函数,而函数库又是以文件的形式存放在外设上。那么如果将函数库存放在内存中,那么将会大大提升读取速度。在Linux中,可以使用ldconfig命令将指定的函数库加载进内存。具体步骤如下:
1. 在/etc/ld.so.conf中设置需要加载进内存的函数库
2. 使用ldconfig命令使配置生效
ldd和ldconfig是动态链接的两个重要辅助工具,所谓“辅助”,是相对于真正的主角动态链接器ld.so,说它是工具,是只它相对于配置文件/etc/ld.so.conf文件。ldd不直接参与链接过程,它依赖于ld.so,但是ld.so不依赖于这个工具,事实上,ldd只是一个脚本,它在调用ld.so的时候传递了一些约定好的环境变量,从而使ld.so执行并打印一些内容出来。
而ldconfig则间接的供ld.so使用,它构造的ld.so.cache文件中包含了系统一些特定文件夹中的所有的so文件,它还会根据so文件内部DT_SONAME动态标签来建立一些符号链接,并且生成ld.so.cache文件,在动态链接器查找so文件的时候,动态链接器在某些情况下(按照一定的顺序)会读取并解析这个文件的内容,从而得到一些so文件的绝对位置,毕竟在很多时候,可执行文件的DT_NEEDED中指明的so只有文件名而没有绝对路径。
ldd用于打印程序或者库文件所依赖的共享库列表。我们常用来用来查看程序运行所需的共享库,用来解决程序因缺少某个库文件而不能运行的一些问题。
- --version:打印指令版本号;
- -v:详细信息模式,打印所有相关信息;
- -u:打印未使用的直接依赖;
- -d:执行重定位和报告任何丢失的对象;
- -r:执行数据对象和函数的重定位,并且报告任何丢失的对象和函数;
- --help:显示帮助信息。
使用ldd命令即可查看指定软件所使用的全部动态函数库,ldd后面跟可执行程序即可:
- [root@iZ231tx6fm4Z tomcat]# ldd /usr/bin/passwd
- linux-vdso.so.1 (0x00007fff3adff000)
- libuser.so.1 => /usr/lib64/libuser.so.1 (0x00007f6428bd5000)
- libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f642899d000)
- libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x00007f6428751000)
- libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x00007f642854e000)
- libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007f6428249000)
- libpopt.so.0 => /lib64/libpopt.so.0 (0x00007f6428040000)
- libpam_misc.so.0 => /lib64/libpam_misc.so.0 (0x00007f6427e3c000)
- libaudit.so.1 => /lib64/libaudit.so.1 (0x00007f6427c20000)
- libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f6427a01000)
- libc.so.6 => /lib64/libc.so.6 (0x00007f642765b000)
- libpam.so.0 => /lib64/libpam.so.0 (0x00007f642744d000)
- libgthread-2.0.so.0 => /lib64/libgthread-2.0.so.0 (0x00007f6427249000)
- librt.so.1 => /lib64/librt.so.1 (0x00007f642702e000)
- libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6426e11000)
- libdl.so.2 => /lib64/libdl.so.2 (0x00007f6426c0d000) /lib64/ld-linux-x86-64.so.2 (0x00007f6428dee000)
第一列:程序需要依赖什么库;
第二列: 系统提供的与程序需要的库所对应的库;
第三列:库加载的开始地址;
通过上面的信息,我们可以得到以下几个信息:
1.通过对比第一列和第二列,我们可以分析程序需要依赖的库和系统实际提供的,是否相匹配。
2.通过观察第三列,我们可以知道在当前的库中的符号在对应的进程的地址空间中的开始位置
如果依赖的某个库找不到,通过这个命令可以迅速定位问题所在。
拓展知识:
ldd不是一个可执行程序,而只是一个shell脚本。
如果使用 ldd 命令时没有找到对应的共享库文件和其具体位置,可能是两种情况引起的:
1、共享库没有安装在该系统中;
2、共享库保存在 /etc/ld.so.conf 文件列出的搜索路径之外的位置。
ldconfig概念:ldconfig是一个动态库管理命令, 为了让动态库为系统所共享, 须运行该命令
ldconfig通常在系统启动时运行, 而当用户安装了一个新的动态库时, 就需要手动运行该命令。
ldconfig用途:用途主要是在默认搜寻目录/lib和/usr/lib以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件。缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表,为了让动态链接库为系统所共享,需运行动态链接库的管理命令ldconfig,此执行程序存放在/sbin目录下。
语法:
- -v或--verbose:用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字。
- -n:用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib、/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录。
- -N:此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache),若未用-X选项,ldconfig照常更新文件的连接。
- -X:此选项指示ldconfig不更新文件的连接,若未用-N选项,则缓存文件正常更新。
- -f CONF:此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf。
- -C CACHE:此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表。
- -r ROOT:此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的)。选择此项时,系统默认的配置文件/etc/ld.so.conf,实际对应的为ROOT/etc/ld.so.conf。如用-r usr/zzz时,打开配置文件/etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件。用此选项,可以大大增加动态链接库管理的灵活性。
- -l:通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接,选择此项时,将进入专家模式,需要手工设置连接,一般用户不用此项。
- -p或--print-cache:此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字。
- -c FORMAT 或 --format=FORMAT:此选项用于指定缓存文件所使用的格式,共有三种:old(老格式),new(新格式)和compat(兼容格式,此为默认格式)。
- -V:此选项打印出ldconfig的版本信息,而后退出。
ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库,修改了ld.so.conf时,就需要手工运行这个命令。
linux下的共享库机制采用了类似于高速缓存的机制,将库信息保存在/etc/ld.so.cache里边。程序连接的时候首先从这个文件里边查找,然后再到ld.so.conf的路径里边去详细找。
ldconfig几个需要注意的地方:
1、往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig,不然这个library会找不到。
2、想往上面两个目录以外加东西的时候,一定要修改/etc/ld.so.conf,然后再调用ldconfig,不然也会找不到。
比如安装了一个mysql到/usr/local/mysql,mysql有一大堆library在/usr/local/mysql/lib下面,这时就需要在/etc/ld.so.conf下面加一行/usr/local/mysql/lib,保存过后ldconfig一下,新的library才能在程序运行时被找到。
3、如果想在这两个目录以外放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西)。那也可以,就是export一个全局变 量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library。一般来讲这只是一种临时的解决方案,在没有权限或临时需要的时 候使用。
4、ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
5、总之,就是不管做了什么关于library的变动后,最好都ldconfig一下,不然会出现一些意想不到的结果。不会花太多的时间,但是会省很多的事。
ldconfig提示“is not asymbolic link”的解决方法
在编译的时候会出现以下错误:
- ldconfig
- ldconfig: /lib/libdb-4.7.so is not a symbolic link
这是因为正常情况下libdb-4.7.so是一个符号连接,而不是一个实体文件,因此只需要把它改成符号连接即可:
- mv libdb-4.7.so libdb-4.so.7
- ln -s libdb-4.so.7 libdb-4.7.so
在x86下,为了查看程序所依赖的库,可以使用 ldd命令:
但如果是使用arm-linux-gcc 等交叉编译环境编译出来的程序,则要使用 readelf命令来查看了:
库用于将相似函数打包在一个单元中。然后这些单元就可为其他开发人员所共享,并因此有了模块化编程这种说法 — 即,从模块中构建程序。Linux 支持两种类型的库,每一种库都有各自的优缺点。静态库包含在编译时静态绑定到一个程序的函数。动态库则不同,它是在加载应用程序时被加载的,而且它与应用程序是在运行时绑定的。
下图展示了 Linux 中的库的层次结构:
使用共享库的方法有两种:您既可以在运行时动态链接库,也可以动态加载库并在程序控制之下使用它们。本文对这两种方法都做了探讨。
静态库较适宜于较小的应用程序,因为它们只需要最小限度的函数。而对于需要多个库的应用程序来说,则适合使用共享库,因为它们可以减少应用程序对内存(包括运行时中的磁盘占用和内存占用)的占用。这是因为多个应用程序可以同时使用一个共享库;因此,每次只需要在内存上复制一个库。要是静态库的话,每一个运行的程序都要有一份库的副本。
GNU/Linux 提供两种处理共享库的方法(每种方法都源于 Sun Solaris)。您可以动态地将程序和共享库链接并让 Linux 在执行时加载库(如果它已经在内存中了,则无需再加载)。另外一种方法是使用一个称为动态加载的过程,这样程序可以有选择地调用库中的函数。使用动态加载过程,程序可以先加载一个特定的库(已加载则不必),然后调用该库中的某一特定函数(下展示了静态链接与动态链接这两种方法)。这是构建支持插件的应用程序的一个普遍的方法。
Linux 提供了很多种查看和解析 ELF 对象(包括共享库)的工具。其中最有用的一个当属 ldd 命令,您可以使用它来发送共享库依赖项。例如,在 dl 应用程序上使用 ldd 命令会显示如下内容:
- mtj@camus:~/dl$ ldd dl
- linux-gate.so.1 => (0xffffe000)
- libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7fdb000)
- libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7eac000)
- /lib/ld-linux.so.2 (0xb7fe7000)
- mtj@camus:~/dl$
ldd 所告诉您的是:该 ELF 映像依赖于 linux-gate.so(一个特殊的共享对象,它处理系统调用,它在文件系统中无关联文件)、libdl.so(DL API)、GNU C 库(libc.so)以及 Linux 动态加载器(因为它里面有共享库依赖项)。
readelf 命令是一个有很多特性的实用程序,它让您能够解析和读取 ELF 对象。 readelf 有一个有趣的用途,就是用来识别对象内可再定位的项。对于我们这个简单的程序来说( 清单 2展示的程序),您可以看到需要再定位的符号为:
- mtj@camus:~/dl$ readelf -r dl
-
- Relocation section '.rel.dyn' at offset 0x520 contains 2 entries:
- Offset Info Type Sym.Value Sym. Name
- 08049a3c 00001806 R_386_GLOB_DAT 00000000 __gmon_start__
- 08049a78 00001405 R_386_COPY 08049a78 stdin
-
- Relocation section '.rel.plt' at offset 0x530 contains 8 entries:
- Offset Info Type Sym.Value Sym. Name
- 08049a4c 00000207 R_386_JUMP_SLOT 00000000 dlsym
- 08049a50 00000607 R_386_JUMP_SLOT 00000000 fgets
- 08049a54 00000b07 R_386_JUMP_SLOT 00000000 dlerror
- 08049a58 00000c07 R_386_JUMP_SLOT 00000000 __libc_start_main
- 08049a5c 00000e07 R_386_JUMP_SLOT 00000000 printf
- 08049a60 00001007 R_386_JUMP_SLOT 00000000 dlclose
- 08049a64 00001107 R_386_JUMP_SLOT 00000000 sscanf
- 08049a68 00001907 R_386_JUMP_SLOT 00000000 dlopen
- mtj@camus:~/dl$
从这个列表中,您可以看到各种各样的需要再定位(到 libc.so)的 C 库调用,包括对 DL API(libdl.so)的调用。函数 __libc_start_main 是一个 C 库函数,它优先于程序的 main 函数(一个提供必要初始化的 shell)而被调用。
其他操作对象文件的实用程序包括:objdump,它展示了关于对象文件的信息;nm,它列出来自对象文件(包括调试信息)的符号。还可以将 EFL 程序作为参数,直接调用 Linux 动态链接器,从而手动启动映像:
- mtj@camus:~/dl$ /lib/ld-linux.so.2 ./dl
- > libm.so expf 0.0
- 1.000000
另外,可以使用 ld-linux.so 的 --list 选项来罗列 ELF 映像的依赖项(ldd 命令也如此)。切记,它仅仅是一个用户空间程序,是由内核在需要时引导的。
替换系统中的库为以下两个:
- lib_4.6.3
- libQt4.8.5
查看系统已加载的库:
- vim /etc/ld.so.conf
- ldconfig
- ldconfig -v|grep libQt
假如程序需要使用的库分别为:libQtNetwork.so、libQtGui.so、libQtCore.so、libQtSql.so。
使用ldd helloWorld(路径在安装路径下)查看程序使用的qt库为指定目录下的qt库,不依赖系统中的qt库:
- cd /etc/ld.so.conf.d
-
- vim localusr.conf
- /usr/local/lib/ # 输入内容
-
- 完成后
- ldconfig
1、首先使用ldconfig -v|grep libQtCore.so.4查看系统qt版本,若是其中之一就不需要更换,只需更换另外一个就可以了。
2、更换库方法复制4.8.5或4.6.3版本库路径,编辑/etc/ld.so.conf文件,将该路径粘贴进去,保存退出,执行ldconfig;
3、执行ldconfig -v|grep libQtCore.so.4,若存在两个版本的qt,执行步骤4
4、执行find / -name libQtCore.so.4.8.5,找到系统库路径,删除掉4.8.5(旧版本)qt文件,删除之前拍快照
5、再次执行ldconfig -v|grep libQtCore.so.4,可看到只有一个版本的qt,且版本为新替换的版本,至此,系统版本库更换完成。
在Linux中,由于每个程序都是在后台执行的,如果直接按下电源开关关机时,则数据可能就此中断。
若不正常关机,可能会造成文件系统的毁损,所以关机时,我们要注意下面几件事:
(1) 查看系统的使用状态
目前有谁在线 who:
网络的联机状态:netstat -a
后台执行的程序:ps -aux:
(2) 通知在线用户关机的时刻:
eg:shutdown
(3) 正确的关机前先使用sync命令
将数据同步写入硬盘中的命令:
sync
重启,关机:shutdown、halt、reboot、poweroff
其实几个命令调用的函数库都差不多,读者可以尝试man一下,是相同的。
下面我们来演示一下这些命令:
当你的系统不正常关机时,由于数据尚未被写入硬盘当中,会造成数据的更新不正常。这时就需要sync这个这个命令,多执行几次总会比较放心。
可以自由选择关机模式:是要关机、重启或进入单用户操作模式;
可以设置关机时间:可以设置某一个特定的是时间关机;
可以自定义关机消息:在关机之前,将自己设置的消息传送给在线用户;
仅发出警告消息;
语法:
shutdown [-t seconds] [-rkhncfF] time [message]
关机标准命令:
Linux 将在一分钟内关闭。“-h”选项明确表示关闭或关闭系统。通常可以通过单独输入关闭命令来产生相同的结果。
shutdown
重启 Linux 的标准命令:
shutdown -r
Linux 将在一分钟内重新启动。“-r”选项代表重新启动或重新启动。
立即关闭 Linux 的命令:
Linux 将立即关闭。在这种情况下,关闭命令后跟“-h”选项和时间规范“0”,表示立即。
shutdown -h 0
或者下述命令也可以:
- shutdown now
- shutdown -h now
立即重启 Linux 的命令:
Linux 将立即重新启动。在这种情况下,关闭命令后跟“-r”选项和时间规范“0”,即立即。
shutdown -r 0
或者下述命令也可以:
shutdown -r now
延迟关机或重启:
- //20分钟后关机
- shutdown -h 20
-
- //效果相同
- shutdown +20
- //20分钟后重启
- shutdown -r 20
-
- //效果相同
- shutdown -r +20
定时关机或重启:
时间规范基于 Linux 中的 24 小时格式,符合语法 (hh:mm)。
- //下午 5:30(即 17:30)关机
- shutdown -h 17:30
-
- //效果相同
- shutdown 17:30
- //下午 5:30(即 17:30)重启
- shutdown -r 17:30
取消预定关闭或重启的命令:
此命令使用频次不高
shutdown -c
仅发出警告信件的参数,并不会关机:
shutdown -k now 'this system will reboot'
提示:ctrl+c 可以停止当前指令的运行。
切换执行等级 init:
系统运作的模式,分为命令行界面(run level 3)及图形界面模式(run level 5)。Linux有七种执行等级,其中有关机关机与重启。
run level 0:关机。
run level 6:重启。
所以我们可以用如下命令关机:
init 0