本文记录了 tmux 和 vim 的配置
Tmux
常用指令
功能 | 指令 |
---|---|
安装 | sudo apt install tmux |
新建会话 | tmux new -s workspace |
断开会话 | tmux detach 或 <ctrl+b> d |
重进会话 | tmux a -t workspace |
关闭会话 | tmux kill-session -t workspace |
关闭服务 | tmux kill-server 关闭tmux服务器 |
查看会话 | tmux ls 或 <ctrl+b> s |
美化
安装tmux(oh-my-tmux)项目
依赖项
-
tmux >= 2.1 (soon >= 2.4) running inside Linux, Mac, OpenBSD, Cygwin or WSL
-
curl, awk, perl and sed
-
outside of tmux,
$TERM
must be set to xterm-256color
安装命令
$ cd
$ git clone https://github.com/gpakosz/.tmux.git
$ ln -s -f .tmux/.tmux.conf
$ cp .tmux/.tmux.conf.local .
然后继续自定义 ~/.tmux.conf.local
副本
如果您是Vim用户,请将$EDITOR
环境变量设置为vim将启用并进一步自定义vi样式的键绑定(请参阅tmux手册)。
安装好后,使用Johnn4Func的配置
这里还可以安装一个天气的插件,~/.bashrc
或者 ~/.zshrc
中加入:
alias weather='curl zh.wttr.in/深圳'
tmux中的常用快捷键
前缀 | 指令 | 功能 |
---|---|---|
<ctrl+b> |
c | 新建窗口 |
<ctrl+b> |
e | 打开配置文件~/.tmux.conf.local |
<ctrl+b> |
m | 切换鼠标模式 |
<ctrl+b> |
q | 显示面板编号 |
<ctrl+b> |
r | 加载tmux配置文件 |
<ctrl+b> |
w | 打开窗口列表 |
<ctrl+b> |
x | 关闭面板 |
<ctrl+b> |
+ | 最大/小化面板 |
<ctrl+b> |
, | 命名窗口 |
<ctrl+b> |
. | 修改窗口编号 |
<ctrl+b> |
- | 上下分屏(面板) |
<ctrl+b> |
| | 左右分屏(面板) |
<ctrl+b> |
</ > |
向前/后置换面板 |
<ctrl+b> |
<ctrl+o> |
顺时针旋转当前窗口中的所有面板 |
<ctrl+b> |
h/j/k/l |
切换面板 |
<ctrl+b> |
<ctrl+h/j/k/l> |
前/下/上/后切换窗口 |
<ctrl+b> |
<ctrl+H/J/K/L> |
前/下/上/后调整面板 |
<ctrl+b> |
:join-pane -s win1 |
把win1窗口合并到当前窗口中 |
<ctrl+b> |
:join-pane -s win1.1 |
把win1窗口中的1号面板合并到当前窗口中 |
<ctrl+b> |
b | 显示粘贴板列表 |
<ctrl+b> |
p | 粘贴顶层粘贴板内容 |
<ctrl+b> |
P | 选择要粘贴的粘贴板内容 |
鼠标模式
-
开启用鼠标拖动调节pane的大小(拖动位置是pane之间的分隔线)
-
开启用鼠标点击pane来激活该pane
-
开启用鼠标点击来切换活动window(点击位置是状态栏的窗口名称)
-
开启
window/pane
里面的鼠标支持(也即可以用鼠标滚轮回滚显示窗口内容,此时还可以用鼠标选取文本)
复制模式
-
prefix + [
进入复制模式(ESC
或者<ctrl+c>
退出复制模式) -
按
v
开始移动光标选择复制区域 -
按
y
复制并退出copy-mode
-
将光标移动到指定位置,按
prefix + ]
粘贴
配置的托管
1. 在 github 上创建一个 config 项目
在Github 上新建个 config 项目,保存各种编辑器、shell、tmux的配置。在新环境中克隆下来,放到 ~/.local/config
下面。
2. 建立自己的配置脚本
写一个 bootstrap.sh
文件,到一个新环境下只需 curl 下来一执行如下命令:
sh -c "$(curl -fsSL https://.../bootstrap.sh)"
这个脚本将会建立必要的目录,克隆你的配置,再做一些必要的初始化
3. 使用 init.sh
新建一个:init.sh
用仓库托管起来,而本地 ~/.bashrc
末尾加一句话:
source ~/.local/xxx/init.sh
这个给文件末尾追加一句话的事情,可以让前面的 bootstrap.sh 来承担。
这样 init.sh 放置通用配置;临时配置,写在 ~/.bashrc
中,同时改写 ~/.bashrc 不会把 config 仓库弄脏;而更新 config 仓库也不会把本地配置覆盖没。
更重要的是,init.sh 可以写成同时兼容:sh, bash, zsh, dash 的模式,每个 shell 的配置里面只要 source 它一下就行了,那么 init.sh 里面即可写通用所有 shell 的一些初始化工作,又可以针对不同的 shell 写一些初始化配置。
对于实验性的新配置,写到本地配置里即可,等你用一段时间,觉得好用了,再把它挪到公共配置仓库里固化起来。这样随着时间的积累,你的 init.sh 积累的配置越来越多,shell 越来越顺手。
写 shell 脚本时,可以参考《《Bash 中文速查表》
安装 neovim
从 github 上下载最新的 Neovim.AppImage
curl -LO https://github.com/neovim/neovim/releases/download/stable/nvim.appimage
chmod u+x nvim.appimage
./nvim.appimage
也可以把 nvim.appimage
创建一个链接放到 /usr/local/bin
目录下
ln -s [nvim.appimage的绝对路径] /usr/local/bin`
下载 vim-init
git clone https://github.com/skywind3000/vim-init.git
VIM 实用插件整理
插件管理器 vim-plug
Vim
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
Neovim
sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
使用
" 指定一个安装插件的目录
call plug#begin('~/.vim/plugged')
Plug 'junegunn/vim-easy-align'
......
" 初始化插件系统
call plug#end()
命令
命令 | 说明 |
---|---|
PlugInstall [name …] [#threads] | 安装插件 |
PlugUpdate [name …] [#threads] | 安装或更新插件 |
PlugClean[!] | 删除未列出的插件(!版本将清除无提示) |
PlugUpgrade | 升级 vim-plug |
PlugStatus | 检查插件的状态 |
PlugDiff | 检查前一次更新的更改和未决的更改 |
PlugSnapshot[!] [output path] | 生成用于恢复插件的当前快照的脚本 |
选项
选项 | 说明 |
---|---|
branch/ tag/ commit |
要使用的存储库的分支/标记/提交 |
rtp | 包含Vim插件的子目录 |
dir | 自定义插件的目录 |
as | 为插件使用不同的名称 |
do | 更新后处理钩(字符串或funcref) Post-update hook (string or funcref) |
on | 按需加载:在执行命令或<Plug>-map 时 |
for | 按需装载:在指定的文件类型时 |
frozen | 不更新,除非显式指定 |
比如:
" On-demand loading
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" Using a non-master branch
Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
主题
推荐安装 base16-shell 和 base16-vim , space_vim_theme 以及 oceanic-next,后两个包含在 base-16 主题中
base16-shell
-
下载
git clone https://github.com/chriskempson/base16-shell.git ~/.config/base16-shell
-
在
~/.bashrc
或~/.zshrc
中加入# Base16 Shell BASE16_SHELL="$HOME/.config/base16-shell/" [ -n "$PS1" ] && \ [ -s "$BASE16_SHELL/profile_helper.sh" ] && \ eval "$("$BASE16_SHELL/profile_helper.sh")"
-
打开一个新的shell,输入base16,然后输入一个tab来执行补全
-
在
~/.vimrc
或~/.config/nvim/init.vim
中加入if filereadable(expand("~/.vimrc_background")) let base16colorspace=256 source ~/.vimrc_background endif
base16-vim
-
安装
Plug 'chriskempson/base16-vim'
-
拷贝主题
cp ~/.vim/bundles/base16-vim/colors/* ~/.config/nvim/colors
-
这样,在 shell 值切换主题后,vim 的主题也跟着切换
目录树(NERDTree)
安装
Plug 'preservim/nerdtree'
Plug 'ryanoasis/vim-devicons'
Plug 'Xuyuanp/nerdtree-git-plugin'
Plug 'tiagofumo/vim-nerdtree-syntax-highlight'
快捷键
快捷键 | 说明 |
---|---|
tt | 打开/关闭 nerdtree |
q | 关闭 nerdtree |
o | 打开选中的文件; 折叠/展开选中的目录 |
i | 打开选中的文件,与已打开文件纵向排布窗口,并跳转至该窗口 |
gi | 打开选中的文件,与已打开文件纵向排布窗口,但不跳转至该窗口 |
s | 打开选中的文件,与已打开文件横向排布窗口,并跳转至该窗口 |
gs | 打开选中的文件,与已打开文件横向排布窗口,但不跳转至该窗口 |
t | 在新 Tab 中打开选中文件/书签,并跳到新 Tab |
T | 在新 Tab 中打开选中文件/书签,但不跳到新 Tab |
x | 折叠选中结点的父目录 |
X | 递归折叠选中结点下的所有目录 |
k / j | 光标在 Neadtree 上下移动 |
<leader>tn | 创建一个新的标签页 |
<leader>tx | 关闭标签页 |
<leader>tf | 前一个标签页 |
<leader>tb | 后一个标签页 |
<leader>to | 关闭其他标签页 |
? | 显示帮助 |
模糊搜索 LeaderF
LeaderF 是一个高效的模糊查找器,可以帮助定位文件、缓冲区、mrus、gtags等。
安装
安装 vim 的插件以及模糊匹配算法的C扩展
Plug 'Yggdroot/LeaderF', { 'do': './install.sh' }
使用方法
usage: Leaderf[!] [-h] [--reverse] [--stayOpen] [--input <INPUT> | --cword]
[--top | --bottom | --left | --right | --belowright | --aboveleft |
--fullScreen | --popup]
[--nameOnly | --fullPath | --fuzzy | --regexMode] [--nowrap] [--next |
--previous]
[--recall] [--popup-height <POPUP_HEIGHT>] [--popup-width <POPUP_WIDTH>]
{file,tag,function,mru,searchHistory,cmdHistory,help,line,colorscheme,gtags,self,bufTag,
buffer,rg,filetype,command,window,quickfix,loclist}
...
如果给出[!],则直接进入正常模式
选项 | 说明 |
---|---|
-h, –help | 显示此帮助信息并退出 |
–reverse | 按自下而上的顺序显示结果 |
–stayOpen | 不要在接受一个条目后退出LeaderF |
–input <INPUT> | 指定INPUT为预先输入的模式 |
–cword | 预先输入当前光标下的字词 |
–top | LeaderF 窗口在屏幕的顶部 |
–bottom | LeaderF 窗口在屏幕的底部 |
–left | LeaderF 窗口在屏幕的左边 |
–right | LeaderF窗口在屏幕的右边 |
–belowright | LeaderF 窗口在屏幕右下角 |
–aboveleft | LeaderF窗口在屏幕的左上角 |
–fullScreen | LeaderF窗口占据了整个屏幕 |
–popup | LeaderF窗口是一个弹出窗口或浮动窗口 |
–nameOnly | LeaderF默认处于NameOnly模式下 |
–fullPath | LeaderF默认为FullPath模式 |
–fuzzy | LeaderF默认为Fuzzy模式 |
–regexMode | LeaderF默认处于Regex模式下 |
–nowrap | LeaderF 窗口中的长线不会被包住 |
–next | 跳转到下一个结果 |
–previous | 跳转到上一个结果 |
–recall | 回忆上一次搜索。如果结果窗口关闭,则重新打开 |
–popup-height |
指定弹出窗口的最大高度,仅在弹出模式下有效 |
–popup-width |
指定弹出窗口的宽度,仅在弹出模式下可用 |
子命令
子命令 | 说明 |
---|---|
file | 检索文件 |
tag | 使用标签文件浏览标签 |
function | 在缓冲区中浏览函数或方法 |
mru | 搜索最近使用的文件 |
searchHistory | 在历史中执行搜索命令 |
cmdHistory | 在历史中执行命令 |
help | 浏览帮助标签 |
line | 检索行 |
colorscheme | 换色 |
gtags | 使用gtags导航标签 |
self | 执行自己的命令 |
bufTag | 缓冲区中的标签导航 |
buffer | 搜索缓冲区 |
rg | 使用 grep |
filetype | 浏览文件类型 |
command | 执行内置/用户定义的Ex命令 |
window | 搜索窗口 |
quickfix | 导航快速修复 |
loclist | 导航位置列表 |
一旦启动了 LeaderF:
快捷键 | 功能 |
---|---|
<C-C> </br><ESC> |
退出LeaderF |
<C-R> |
切换模糊搜索模式和regex模式。 |
<C-F> |
切换全路径搜索模式和名称搜索模式 |
<Tab> |
转入正常模式 |
<C-V> </br><S-Insert> |
剪贴板粘贴 |
<C-U> |
撇清关系 |
<C-W> |
删去提示中光标前的字样。 |
<C-J> |
在结果窗口中向下移动光标。 |
<C-K> |
在结果窗口中向上移动光标。 |
<Up> /<Down> |
回顾历史上最后一个/下一个输入模式 |
<2-LeftMouse> </br><CR> |
勾选光标下的文件或选中的文件(当选中多个文件时) |
<C-X> |
横开 |
<C-]> |
竖开 |
<C-T> |
新页 |
<F5> |
刷新缓存 |
<C-LeftMouse> </br><C-S> |
选择多个文件 |
<S-LeftMouse> |
连续选择多个文件 |
<C-A> |
选择所有文件 |
<C-L> |
清除所有选择 |
<BS> |
在提示语中输入前面的字符 |
<Del> |
删除当前提示符 |
<Home> |
将光标移到提示开始处。 |
<End> |
将光标移到提示语的末尾部分 |
<Left> |
在提示符中向左移动一个字 |
<Right> |
将光标向右移动一个字符的提示音 |
<C-P> |
预览结果 |
<C-Up> |
在弹出的预览窗口中向上滚动 |
<C-Down> |
在弹出的预览窗口中向下滚动 |
输入格式
- 在NameOnly模式下(模糊模式)
- 如果你输入的第一个字符是’;’,那么搜索将与FullPath模式相同。
- 如果您输入的字符串是’abc;def’,那么’abc’将匹配文件名,’def’将匹配目录名。
- 在FullPath模式(模糊模式)下
- 除了模式将匹配完整的路径,而不是只匹配文件名之外,与NameOnly模式相同。
- 在Regexp模式下
- 输入的字符串与Vim的regexp相同。
Leaderf gtags
Gtags也就是GNU GLOBAL,是一个非常强大的源码符号索引工具。它通过建立索引数据库,不但可以查找函数的定义,还可以查找函数的所有引用(被调用的地方);而且它还可以增量地更新索引数据库,当代码有所改变时,它可以在很短的时间内更新索引数据库,保持索引数据库和代码同步。
LeaderF 可以自己管理 gtags 数据库(GTAGS,GRTAGS,GPATH),它不会在你的项目目录下生成任何额外的文件或目录。gtags 数据库文件存储在$HOME/.LfCache/gtags/%PATH%OF%YOUR%PROJECT/
下面, %PATH%OF%YOUR%PROJECT
是把你项目路径中的 \
或 /
替换成 %
。
只要设置let g:Lf_GtagsAutoGenerate = 1
, LeaderF 就会在打开第一个文件时自动生成 gtags 数据库。当代码有更改并且已经有 gtags 数据库生成时,更改的代码会自动同步到 gtags 数据库(即使g:Lf_GtagsAutoGenerate
是0)。
只有在项目根目录下有g:Lf_RootMarkers
(默认值是['.git', '.hg', '.svn']
)里面指定的文件或目录时,LeaderF 才会自动生成 gtags 数据库;否则只能手动生成 gtags 数据库:Leaderf gtags --update
,但是当代码有更改时,gtags 数据库依然可以自动更新。
LeaderF 快捷键
快捷键 | 功能 |
---|---|
<leader>fr |
搜索项目中光标下tag的引用 |
<leader>fd |
搜索项目中光标下tag的定义 |
<leader>fo |
再执行上一次的搜索 |
<leader>fh |
跳转到下一个搜索处 |
<leader>fl |
跳转到上一个搜索处 |
<leader>fb / <alt-n> |
打开 buffer 列表进行模糊匹配 |
<leader>ft |
在当前buf中搜索tag |
<leader>fl |
搜索某一行 |
<leader>ff |
打开最近使用的文件 |
<alt-p> |
打开函数列表,按 i 进入模糊匹配,esc 退出 |
<alt-P> |
打开 tag 列表,按 i 进入模糊匹配,esc 退出 |
<alt-m> |
全局 tags 模糊匹配 |
<leader>rw |
以regex方式搜索光标下词条 |
<leader>ra |
将结果附加到之前的搜索结果中 |
<leader>rb |
只在当前缓冲区中搜索光标下的字 |
<leader>rc |
在所有列出的缓冲区中按字面意思搜索光标下的文字 |
<leader>rh |
回顾上一次搜索 |
<leader>rs |
在*.h 和*.cpp 文件中搜索光标下的单词 |
<leader>re |
在cpp文件中搜索光标下的单词,排除*.hpp文件 |
gf |
在visual模式下选择的文本中搜索,不要在接受一个条目后退出LeaderF |
Leaderf gtags 使用介绍
参数 | 说明 |
---|---|
–update | 如果标签文件不存在,则创建标签文件,否则更新标签文件。 |
–remove | 删除生成的标签文件。 |
–accept-dotfiles | 接受名称以点开头的文件和目录。 默认情况下,gtags 会忽略这些文件和目录。 |
–skip-unreadable | 跳过不可读的文件。 |
–gtagsconf <FILE> | 设置环境变量GTAGSCONF为<FILE>。 |
–gtagslabel <LABEL> | 将环境变量GTAGSLABEL设置为<LABEL>。 |
–skip-symlink [<TYPE>] | 跳过符号链接。如果类型为’f’,则只跳过文件的符号链接, 如果为’d’,则只跳过目录的符号链接。 类型的默认值是’a’(所有符号链接)。 |
–gtagslibpath <PATH> [<PATH> …] | 指定搜索库函数的路径。 |
-d <PATTERN>, –definition <PATTERN> | 显示定义的位置。 |
-r <PATTERN>, –reference <PATTERN> | 显示对有定义的符号的引用。 |
-s <PATTERN>, –symbol <PATTERN> | 显示对没有定义的符号的引用。 |
-g <PATTERN>, –grep <PATTERN> | 显示所有符合<PATTERN>的行 |
–by-context | 根据光标位置的上下文决定标签类型。 如果上下文是模式的定义,则使用-r, 否则如果至少有一个模式的定义,则使用-d, 否则使用-s。模式不允许使用正则表达式。 |
-i, –ignore-case | 忽略模式中的大小写区分。 |
–literal | 执行文字搜索而不是正则表达式搜索。 |
–path-style <FORMAT> | 使用<FORMAT>显示路径名,可以是以下之一。”relative”、”absolute”、”shorter”、”abslib “或 “through”。relative 表示相对路径。absolute 表示绝对路径。shorter 表示相对路径和绝对路径中较短的一个。abslib 是指库的绝对路径(GTAGSLIBPATH)和其他库的相对路径。through 是指从项目根目录开始的相对路径(GPATH的内部格式)。默认为 “relative”。 |
-S <DIR>, –scope <DIR> | 只显示<DIR>目录下存在的标签。 |
–recall | 回忆上次搜索的内容。如果结果窗口关闭,则重新打开。 |
–match-path | 模糊搜索时匹配文件路径。 |
–append | 追加到之前的搜索结果中。 |
–current-buffer | 显示当前缓冲区的标签。 |
–all-buffers | 显示所有缓冲区中的标签。 |
–all | 显示整个项目中的标签。 |
–result <FORMAT> | 使用格式化的方式显示结果,格式化的方式可以是。ctags (默认)、ctags-x 、ctags-mod 中的一种。 |
–auto-jump [<TYPE>] | 当只有一个匹配时,直接跳转到标签。<TYPE>可以是’h’、’v’或’t’, 分别表示跳转到一个水平、垂直分割的窗口或一个新的标签页。 如果省略<TYPE>,则跳转到一个位置。 |
注意:如果:Leaderf
后面有感叹号,会直接进入normal模式;如果没有感叹号,则是输入模式,此时可以输入字符来进行模糊匹配过滤。可以用tab键在两个模式间来回切换。
手动生成gtags数据库
Leaderf[!] gtags --update
[--gtagsconf <FILE>] [--gtagslabel <LABEL>] [--accept-dotfiles]
[--skip-unreadable] [--skip-symlink [<TYPE>]]
[--gtagslibpath <PATH> [<PATH> ...]]
--gtagsconf <FILE>
用来指定 gtags.conf 文件的路径,一般情况下不需要指定,默认值就可以很好地工作。对于Windows上,如果相对于gtags.exe
所在路径有../share/gtags/gtags.conf
,也不需要指定该选项。如果需要用户自己特有的针对 gtags 的配置,可以指定用户的配置文件。 也可以在vimrc
里设置g:Lf_Gtagsconf
达到同样的目的。--gtagslabel <LABEL>
用来指定gtagslabel,如果不指定,默认值是'default'
- 推荐native-pygments 对于原生支持的6种语言使用内置parser,其他语言使用pygments作为parser。
- 也可以在
vimrc
里设置g:Lf_Gtagslabel
达到同样的目的。
- –gtagslibpath
[ ...] 用来指定项目所用 library 的 Paths,这样就可以生成 library 的索引,查找定义或引用时可以跳转 到 library 代码中去。后面指定的路径还可以是一个或多个其他项目路径,跳转时可以跳到其他项目中的文件
查找tags
Leaderf[!] gtags [--current-buffer | --all-buffers | --all] [--result <FORMAT>] [COMMON_OPTIONS]
列出当前buffer、所有打开的buffer或者整个项目的tags
-
Leaderf[!] gtags
等同于Leaderf[!] gtags --all
,列出整个项目的tags。 -
--result <FORMAT>
指定显示格式,可以是ctags
(default),ctags-x
或者ctags-mod
查找定义、引用
Leaderf[!] gtags
-d <PATTERN> [--auto-jump [<TYPE>]]
[-i] [--literal] [--path-style <FORMAT>]
[-S <DIR>][--append] [--match-path]
[--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags
-r <PATTERN> [--auto-jump [<TYPE>]]
[-i] [--literal] [--path-style <FORMAT>]
[-S <DIR>][--append] [--match-path]
[--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
Leaderf[!] gtags --by-context [--auto-jump [<TYPE>]]
[-i] [--literal] [--path-style <FORMAT>]
[-S <DIR>][--append] [--match-path]
[--gtagsconf <FILE>] [--gtagslabel <LABEL>] [COMMON_OPTIONS]
<PATTERN>
可以是正则表达式。--auto-jump [<TYPE>]
意思是如果只有一个结果直接跳过去。--by-context
意思是:光标下如果是定义,就跳到引用处,如果是引用,就跳到定义处。
CoC
快捷键 | 功能 |
---|---|
:CocDiagnostics |
获取获取当前位置列表中所有缓冲区的诊断信息 |
[g |
前一个诊断信息 |
]g |
后一个诊断信息 |
gd | 跳转到函数定义 |
gr | 返回引用处 |
gi | 跳转到实现(implementation) |
gy | 类型定义 |
K | 显示光标下符号的帮助文档 |
<leader>rn |
符号重命名 |
<leader>f |
格式化通过visual模式选择的代码 |
<leader>qf |
对当前行的问题应用自动修复 |
<c-l> |
代码展开 |
<c-e> |
翻译光标下单词(命令行) |
<leader>i |
翻译光标下单词(弹窗) |
其他快捷键
快捷键 | 功能 | 插件 |
---|---|---|
<leader>gg |
显示tagbar | tagbar |
<c-p> |
markdown 预览 | markdown-preview |
<leader>tm |
打开markdown表格美化 | vim-table |
gh |
命令行显示函数声明 | vim-preview |
gl | 在右侧栏预览函数体 | - |
gz | 关闭右侧预览窗口 | - |
<alt-u> |
预览窗口向上滚动 | - |
<alt-d> |
预览窗口向下滚动 | - |
s{charA}{charB} |
光标跳转到当前窗口的{charA}{charB} 处 |
easymotion |
<leader><leader>w |
激活easymotion模式 | - |
<alt-=> |
alt_+/- 用于按分隔符扩大缩小 v 选区 | - |
F4 | 执行cmake . |
AsyncRun |
F5 | 运行文件 call ExecuteFile() |
- |
F6 | 测试文件make test |
- |
F7 | 编译文件 make |
- |
F8 | 运行项目 make run |
- |
F9 | 编译 C/C++ gcc -o |
- |
<leader>s |
打开Startify窗口 | Startify |
g; | 跳转到上一次修改处 | |
g, | 跳转到下一次修改处 | |
<c-w>[ 、 <c-w>] |
调整窗口大小 |
ld.so, ld-linux.so* - 动态链接器和加载器
动态链接器可以通过运行一些动态链接的程序或共享对象间接运行(在这种情况下,不能传递动态链接器的命令行选项,在ELF情况下,存储在程序的.interp部分的动态链接器会被执行),或者直接运行:
/lib/ld-linux.so.* [OPTIONS] [PROGRAM [ARGUMENTS]]
说明
ld.so
和ld-linux.so*
程序找到并加载程序所需的共享对象(共享库),为程序的运行做准备,然后运行。
Linux 二进制文件需要动态链接 (运行时的链接), 除非在编译过程中给 ld 添加了 -static 选项。
ld.so 程序处理 a.out 二进制文件,这是很久以前使用的格式;ld-linux.so*
处理 ELF(/lib/ld-linux.so.1
用于 libc5
,/lib/ld-linux.so.2
用于 glibc2
),现在大家已经使用了很多年。 除此之外,两者都有相同的行为,并使用相同的支持文件和程序ldd(1)、ldconfig(8)和/etc/ld.so.conf。
在解析共享对象依赖关系时,动态链接器首先检查每个依赖关系字符串是否包含斜线(如果在链接时指定了包含斜线的共享对象路径名,则会出现这种情况)。 如果发现斜线,那么依赖字符串就会被解释为(相对或绝对)路径名,并使用该路径名加载共享对象。
如果一个共享对象的依赖关系不包含斜线,那么就会按照以下顺序进行搜索:
- (仅 ELF) 如果二进制文件的
DT_RPATH
动态部分属性存在且DT_RUNPATH
属性不存在,则使用该属性指定的目录。DT_RPATH
的使用已被废弃。 - 使用环境变量
LD_LIBRARY_PATH
(除非可执行文件是在安全执行模式下运行的),在这种情况下,它会被忽略 - (仅 ELF) 使用二进制文件
DT_RUNPATH
动态部分属性中指定的目录(如果存在)。 - 来自缓存文件
/etc/ld.so.cache
,它包含了之前在增强库路径中找到的候选共享对象的编译列表。 然而,如果二进制文件是用-z nodeflib
链接器选项链接的,那么默认路径中的共享对象将被跳过。 安装在硬件能力目录中的共享对象(见下文)比其他共享对象更优先。 - 在默认路径中
/lib
,然后是/usr/lib
。 (在某些64位架构上,64位共享对象的默认路径是/lib64
,然后是/usr/lib64
。) 如果二进制文件是用-z nodeflib
链接器选项链接的,则跳过这一步。
选项
选项 | 说明 |
---|---|
–list | 列出所有的依赖关系,以及它们是如何解析(resolved)的 |
–verify | 确认程序是动态链接的,而且这个动态链接器可以处理 |
–inhibit-cache | 不要使用/etc/ld.so.cache |
–library-path <路径>路径> | 使用<路径>代替`LD_LIBRARY_PATH`环境变量设置(见下文)路径> |
–inhibit-rpath <列表>列表> | 忽略<列表>指定的对象中的RPATH和RUNPATH信息。 在安全执行模式下运行时,这个选项会被忽略(见下文)列表> |
–audit <列表>列表> | 使用列表中命名的对象作为审核员 |
环境
各种环境变量影响着动态链接器的运行
安全执行模式
为了安全起见,如果动态链接器确定二进制文件应该在安全执行模式下运行,那么一些环境变量的效果就会失效或被修改。 这个决定是通过检查辅助向量中的AT_SECURE条目(见getauxval(3))是否有一个非零值来实现的。 这个条目可能因为各种原因而具有非零值,包括:
- 进程的实际和有效值。
- 进程的真实和有效用户ID不同,或者真实和有效组ID不同。 这通常是执行set-user-ID或set-group-ID程序的结果
- 一个非root用户ID的进程执行了一个赋予允许或有效能力的二进制程序。
- Linux安全模块可能设置了一个非零值
比较重要的环境变量
环境变量 | 说明 |
---|---|
LD_ASSUME_KERNEL | 每个共享对象都可以告知动态链接器它所需要的最小内核ABI版本。 (这个要求被编码在ELF注解部分,可以通过readelf -n 查看标有NT_GNU_ABI_TAG 的部分。) 在运行时,动态链接器确定运行中的内核的ABI版本,并将拒绝加载指定了超过该ABI版本的最小ABI版本的共享对象。LD_ASSUME_KERNEL 可以用来使动态链接器假定它是在一个具有不同的内核ABI版本的系统上运行。 例如,下面的命令行使动态链接器在加载myprog所需的共享对象时,假定它运行在Linux 2.2.5上。$ LD_ASSUME_KERNEL=2.2.5 ./myprog 在提供共享对象的多个版本(在搜索路径的不同目录中)的系统上,这些共享对象有不同的最低内核ABI版本要求, LD_ASSUME_KERNEL 可以用来选择使用的对象版本(取决于目录搜索顺序)。 从历史上看,LD_ASSUME_KERNEL 功能最常见的用法是在同时提供LinuxThreads和NPTL的系统上手动选择旧的LinuxThreads POSIX线程实现(后者通常是这类系统的默认版本);参见pthreads(7)。 |
LD_LIBRARY_PATH | 在执行时搜索ELF库的目录列表。 列表中的项目由冒号或分号分隔。 类似于PATH环境变量。 在安全执行模式下,这个变量被忽略 |
LD_PRELOAD | 在所有其他对象之前加载的额外的、用户指定的ELF共享对象列表。 列表中的项目可以用空格或冒号分隔。 这可以用来选择性地覆盖其他共享对象的功能。 使用在DESCRIPTION下给出的规则搜索对象。 在安全执行模式下,包含斜线的预加载路径名会被忽略,只有当共享对象文件上的set-user-ID模式位被启用时,才会加载标准搜索目录中的共享对象。 |
LD_TRACE_LOADED_OBJECTS | (仅 ELF) 如果设置 (为任何值),将导致程序列出其动态依赖关系,就像通过 ldd(1) 运行一样,而不是正常运行。 |
Rpath标签扩展
ld.so可以理解rpath规范中的某些字符串(DT_RPATH
或DT_RUNPATH
);这些字符串被替换为以下内容:
-
$ORIGIN
(或等价的${ORIGIN}
)这将扩展到包含程序或共享对象的目录。 因此,一个位于
somedir/app
的应用程序可以用以下方式编译gcc -Wl,-rpath,'$ORIGIN/../lib'
这样它能在
somedir/lib
中找到相关的共享对象,无论somedir在目录层次中的位置如何。 这有利于创建 “交钥匙 “应用程序(turn-key applications),这些应用程序不需要安装到特殊的目录中,而是可以解压到任何目录中,并且仍然可以找到自己的共享对象。 -
$LIB
(或者${LIB}
)根据不同的架构,它可以扩展为lib或lib64(例如,在x86-64上,它扩展为lib64,在x86-32上,它扩展为lib)。
-
$PLATFORM
(或者${PLATFORM}
)这将扩展为对应于主机系统处理器类型的字符串(例如,”x86_64”)。 在某些架构上,Linux内核并没有向动态链接器提供平台字符串。 这个字符串的值取自辅助向量中的
AT_PLATFORM
值(见getauxval(3))。
文件
-
/lib/ld.so
a.out
的动态链接器/加载器 -
/lib/ld-linux.so.{1, 2}
ELF 的动态链接器/加载器
-
/etc/ld.so.cache
文件中包含一个用于搜索共享对象的目录汇编列表,以及候选共享对象的有序列表。
-
/etc/ld.so.preload
包含一个以空格分隔的ELF共享对象列表的文件,要在程序之前加载。
-
lib*.so*
共享对象
注意
ld.so功能适用于使用libc 4.4.3或更高版本编译的可执行文件。 ELF功能从Linux 1.1.52和libc5开始提供。
libc、glibc和glib的关系
glibc 和 libc
glibc 和 libc 都是 Linux 下的 C 函数库。
libc 是 Linux 下的 ANSI C 函数库;glibc 是 Linux 下的 GUN C 函数库。
ANSI C 和 GNU C 的区别
ANSI C 函数库是基本的 C 语言函数库,包含了 C 语言最基本的库函数。这些库函数在其各种支持 C 语言的 IDE 中都是有的。
GNU C 函数库是一种类似于第三方插件的东西。由于 Linux 是用 C 语言写的,所以 Linux 的一些操作是用 C 语言实现的。因此,GUN 组织开发了一个 C 语言的库,以便让我们更好的利用 C 语言开发基于 Linux 操作系统的程序。不过现在的不同的 Linux 的发行版本对这两个函数库有不同的处理方法,有的可能已经集成在同一个库里了。
glibc是linux下面c标准库的实现,即GNU C Library。glibc本身是GNU旗下的C标准库,后来逐渐成为了Linux的标准c库,而Linux下原来的标准c库Linux libc逐渐不再被维护。Linux下面的标准c库不仅有这一个,如uclibc、klibc,以及上面被提到的Linux libc,但是glibc无疑是用得最多的。glibc在/lib目录下的.so文件为libc.so.6。
查看当前系统的 glibc 版本的两种方法:
-
/lib/libc.so.6
# /lib32/libc.so.6 GNU C Library (Ubuntu GLIBC 2.23-0ubuntu11) stable release version 2.23, by Roland McGrath et al. Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 5.4.0 20160609. Available extensions: crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B libc ABIs: UNIQUE IFUNC For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
-
ldd
# ldd --version ldd (Ubuntu GLIBC 2.23-0ubuntu11) 2.23 Copyright (C) 2016 自由软件基金会。 这是一个自由软件;请见源代码的授权条款。本软件不含任何没有担保;甚至不保证适销性 或者适合某些特殊目的。 由 Roland McGrath 和 Ulrich Drepper 编写。
glibc 和 glib
glib 和 glibc 基本上没有太大联系,可能唯一的共同点就是,其都是 C 编程需要调用的库而已。
glib 是 Gtk+ 库和 Gnome 的基础。glib 可以在多个平台下使用,比如 Linux、Unix、Windows 等。glib 为许多标准的、常用的 C 语言结构提供了相应的替代物。
glib是GTK+的基础库,它由基础类型、对核心应用的支持、实用功能、数据类型和对象系统五个部分组成,可以在gtk网站下载其源代码。是一个综合用途的实用的轻量级的C程序库,它提供C语言的常用的数据结构的定义、相关的处理函数,有趣而实用的宏,可移植的封装和一些运行时机能,如事件循环、线程、动态调用、对象系统等的API。GTK+是可移植的,当然glib也是可移植的,你可以在linux下,也可以在windows下使用它。使用gLib2.0(glib的2.0版本)编写的应用程序,在编译时应该在编译命令中加入pkg-config --cflags --libs glib-2.0
,如:
gcc `pkg-config --cflags --libs glib-2.0` hello.c -o hello
使用glib最有名的就是GNOME了。
总结
libc, glibc在一个层次,都是C的标准实现库,是操作系统级别的基石之一。
glib是用C写的一些utilities,即C的工具库,和libc/glibc没有关系。