目錄
1?vim
1.1 vim簡單介紹
1.2 vim的三種模式
1.3 vim基本操作
1.3.1命令模式下的操作
1.3.2 切換到文本輸入模式
1.3.3 末行模式下的操作
2 gcc編譯器
2.1 gcc的工作流程
2.2 gcc常用參數(shù)
3 靜態(tài)庫和共享(動態(tài))庫
3.1庫的介紹 ??
3.2靜態(tài)庫(static library)
3.3共享庫(shared library)/動態(tài)庫
學(xué)習(xí)目標(biāo)
掌握vim命令模式下相關(guān)命令的使用
掌握從命令模式切換到編輯模式的相關(guān)命令
掌握vim末行模式下相關(guān)命令的使用
能夠說出gcc的工作流程和掌握常見參數(shù)的使用
熟練掌握Linux下的靜態(tài)庫的制作和使用
熟練掌握Linux下的共享庫的制作和使用
1?vim
1.1 vim簡單介紹
vi是”visual interface”的簡稱, 它在Linux上的地位就仿佛Windows中的記事本一樣. 它可以執(zhí)行編輯、刪除、查找、替換、塊操作等眾多文本操作,?而且用戶可以根據(jù)自己的需要對其進(jìn)行定制. vi是一個文本編輯程序, 沒有菜單,?只有命令.
vim更高級一些, 可以理解是vi的高級版本.
vim需要自行安裝, 在shell中輸入vimtutor命令可以查看相關(guān)的幫助文檔.
1.2 vim的三種模式
Vi有三種基本工作模式: 命令模式、文本輸入模式、末行模式。
三種工作模式的切換如圖所示, 從下圖中可以看出編輯模式和末行模式之間不能相互切換, 必須經(jīng)過命令模式.
1.3 vim基本操作
1.3.1命令模式下的操作
用戶按下esc鍵, 就可以使vi進(jìn)入命令模式下; 當(dāng)使用vi打開一個新文件開始也是進(jìn)入命令模式下.
保存退出
快捷鍵 |
操作 |
ZZ |
保存退出 |
代碼格式化
快捷鍵 |
操作 |
gg=G |
代碼的格式化 |
光標(biāo)移動
快捷鍵 |
操作 |
h |
光標(biāo)左移 |
j |
光標(biāo)下移 |
k |
光標(biāo)上移 |
l |
光標(biāo)右移 |
w |
移動一個單詞 |
gg |
光標(biāo)移動到文件開頭 |
G |
光標(biāo)移動到文件末尾 |
0 |
光標(biāo)移到到行首 |
$ |
光標(biāo)移到到行尾 |
nG |
行跳轉(zhuǎn), 例12G, 跳到12行處 |
刪除命令
快捷鍵 |
操作 |
x |
刪除光標(biāo)后一個字符,相當(dāng)于 Del |
X |
刪除光標(biāo)前一個字符,相當(dāng)于 Backspace |
dw |
刪除光標(biāo)開始位置的字,包含光標(biāo)所在字符 |
d0 |
刪除光標(biāo)前本行所有內(nèi)容,不包含光標(biāo)所在字符 |
D[d$] |
刪除光標(biāo)后本行所有內(nèi)容,包含光標(biāo)所在字符 |
dd |
刪除光標(biāo)所在行(本質(zhì)其實(shí)是剪切) |
ndd |
從光標(biāo)當(dāng)前行向下刪除指定的行數(shù), 如15dd |
v/ctrl+v |
使用h、j、k、l移動選擇內(nèi)容, 然后按d刪除其中ctrl+v是列模式, v為非列模式 |
撤銷和反撤銷命令
快捷鍵 |
操作 |
u |
一步一步撤銷, 相當(dāng)于word文檔的ctrl+z |
ctrl-r |
反撤銷, 相當(dāng)于word文檔的ctrl+y |
復(fù)制粘貼
快捷鍵 |
操作 |
yy |
復(fù)制當(dāng)前行 |
nyy |
復(fù)制n行, 如10yy |
p |
在光標(biāo)所在位置向下新開辟一行,?粘貼 |
P |
在光標(biāo)所在位置向上新開辟一行,?粘貼 |
剪切 操作 |
按dd或者ndd刪除, 將刪除的行保存到剪貼板中, 然后按p/P就可以粘貼了 |
可視模式
快捷鍵 |
操作 |
v/ctrl+v |
使用h、j、k、l移動選擇內(nèi)容; 使用d刪除 使用y復(fù)制? 使用p粘貼到光標(biāo)的后面 使用P粘貼到光標(biāo)的前面 |
替換操作
快捷鍵 |
操作 |
r |
替換當(dāng)前字符 |
R |
替換當(dāng)前行光標(biāo)后的字符 |
查找命令
快捷鍵 |
操作 |
/ |
/xxxx, 從光標(biāo)所在的位置開始搜索, 按n向下搜索, 按N向上搜索 |
? |
?xxxx, 從光標(biāo)所在的位置開始搜索, 按n向上搜索, 按N向下搜索 |
# |
將光標(biāo)移動到待搜索的字符串上, 然后按n向上搜索,但N向下搜索 |
shift+k |
在待搜索的字符串上按shift+k或者K, 可以查看相關(guān)的幫助文檔 |
1.3.2 切換到文本輸入模式
從命令模式切換到文本輸入模式只需輸入如下命令:
快捷鍵 |
操作 |
i |
在光標(biāo)前插入 |
a |
在光標(biāo)后插入 |
I |
在光標(biāo)所在行的行首插入 |
A |
在光標(biāo)所在行的行尾插入 |
o |
在光標(biāo)所在的行的下面新創(chuàng)建一行, 行首插入 |
O |
在光標(biāo)所在的行的上面新創(chuàng)建一行, 行首插入 |
s |
刪除光標(biāo)后邊的字符, 從光標(biāo)當(dāng)前位置插入 |
S |
刪除光標(biāo)所在當(dāng)前行, 從行首插入 |
按列模式插入 |
先按ctrl+v進(jìn)入列模式, 按hjkl移動選定某列,按I或者shift+i向前插入, 然后插入字符, 最后按兩次esc. |
1.3.3 末行模式下的操作
從命令模式切換到末行模式, 輸入冒號(:)
保存退出
快捷鍵 |
操作 |
q |
退出 |
?q! |
強(qiáng)制退出,不保存修改內(nèi)容 |
w |
保存修改內(nèi)容, 不退出 |
wq |
保存并退出 |
x |
相當(dāng)于wq |
替換操作
下面表格中old表示原字符串, new表示新字符串
快捷鍵 |
操作 |
:s/old/new/ |
光標(biāo)所在行的第一個old替換為new |
:s/old/new/g |
光標(biāo)所在行的所有old替換為new |
:m, ns/old/new/g |
將第m行至第n行之間的old全部替換成new |
:%s/old/new/g |
當(dāng)前文件的所有old替換為new |
:1,$s/old/new/g |
當(dāng)前文件的所有old替換為new |
:%s/old/new/gc |
同上,但是每次替換需要用戶確認(rèn) |
快速翻屏
???快捷鍵 |
操作 |
ctrl + u |
向下翻半屏(up)--光標(biāo)向上移動 |
ctrl + d |
向上翻半屏(down)--光標(biāo)向下移動 |
ctrl + f |
向上翻一屏(front) |
ctrl + b |
向后翻一屏(back) |
在末行模式下執(zhí)行shell命令
!shell命令
按下兩次esc可以回到命令模式
分屏操作
- 在打開文件之后分屏:
快捷鍵 |
操作 |
sp |
當(dāng)前文件水平分屏 |
vsp |
當(dāng)前文件垂直分屏 |
sp?文件名 |
當(dāng)前文件和另一個文件水平分屏 |
vsp?文件名 |
當(dāng)前文件和另一個文件垂直分屏 |
ctrl-w-w |
在多個窗口切換光標(biāo) |
wall/wqall/xall/qall/qall! |
保存/保存退出/保存退出/退出/強(qiáng)制退出分屏窗口 |
- 在打開文件之前分屏:
分屏: vim?-on?file1 file2 … ?
垂直分屏: vim?-On file1 file2… ?
注意: n可以省略, 有幾個文件就分幾屏
從末行模式切換回命令模式
按兩次ESC, 退格(backspace)或者回車鍵
1.3.4 vim的配置文件
用戶級別配置文件
~/.vimrc, 修改用戶級別的配置文件只會影響當(dāng)前用戶,?不會影響其他的用戶.
例如: 在用戶的家目錄下的.vimrc文件中添加
set tabstop=4 ?----設(shè)置縮進(jìn)4個空格
set nu ???????----設(shè)置行號
set shiftwidth=4 ?---設(shè)置gg=G縮進(jìn)4個空格, 默認(rèn)是縮進(jìn)8個空格
系統(tǒng)級別配置文件
/etc/vim/vimrc, 修改了系統(tǒng)級別的配置文件將影響系統(tǒng)下的所有用戶.
說明: 由于linux是多用戶操作系統(tǒng), 建議只在用戶級別的配置文件下進(jìn)行修改, 不要影響其他用戶.
2 gcc編譯器
2.1 gcc的工作流程
gcc編譯器將c源文件到生成一個可執(zhí)行程序,中間一共經(jīng)歷了四個步驟:
?
四個步驟并不是gcc獨(dú)立完成的,而是在內(nèi)部調(diào)用了其他工具,從而完成了整個工作流程, 其中編譯最耗時(shí), 因?yàn)橐鹦袡z查語法.
下面以test.c為例介紹gcc的四個步驟:
gcc -E test.c -o test.i
gcc -S test.i -o test.s
gcc -c test.s -o test.o
gcc test.o -o test
一步生成最終的可執(zhí)行程序:
??gcc test.c -o test
2.2 gcc常用參數(shù)
- -v ?查看gcc版本號, --version也可以
- -E ?生成預(yù)處理文件
- -S ?生成匯編文件
- -c ?只編譯,?生成.o文件, 通常稱為目標(biāo)文件
- -I ??指定頭文件所在的路徑
- -L ??指定庫文件所在的路徑
- -l????指定庫的名字
- -o ??指定生成的目標(biāo)文件的名字
- -g ??包含調(diào)試信息, 使用gdb調(diào)試需要添加-g參數(shù)
- -On n=0~3 編譯優(yōu)化,n越大優(yōu)化得越多
例如:下面代碼片段
int a = 10;
int b = a;
int c = b;
printf("%d", c);
上面的代碼可能會被編譯器優(yōu)化成:
int c = 10;
printf("%d", 10);
- -Wall 提示更多警告信息
int?a;
int?b;
int?c?= 10;
printf(“[%d]\n”, c);
編譯如下:?
gcc -o test -Wall test.c
warning: unused variable ‘b’ [-Wunused-variable]
warning: unused variable ‘a(chǎn)’ [-Wunused-variable]
- -D ?編譯時(shí)定義宏
test.c文件中的代碼片段:
printf("MAX==[%d]\n", MAX);
?????????編譯:
???? gcc -o test test.c -D MAX=10
???????gcc -o test test.c -DMAX=10
3 靜態(tài)庫和共享(動態(tài))庫
3.1庫的介紹 ??
什么是庫
???庫是二進(jìn)制文件, 是源代碼文件的另一種表現(xiàn)形式, 是加了密的源代碼;
是一些功能相近或者是相似的函數(shù)的集合體.
使用庫有什么好處
- 提高代碼的可重用性, 而且還可以提高程序的健壯性;
- 可以減少開發(fā)者的代碼開發(fā)量, 縮短開發(fā)周期.
庫制作完成后, 如何給用戶使用
- 頭文件---包含了庫函數(shù)的聲明
- 庫文件---包含了庫函數(shù)的代碼實(shí)現(xiàn)
注意: 庫不能單獨(dú)使用, 只能作為其他執(zhí)行程序的一部分完成某些功能, 也
就是說只能被其他程序調(diào)用才能使用.
庫可分靜態(tài)庫(static library)和共享庫(shared library)
3.2靜態(tài)庫(static library)
靜態(tài)庫可以認(rèn)為是一些目標(biāo)代碼的集合, 是在可執(zhí)行程序運(yùn)行前就已經(jīng)加入到執(zhí)行碼中,?成為執(zhí)行程序的一部分. 按照習(xí)慣,?一般以.a做為文件后綴名.
靜態(tài)庫的命名一般分為三個部分:
- 前綴:lib
- 庫名稱:自定義即可, 如test
- 后綴:.a
所以最終的靜態(tài)庫的名字應(yīng)該為:libtest.a
靜態(tài)庫的制作
下面以fun1.c , fun2.c和head.h三個文件為例講述靜態(tài)庫的制作和使用, 其中head.h文件中有函數(shù)的聲明, ?fun1.c和fun2.c中有函數(shù)的實(shí)現(xiàn).
步驟1:將c源文件生成對應(yīng)的.o文件
gcc -c fun1.c fun2.c
???或者分別生成.o文件:
? gcc -c fun1.c -o fun1.o
? gcc -c fun2.c -o fun2.o
步驟2:使用打包工具ar將準(zhǔn)備好的.o文件打包為.a文件?
- 在使用ar工具是時(shí)候需要添加參數(shù)rcs
- r更新、c創(chuàng)建、s建立索引
- 命令:ar rcs 靜態(tài)庫名?.o文件
- ar rcs libtest1.a fun1.o fun2.o
靜態(tài)庫的使用
靜態(tài)庫制作完成之后, 需要將.a文件和頭文件一定發(fā)布給用戶.
假設(shè)測試文件為main.c, 靜態(tài)庫文件為libtest1.a, 頭文件為head.h
用到的參數(shù):
- -L:指定要連接的庫的所在目錄
- -l:指?
- -I: 指定main.c文件用到的頭文件head.h所在的路徑
gcc -o main1 main.c -L./ -ltest1 -I./
gcc -o main1 main.c -L./ -ltest1
-I 指向頭文件所在的位置 -L指向庫文件所在的位置,頭文件和庫文件在同一個目錄-I 可以省略
使用ldd main1.可以查看加載的動態(tài)庫是否找到了。
靜態(tài)庫的優(yōu)缺點(diǎn)
-
優(yōu)點(diǎn):
- 函數(shù)庫最終被打包到應(yīng)用程序中,實(shí)現(xiàn)是函數(shù)本地化,尋址方便、速度快。
(庫函數(shù)調(diào)用效率==自定義函數(shù)使用效率)
-
- 程序在運(yùn)行時(shí)與函數(shù)庫再無瓜葛,移植方便。
-
缺點(diǎn):
- 消耗系統(tǒng)資源較大, 每個進(jìn)程使用靜態(tài)庫都要復(fù)制一份, 無端浪費(fèi)內(nèi)存。
-
- 靜態(tài)庫會給程序的更新、部署和發(fā)布帶來麻煩。如果靜態(tài)庫libxxx.a更新了,所有使用它的應(yīng)用程序都需要重新編譯、發(fā)布給用戶(對于玩家來說,可能是一個很小的改動,卻導(dǎo)致整個程序重新下載)。
func1.c
#include <stdio.h>
void func1()
{
printf("this is fun1\n");
}
func2.c?
1 #include <stdio.h>
2 void func2()
3 {
4 printf("this is fun2\n");
5 }
~
~
main.c?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "head.h"
int main(int argc, char *argv[])
{
printf("this is main!\n");
int i = 0;
for(i=0; i<argc; i++)
{
printf("[%d]:[%s]\n", i, argv[i]);
}
func1();
func2();
printf("sum(10)==[%d]\n", sum(10));
return 0;
}
head.h
void func1();
void func2();
int sum(int len);
sum.c
#include<stdio.h>
int sum(int len){
int i=0;
int sum=0;
for(i=0;i<len;i++){
sum+=i;
}
return sum;
}
3.3共享庫(shared library)/動態(tài)庫
共享庫在程序編譯時(shí)并不會被連接到目標(biāo)代碼中, 而是在程序運(yùn)行是才被載入. 不同的應(yīng)用程序如果調(diào)用相同的庫, 那么在內(nèi)存里只需要有一份該共享庫的拷貝, 規(guī)避了空間浪費(fèi)問題.動態(tài)庫在程序運(yùn)行時(shí)才被載入, 也解決了靜態(tài)庫對程序的更新、部署和發(fā)布會帶來麻煩. 用戶只需要更新動態(tài)庫即可, 增量更新. 為什么需要動態(tài)庫, 其實(shí)也是靜態(tài)庫的特點(diǎn)導(dǎo)致.
按照習(xí)慣,?一般以”.so”做為文件后綴名. 共享庫的命名一般分為三個部分:
- 前綴:lib
- 庫名稱:自己定義即可, 如test
- 后綴:.so
所以最終的靜態(tài)庫的名字應(yīng)該為:libtest.so
共享庫的制作
- 生成目標(biāo)文件.o, 此時(shí)要加編譯選項(xiàng):-fPIC(fpic)
gcc?-fpic -c fun1.c?fun2.c
參數(shù):-fpic創(chuàng)建與地址無關(guān)的編譯程序(pic, position independent code), 目的就是為了能夠在多個應(yīng)用程序間共享.
- 生成共享庫, 此時(shí)要加鏈接器選項(xiàng): -shared(指定生成動態(tài)鏈接庫)
gcc -shared fun1.o fun2.o -o libtest2.so
共享庫的使用
引用動態(tài)庫編譯成可執(zhí)行文件(跟靜態(tài)庫方式一樣):
用到的參數(shù):
- -L:指定要連接的庫的所在目錄
- -l:指定鏈接時(shí)需要的動態(tài)庫, 去掉前綴和后綴
- -I: 指定main.c文件用到的頭文件head.h所在的路徑
gcc main.c -I./ -L./ -ltest2 -o main2
然后運(yùn)行:./main2,發(fā)現(xiàn)竟然報(bào)錯了.
分析為什么在執(zhí)行的時(shí)候找不到libtest2.so庫
- 當(dāng)系統(tǒng)加載可執(zhí)行代碼時(shí)候, 能夠知道其所依賴的庫的名字, 但是還需要知道所依賴的庫的絕對路徑。此時(shí)就需要系統(tǒng)動態(tài)載入器(dynamic linker/loader)。
ldd命令可以查看可執(zhí)行文件依賴的庫文件, 執(zhí)行l(wèi)dd?main2, 可以發(fā)現(xiàn)libtest2.so找不到.
- 對于elf格式的可執(zhí)行程序,是由ld-linux.so*來完成的, 它先后搜索elf文件的 DT_RPATH段?— 環(huán)境變量LD_LIBRARY_PATH?— /etc/ld.so.cache文件列表?— /lib/,?/usr/lib目錄找到庫文件后將其載入內(nèi)存。
使用file命令可以查看文件的類型: file main2
如何讓系統(tǒng)找到共享庫
- 拷貝自己制作的共享庫到/lib或者/usr/lib
- 臨時(shí)設(shè)置LD_LIBRARY_PATH:
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:庫路徑
- 永久設(shè)置, 把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:庫路徑, 設(shè)置到~/.bashrc文件中, 然后在執(zhí)行下列三種辦法之一:
- 執(zhí)行. ~/.bashrc使配置文件生效(第一個.后面有一個空格)
- 執(zhí)行source?~/.bashrc配置文件生效
- 退出當(dāng)前終端, 然后再次登陸也可以使配置文件生效
- 永久設(shè)置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:庫路徑,設(shè)置到/etc/profile文件中
- 將其添加到 /etc/ld.so.cache文件中
- 編輯/etc/ld.so.conf文件, 加入庫文件所在目錄的路徑
- 運(yùn)行sudo?ldconfig -v, 該命令會重建/etc/ld.so.cache文件
解決了庫的路徑問題之后, 再次ldd命令可以查看可執(zhí)行文件依賴的庫文件, ldd?main2:
共享庫的特點(diǎn)
- 動態(tài)庫把對一些庫函數(shù)的鏈接載入推遲到程序運(yùn)行的時(shí)期。
- 可以實(shí)現(xiàn)進(jìn)程之間的資源共享。(因此動態(tài)庫也稱為共享庫)
- 將一些程序升級變得簡單。
甚至可以真正做到鏈接載入完全由程序員在程序代碼中控制(顯示調(diào)用)
3.4比較靜態(tài)庫和動態(tài)庫的優(yōu)缺點(diǎn)
?靜態(tài)庫的優(yōu)點(diǎn):
? 1 執(zhí)行速度快, 是因?yàn)殪o態(tài)庫已經(jīng)編譯到可執(zhí)行文件內(nèi)部了
? 2 移植方便, 不依賴域其他的庫文件
?缺點(diǎn):
? 1 耗費(fèi)內(nèi)存, 是由于每一個靜態(tài)庫的可執(zhí)行程序都會加載一次
? 2 部署更新麻煩, 因?yàn)殪o態(tài)庫修改以后所有的調(diào)用到這個靜態(tài)庫的可執(zhí)行文
件都需要重新編譯
?動態(tài)庫的優(yōu)點(diǎn):
? 1 節(jié)省內(nèi)存
? 2 部署升級更新方便, 只需替換動態(tài)庫即可,?然后再重啟服務(wù).
?缺點(diǎn):
? 1 加載速度比靜態(tài)庫慢
? 2 移植性差, 需要把所有用到的動態(tài)庫都移植.
由于由靜態(tài)庫生成的可執(zhí)行文件是把靜態(tài)庫加載到了其內(nèi)部, 所以靜態(tài)庫生成的可執(zhí)行文件一般會比動態(tài)庫大.
作業(yè):
1 復(fù)習(xí)當(dāng)天內(nèi)容, 重點(diǎn)是gcc和庫的制作和使用
2 編寫4個.c文件, 加, 減,?乘, 除
??add.c --加法
??sub.c --減法
??mul.c --乘法
??dive.c --除法
??main.c?---主函數(shù)所在文件, 內(nèi)部調(diào)用上述函數(shù)
??head.h??---函數(shù)聲明
??libsmath.a ?--靜態(tài)庫文件
??libdmath.so ?--動態(tài)庫文件
??main1---靜態(tài)庫可執(zhí)行程序文章來源:http://www.zghlxwxcb.cn/news/detail-650465.html
??main2--動態(tài)庫可執(zhí)行程序文章來源地址http://www.zghlxwxcb.cn/news/detail-650465.html
到了這里,關(guān)于linux 系統(tǒng)中vi 編輯器和庫的制作和使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!