1、基本的shell操作
shell命令行快捷鍵
編輯命令
Ctrl + a 移到命令行首, ahead,與home鍵功能相同
Ctrl + e 移到命令行尾, end, 與end鍵功能相同
Ctrl + f 按字符前移(右向), forward, 與方向鍵left功能相同
Ctrl + b 按字符後移(左向), back, 與方向鍵right功能相同
Alt + f 按單詞前移(右向)
Alt + b 按單詞後移(左向)
Ctrl + xx 在命令行首和光標之間移動
Ctrl + u 從光標處刪除至命令行首
Ctrl + k 從光標處刪除至命令行尾
Ctrl + w 從光標處刪除至字首
Alt + d 從光標處刪除至字尾
Ctrl + d 刪除光標處的字符, 與delete鍵功能相同
Ctrl + h 刪除光標前的字符, 與backspace鍵功能相同
Ctrl + y 粘貼至光標後, yank
Alt + c 從光標處更改為首字母大寫的單詞
Alt + u 從光標處更改為全部大寫的單詞, uppercase
Alt + l 從光標處更改為全部小寫的單詞, lowercase
Ctrl + t 交換光標處和之前的字符
Alt + t 交換光標處和之前的單詞
Alt + Backspace 與 Ctrl + w 類似,分隔符有些差別
重新執行命令
Ctrl + r 逆向搜索命令歷史
Ctrl + g 從歷史搜索模式退出
Ctrl + p 歷史中的上一條命令, previous,與方向鍵up功能相同
Ctrl + n 歷史中的下一條命令, next, 與方向鍵down功能相同
Alt + . 使用上一條命令的最後一個參數
控制命令
Ctrl + l 清屏, clear
Ctrl + o 執行當前命令,並選擇上一條命令
Ctrl + s 阻止屏幕輸出
Ctrl + q 允許屏幕輸出
Ctrl + c 終止命令
Ctrl + z 掛起命令
Bang (!) 命令
!! 執行上一條命令
!blah 執行最近的以 blah 開頭的命令,如 !ls
!blah:p 僅打印輸出,而不執行
!$ 上一條命令的最後一個參數,與 Alt + . 相同
!$:p 打印輸出 !$ 的內容
!* 上一條命令的所有參數
!*:p 打印輸出 !* 的內容
^blah 刪除上一條命令中的 blah
^blah^foo 將上一條命令中的 blah 替換為 foo
^blah^foo^ 將上一條命令中所有的 blah 都替換為 foo
虛擬終端(VT)
簡介
英文:Virtual Terminal
解釋:連接在遠地的分時共用計算機系統的遠程終端,它具有使用戶感到是在計算機旁使用終端的功能。
常用工具
XManager
Putty
SecureCRT
命令和路徑補齊
tab鍵按一次 當只有一個匹配時,自動補全命令或路徑
tab鍵按兩次 當有多個匹配時,顯示命令或路徑列表
2、Linux 標准目錄結構
初學Linux,首先需要弄清Linux 標准目錄結構:
/
root --- 啟動Linux時使用的一些核心文件。如操作系統內核、引導程序Grub等。
home --- 存儲普通用戶的個人文件
ftp --- 用戶所有服務
httpd
samba
user1
user2
bin --- 系統啟動時需要的執行文件(二進制)
sbin --- 可執行程序的目錄,但大多存放涉及系統管理的命令。只有root權限才能執行
proc --- 虛擬,存在linux內核鏡像;保存所有內核參數以及系統配置信息
1 --- 進程編號
usr --- 用戶目錄,存放用戶級的文件
bin --- 幾乎所有用戶所用命令,另外存在與/bin,/usr/local/bin
sbin --- 系統管理員命令,與用戶相關,例如,大部分服務器程序
include --- 存放C/C++頭文件的目錄
lib --- 固定的程序數據
local --- 本地安裝軟件保存位置
man --- 手工生成的目錄
info --- 信息文檔
doc --- 不同包文檔信息
tmp
X11R6 --- 該目錄用於保存運行X-Window所需的所有文件。該目錄中還包含用於運行GUI要的配置文件和二進制文件。
X386 --- 功能同X11R6,X11 發行版5 的系統文件
boot --- 引導加載器所需文件,系統所需圖片保存於此
lib --- 根文件系統目錄下程序和核心模塊的公共庫
modules --- 可加載模塊,系統崩潰後重啟所需模塊
dev --- 設備文件目錄
etc --- 配置文件
skel --- home目錄建立,該目錄初始化
sysconfig --- 網絡,時間,鍵盤等配置目錄
var
file
lib --- 該目錄下的文件在系統運行時,會改變
local --- 安裝在/usr/local的程序數據,變化的
lock --- 文件使用特定外設或文件,為其上鎖,其他文件暫時不能訪問
log --- 記錄日志
run --- 系統運行合法信息
spool --- 打印機、郵件、代理服務器等假脫機目錄
tmp
catman --- 緩存目錄
mnt --- 臨時用於掛載文件系統的地方。一般情況下這個目錄是空的。
在我們將要掛載分區時在這個目錄下建立目錄,再將我們將要訪問的設備掛載在這個目錄上,這樣我們就可訪問文件了。
tmp --- 臨時文件目錄,系統啟動後的臨時文件存放在/var/tmp
lost+found --- 在文件系統修復時恢復的文件
/
根目錄,一般根目錄下只存放目錄,不要存放文件。
/etc、/bin、/dev、/lib、/sbin應該和根目錄放置在一個分區中。
/bin, /usr/bin
可執行二進制文件的目錄,如常用的命令ls、tar、mv、cat等。
/boot
放置linux系統啟動時用到的一些文件。/boot/vmlinuz為linux的內核文件,以及/boot/gurb。建議單獨分區,分區大小100M即可。
/dev
存放linux系統下的設備文件,訪問該目錄下某個文件,相當於訪問某個設備,常用的是掛載光驅mount:
/dev/cdrom、/mnt
/etc
系統配置文件存放的目錄,不建議在此目錄下存放可執行文件。
重要的配置文件有:/etc/inittab、/etc/fstab、/etc/init.d、/etc/X11、/etc/sysconfig、/etc/xinetd.d。
修改配置文件之前記得備份。
注:/etc/X11存放與x windows有關的設置。
/home
系統默認的用戶家目錄,新增用戶賬號時,用戶的家目錄都存放在此目錄下。
~表示當前用戶的家目錄,~test表示用戶test的家目錄。
建議單獨分區,並設置較大的磁盤空間,方便用戶存放數據。
/lib,/usr/lib,/usr/local/lib
系統使用的函數庫的目錄,程序在執行過程中,需要調用一些額外的參數時需要函數庫的協助,比較重要的目錄為/lib/modules。
/lost+fount
系統異常產生錯誤時,會將一些遺失的片段放置於此目錄下,通常這個目錄會自動出現在裝置目錄下。
如加載硬盤於/disk 中,此目錄下就會自動產生目錄/disk/lost+found
/mnt,/media
光盤默認掛載點,通常光盤掛載於/mnt/cdrom下,也不一定,可以選擇任意位置進行掛載。
/opt
給主機額外安裝軟件所擺放的目錄。
如:FC4使用的Fedora 社群開發軟件,如果想要自行安裝新的KDE 桌面軟件,可以將該軟件安裝在該目錄下。
以前的 Linux 系統中,習慣放置在 /usr/local 目錄下。
/proc
此目錄的數據都在內存中,如系統核心,外部設備,網絡狀態,由於數據都存放於內存中,所以不占用磁盤空間。
比較重要的目錄有/proc/cpuinfo、/proc/interrupts、/proc/dma、/proc/ioports、/proc/net/*等。
/root
系統管理員root的家目錄,系統第一個啟動的分區為/,所以最好將/root和/放置在一個分區下。
/sbin,/usr/sbin,/usr/local/sbin
放置系統管理員使用的可執行命令,如fdisk、shutdown、mount等。
與/bin不同的是,這幾個目錄是給系統管理員root使用的命令,一般用戶只能"查看"而不能設置和使用。
/tmp
一般用戶或正在執行的程序臨時存放文件的目錄,任何人都可以訪問,重要數據不可放置在此目錄下。
/srv
服務啟動之後需要訪問的數據目錄,如www服務需要訪問的網頁數據存放在/srv/www內。
/usr
應用程序存放目錄。
/usr/bin 存放應用程序。
/usr/share 存放共享數據。
/usr/lib 存放不能直接運行的,卻是許多程序運行所必需的一些函數庫文件。
/usr/local 存放軟件升級包。
/usr/share/doc 系統說明文件存放目錄。
/usr/share/man 程序說明文件存放目錄。
使用 man ls時會查詢/usr/share/man/man1/ls.1.gz的內容。
建議單獨分區,設置較大的磁盤空間。
/var
放置系統執行過程中經常變化的文件。
/var/log 隨時更改的日志文件。
/var/log/message 所有的登錄文件存放目錄。
/var/spool/mail 郵件存放的目錄。
/var/run 程序或服務啟動後,其PID存放在該目錄下。
建議單獨分區,設置較大的磁盤空間。
3、文件和目錄操作相關命令
用戶目錄
ls
ls -al
-a, --all 不隱藏任何以. 開始的項目
-l 使用較長格式列出信息
-rw-r--r-- 1 super root 3771 6月 7 2016 .bashrc
drwx------ 22 super root 4096 12月 15 08:02 .cache
lrwxrwxrwx 1 super root 31 11月 23 07:42 .vimrc -> /home/super/.spf13-vim-3/.vimrc
以最後一個為例:
lrwxrwxrwx
第1個字符:表示文件類型
- 普通文件
d 目錄
l 鏈接符號
b 塊設備
c 字符設備
s socket文件
p 管道
第2-4個字符:文檔所有者權限
第5-7個字符:同組用戶權限
第8-10個字符:其他人權限
r: read 4
w: write 2
x: execute 1
1 文件的硬鏈接數
super 該文件或目錄的所有者
root 該文件或目錄所屬的組
31 占用的存儲空間
11月 23 07:42 文件最後創建或修改的時間
.vimrc 文件名
cd
cd ~ 切換到用戶home目錄
cd / 切換到根目錄
cd 切換到用戶home目錄
cd.. 切換到上一級目錄
tree
tree path 顯示指定路徑的目錄樹結構
文件或目錄顏色一般情況
白色 普通文件
藍色 目錄
綠色 可執行文件
紅色 壓縮文件
青色 鏈接文件
黃色 設備文件
灰色 其他文件
mkdir
mkdir dirname 創建目錄。
mkdir dir1/dir2/dir3 -p 按層次創建目錄。
rmdir
rmdir dirname 目錄必須為空才能刪除,所以實際使用時不常用。
rm
rm -rf dirname 遞歸強制刪除文件夾下的目錄和文件,實際使用中常用。
rm -ri dirname 遞歸刪除並提示用戶刪除了哪些目錄或文件。
touch
touch test.txt 創建文件。
cp
cp hello.c temp 在當前目錄下生成一個temp文件,並把hello.c的內容寫入文件。
如果temp不存在,則創建文件;如果存在,則覆蓋已有文件。
cp mydir newdir -r 在當前目錄下生成一個newdir目錄,並把mydir目錄裡面的目錄或文件拷貝過去。
如果目錄不存在,則創建;如果存在,則mydir目錄本身也拷貝到newdir目錄下。
cat
cat test.txt 查看文件的內容,缺點內容太多時查看困難。
more
more stdio.h 分屏查看文件,Enter下翻一行,Space下翻一頁,缺點不能往回看。
less
less stdio.h 分屏查看文件。比more更實用,可以來回翻頁。
ctrl + p 上翻一行
ctrl + n 下翻一行
ctrl + b 上翻一頁
ctrl + f 下翻一頁
q 退出
head
head -5 stdio.h 查看前五行內容,不加參數默認是10行。
tail
tail -5 stdio.h 查看後5行內容, 不加參數默認是10行。
mv
mv test.c hello.c 移動到。多用於重命名目錄或文件。
ln
ln -s ~/.vim/.vimrc .vimrc 創建軟鏈接,相當於windows下的快捷方式,可用於目錄或文件。
路徑要用絕對路徑,這樣軟鏈接拷貝到哪裡都是有效的。
如果刪除原文件,則軟鏈接失效。
ln .vimrc .vimrc.hard 創建硬鏈接,只能用於文件。不必使用絕對路徑。
創建後生成的硬鏈接與原文件引用同一個inode,硬鏈接本身不占硬盤空間。
如果刪除原文件,硬鏈接仍然有效。
wc
wc test.c 統計文件的行數,字數,字節數。
od
od -tx test.c 以十六進制形式查看文件。
od -tc test.c 以ASCII字符形式查看文件。
od -td test.c 以有符號十進制形式查看文件。
od -tf test.c 以浮點數形式查看文件。
od -to test.c 以八進制形式查看文件。
od -tu test.c 以無符號十進制形式查看文件。
du
du -h 查看當前文件夾下的目錄或文件所占用磁盤的大小。
df
df -h 查看當前文件夾下的目錄或文件所使用磁盤空間的詳細情況。
which
which ls 查看外部命令的位置,內部命令無法查看。
pwd
pwd 查看當前所在目錄
4、文件權限、用戶、用戶組相關命令
查看當前用戶
whoami 查看當前用戶名。
id 查看當前用戶信息,如用戶名,所屬群組,UID,GID等。
修改目錄或文件權限
文字設定法
chmod [who] [+|-|=] [mode]
who : 不指定的話,默認是所有
文件所有者:u
文件所屬組:g
其他人:o
所有人:a
mode
r : 讀
w : 寫
x : 執行
chmod o+w temp 給其他人加寫權限。
chmod a-x temp 給所有人去除執行權限。
chmod a=r temp 所有人只有讀權限。
數字設定法
- 0 沒有權限
r 4 讀
w 2 寫
x 1 執行
chmod 755 temp -rwxr-xr-x
chmod -001 temp -rwxr-xr--
修改目錄或文件所有者與所屬組
chown root temp 把文件temp的所有者修改為root。
chown super:root temp 把文件temp的所有者修改super,所屬組修改為root。
修改目錄或文件所屬組
chgrp root temp 修改文件所屬組為root。
目錄必須有執行權限,否則不能打開目錄。
5、查找和檢索相關命令
按文件屬性查找
文件名
find ~ -name "hello.c" 按完整名稱匹配
find ~ -name "*.h" *代表任意長度字符
find ~ -name "tem?" ?代表一個任意字符
文件大小
find ~ -size +10k 查找大於10k的文件
find ~ -size -10M 查找小於10M的文件
find ~ -size +10M -size -100M 查找大於10M小於是100M的文件
文件類型
find ~ -type p 查找類型為管道的檔案
find ~ -type f 查找類型為文件的檔案
find ~ -type d 查找類型為目錄的檔案
find ~ -type l 查找類型為鏈接的檔案
按文件內容查找
grep -r "stdio.h" ~ 在用戶家目錄中查找文件內容裡包括stdio.h的所有文件
6、軟件安裝和卸載
在線安裝
apt-get
安裝 apt-get install tree 在線下載安裝
移除 apt-get remove tree
更新 apt-get update 更新軟件列表
清理 apt-get clean 清理所有軟件安裝包,實際上清理的是/var/cache/apt/archives目錄下的.deb文件
aptitude
安裝 aptitude install tree
重新安裝 aptitude reinstall tree
更新 apt-get update
移除 aptitude remove tree
顯示狀態 aptitude show tree
deb包安裝
安裝
dpkg -i xxx.deb
刪除
dpkg -r xxx
源碼安裝
1)解壓縮源代碼包。
2)進入安裝目錄。
3)檢測文件是否缺失,創建Makefile,檢測編譯環境:./configure。
4)編譯源碼,生成庫和可執行程序:make。
5)把庫和可執行程序,安裝到系統目錄下:make install。
6)刪除和卸載軟件:make distclean。
7)上述安裝步驟並不是絕對的,應該先查看附帶的README文件。
7、磁盤管理
磁盤設備種類
hd Hard Disk 硬盤
fd Floppy Disk 軟盤
sd SCSI Device 小型計算機系統接口(英語:Small Computer System Interface; 簡寫:SCSI)。
一種用於計算機和智能設備之間(硬盤、軟驅、光驅、打印機、掃描儀等)系統級接口的獨立處理器標准。
SCSI是一種智能的通用接口標准。
設備都保存在/dev中
sd後面加小寫字母,分別代表不同的硬盤,如:
sda 第一個硬盤
sdb 第二個硬盤
sdc 第三個硬盤
sdd 第四個硬盤
每個硬盤又分為主分區和邏輯分區,一個硬盤最多允許四個主分區,第一個邏輯分區從sda5開始。
主分區:
sda1 主分區1
sda2 主分區2
sda3 主分區3
sda4 主分區4
擴展分區:
sda5 邏輯分區1
sda6 邏輯分區2
sda7 邏輯分區3
......
查看設備信息
fdisk -l 當你不知道usb的名稱時,可以用這個命令在獲取
掛載USB
mount /dev/sdb1 /mnt
注: 如果掛載的目錄不是一個空目錄,則目錄裡面的內容會被臨時覆蓋掉,導致目錄原有文件無法操作,卸載後會恢復原有文件。
建議使用空目錄, 如/mnt。
卸載USB
umount /mnt
1、壓縮包管理
屌絲版
gzip -- .gz格式壓縮包
gzip *.txt 假設當前目錄中有a.txt和b.txt, 則會生成a.txt.gz和b.txt.gz,txt源文件會被刪除。
這個命令不能用於目錄。
gunzip *.gz 解壓
bzip2 -- .bz2格式的壓縮包
bzip2 -k *.txt 假設當前目錄中有a.txt和b.txt,則會生成a.txt.bz2和b.txt.bz2文件,加-k參數可以將源文件保留。
這個命令不能用於目錄。
bunzip2 *.bz2 解壓
高富帥版
tar -- 不使用z或j參數,該命令只能對文件和目錄打包
參數
c 創建--壓縮時使用。
x 釋放--解壓縮時使用。
v 顯示提示信息--壓縮和解壓縮都可以使用,可以省略。
f 指定壓縮文件的名字
z 使用gzip的方式壓縮文件
j 使用bzip2的方式壓縮文件
壓縮
用法:tar zcvf 生成的壓縮包的名字(xxx.tar.gz) 要壓縮的文件或目錄
示例:tar zcvf alltxt.tar.gz *.txt test/ 同時對文件和目錄進行打包壓縮
用法:tar jcvf 生成的壓縮包的名字(xxx.tar.bz2) 要壓縮的文件或目錄
示例:tar jcvf alltxt.tar.bz2 *.txt test/ 同時對文件和目錄進行打包壓縮
解壓縮
tar zxvf 壓縮包的名字 解壓到當前目錄
tar jxvf 壓縮包的名字 -C 目錄 解壓到指定目錄
rar
參數
a Add壓縮
x Extract解壓縮
r 壓縮時遞歸目錄,不加這個參數默認就是遞歸的
壓縮
用法:rar a 生成的壓縮文件的名字 壓縮的文件或目錄
示例:
rar a all *.txt 打包壓縮文件
rar a dir dir/ 打包壓縮目錄
解壓縮
用法:rar x 壓縮文件名 [解壓縮目錄]
示例:rar x all.rar
zip
參數
r 壓縮目錄時加個參數用於遞歸目錄,不加不能壓縮
壓縮
用法:zip 壓縮包的名字 壓縮的文件或目錄
示例:zip all *.txt
zip -r myzip mytest/
解壓縮
用法:unzip 壓縮包的名字
unzip 壓縮包的名字 -d 解壓的目錄
示例:unzip all.zip
unzip all.zip -d test/
2、進程管理
查看在線用戶狀態
who 查看當前在線用戶的狀態
tty1~tty6 文字界面終端
tty7 圖形界面終端
pts 虛擬終端
Alt+Ctrl+F1~F7 切換終端,切換後各個終端互不影響
查看進程
ps aux 查看在線用戶下所有進程
ps aux | grep bash 進程過濾
終止進程
kill -l 查看所有信號
kill -SIGKILL 5179 終止進程
kill -9 4678 終止進程
查看當前進程的環境變量
env 查看所有環境變量
env | grep PATH 只查看PATH環境變量
查看系統狀態
top
3、網絡管理
獲取網絡接口信息
ifconfig
測試與目標主機連通性
ping www.baidu.com -c 4 發送4個數據包後終止
查看服務器域名對應的IP地址
nslookup www.baidu.com
4、用戶管理
創建用戶
adduser super 用戶名只能小寫,不能大寫
useradd -s /bin/bash -g super -d /home/super -m super 用戶名可以大寫
-s 指定新用戶登陸時shell類型
-g 指定所屬組,該組必須已經存在
-d 用戶家目錄
-m 用戶家目錄不存在時,自動創建該目錄
設置用戶組
groupadd super
刪除用戶
deluser super
userdel -r super 選項-r的作用是把用戶的主目錄一起刪除
切換用戶
su super
修改用戶密碼
passwd super
退出當前用戶
exit
查看所有用戶信息
vi /etc/passwd
5、ftp服務器搭建
服務器端
安裝vsftpd
apt-get install -y vsftpd 安裝完成後會隨系統啟動而自動啟動
修改配置文件
vi /etc/vsftpd.conf
listen=YES
anon_root=/home/super/anonFtp/ #指定匿名用戶根目錄,不指定默認是/srv/ftp/
anonymous_enable=YES #允許匿名用戶登錄
write_enable=YES #實名用戶擁有寫權限(上傳數據)
local_umask=022 #設置本地掩碼為022
anon_upload_enable=YES #匿名用戶可以向ftp服務器上傳數據
anon_mkdir_write_enable=YES #匿名用戶可以在ftp服務器上創建目錄
創建匿名用戶根目錄
cd ~
mkdir anonFtp
chown ftp anonFtp
chmod 777 anonFtp
重啟服務
service vsftpd retart
客戶端
實名用戶登錄
ftp IP(server)
輸入用戶名
輸入密碼
文件的上傳和下載
文件的上傳: put file
文件的下載: get file
不允許操作目錄,如果想操作目錄 -- 打包tar/rar/zip
匿名用戶登錄
ftp IP(server)
用戶名:anonymous
密碼:直接回車
不允許匿名用戶在任意目錄直接切換
只能在一個指定目錄范圍內工作
需要在ftp服務器上創建一個匿名用戶的目錄 -- 匿名用戶的根目錄
退出
quit 推薦
bye 推薦
exit
lftp客戶端訪問ftp服務器
安裝
apt-get install -y lftp
登錄服務器
匿名
lftp IP(sever) 回車
login
實名
lftp username@IP(sever) 回車
輸入服務器密碼
操作
put file 上傳文件
mput file1 file2 上傳多個文件
get file 下載文件
mget file1 file2 下載多個文件
mirror dir 下載整個目錄及其子目錄
mirror -R dir 上傳整個目錄及其子目錄
6、nfs服務器搭建
服務器端
安裝
apt-get install nfs-kernel-server 安裝成功後會隨系統啟動而自動啟動
創建共享目錄
如: /home/super/NfsShare
修改配置文件
vi /etc/exports
在文件最後加入下面設置:
/home/super/NfsShare *(rw, sync)
重啟服務
service nfs-kernel-server restart
客戶端
掛載服務器共享目錄
用法: mount serverIP:ShareDir /mnt
示例: mount 192.168.10.100:/home/super/NfsShare /mnt
7、ssh(Secure Shell)服務器
服務器端
安裝ssh
apt-get install -y openssh-server
aptitude show openssh-server
客戶端
遠程登錄
ssh Username@ServerIP
退出登錄
logout
8、scp(Super Copy)命令
使用該命令的前提條件
目標主機已經安裝了openssh-server
使用方法
scp -r 目標用戶名@目標主機IP地址:/目標文件的絕對路徑 /保存到本機的絕對(相對)路徑
scp -r [email protected]:/home/super/SCP/ ./mydir/
9、其他命令
翻頁
Shift+PageUp 上翻頁
Shift+PageDown 下翻頁
清屏
clear
Ctrl+l
創建終端
Ctrl+Alt+T Ubuntu
Ctrl+Shift+T 添加新標簽頁
看手冊
man man
一共有九個章節,1,2,3,5是重點:
1 可執行程序或 shell 命令
2 系統調用(內核提供的函數)
3 庫調用(程序庫中的函數)
4 特殊文件(通常位於 /dev)
5 文件格式和規范,如 /etc/passwd
6 游戲
7 雜項(包括宏包和規范,如man(7),groff(7))
8 系統管理命令(通常只針對root用戶)
9 內核例程 [非標准
設置查看別名
alias 查看
alias l='ls -al' 設置
在顯示器上顯示數據
echo "hello" 打印字符串
echo $PATH 打印環境變量
echo $? 顯示上一次程序退出值
10、關機重啟
shutdown
參數
-t 秒數:設定在切換至不同的runlevel之前,警告和刪除兩訊號之間的延遲時間(秒)
-k 僅送出警告訊息文字,但不是真的要shutdown
-r shutdown之後重新開機
-h shutdown之後關機
-n 不經過init,由shutdown指令本身來做關機動作(不建議使用)
-f 重新開機時,跳過fsck指令,不檢查檔案系統
-F 重新開機時,強迫做fsck檢查
-c 將已經正在shutdown的動作取消
示例
shutdown -r now #立即重啟
shutdown -h now #立即關機
shutdown -k now 'Hey! Go away! now...' #發出警訊息,但沒有真的關機
shutdown -t3 -r now #立即重啟,但在警告和刪除processes之間,延遲3秒鐘
shutdown -h 10:42 'Hey! Go away!' #10:42關機
shutdown -r 10 'Hey! Go away!' #10分鐘後關機
shutdown -c #取消shutdown指令,必須切換至其他tty,登入之後,才能下些命令
shutdown now #切換至單人操作模式(不加任何選項時)
命令模式 -- 打開文件之後,默認進入命令模式。
移動光標
h 左
j 下
k 下
l 右
0 行首
$ 行尾
gg 文件頭部
G 文件尾部
5G 行跳轉,移到第五行
刪除操作(不是真正意義上的刪除,更象是剪切操作)
x 刪除光標後一個字符
X 刪除光標前一個字符
dw 刪除光標後一個單詞
d0 刪除光標到行首的所有字符
D(d$) 刪除光標到行尾的所有字符
dd 刪除一行
5dd 刪除五行
撤消操作
u 撤消
ctrl+r 還原前一個操作
復制粘貼
p 小寫的p,粘貼到光標的下一行
P 大寫的p,粘貼到光標的所在行
yy 復制一行
5yy 復制五行
可視模式
v 切換到可視塊模式
h/j/k/l 調整選中塊
y 復制
d 刪除
p 粘貼
查找模式
/ 切換到查找模式,向下查找
? 切換到查找模式,向上查找
n 下一個匹配
N 上一個匹配
# 移到要查找的單詞上,按#號即可開啟查找模式
字符替換
r 單個字符替換
行縮進
>> 向右縮進
<< 向左縮進
查看函數man文檔
K 先輸入3(庫函數章節),再輸入K,以查看指定函數的man文檔
編輯模式 -- 需要輸入一些命令,切換到編輯模式。
a 在光標所在位置的後邊插入
A 在當前行的尾部插入
i 在光標所在位置的前邊插入
I 在光標所在行的行首插入
o 在光標所在行的下邊開辟一個新的行
O 在光標所在行的上邊開辟一個新的行
s 刪除光標後邊的字符
S 刪除光標所有的行
末行模式 -- 在末行模式下可以輸入一些命令。
:s/tom/jack/g 把光標所在行的tom替換成jack
:%s/tom/jack/g 把整個文檔的tom替換成jack
:25,30s/tom/jack/g 把25到30行的tom替換成jack
:q 退出
:q! 強制退出
:w 保存
:wq 保存並退出
:x 相當於:wq
ZZ 相當於:wq
分屏操作
:sp [file] 將屏幕水平分成兩部分
:vsp [file] 交屏幕垂直分成兩部分
:wqall 同時保存打開文件
ctrl+ww 切換兩個屏幕
vim打造成IDE
/etc/vim/vimrc 系統級配置文件
~/.vim/vimrc 用戶級配置文件
gcc編譯的四個階段:
hello.c --------> hello.i --------> hello.s --------> hello.o -------> hello.out
預處理編譯器(cpp) 編譯器(gcc) 匯編器(as) 鏈接器(ld)
gcc -E gcc -S gcc -c gcc
編譯工具鏈:
預處理編譯器:cpp gcc -E hello.c -o hello.i 頭文件展開,宏替換,注釋去掉
編譯器:gcc gcc -S hello.i -o hello.s c文件變成匯編文件
匯編器:as gcc -c hello.s -o hello.o 匯編文件變成二進制文件
鏈接器:ld gcc hello.o -o hello 將函數庫中相應的代碼組合到目標文件中
直接編譯生成可執行文件
gcc hello.c -o hello
編譯時指定頭文件目錄-I
gcc hello.c -I ./include hello
編譯時指定宏,通常用於調試代碼-D
gcc hello.c -D DEBUG
在需要打印日志的代碼中加上下面的語句:
#ifdef DEBUG
printf("debug info");
#endif
編譯時對代碼進行優化-O3
gcc hello.c -o hello -O3
級別:
0 沒有優化
1 缺省值
3 優化級別最高
編譯時顯示告警信息-Wall
gcc hello.c -o hello -Wall
編譯時包含調試信息-g(gdb)
gcc hello.c -o hello -g
查看編譯版本
gcc -v
gcc --version
准備
目錄結構
myCalc
├── include
│ └── head.h
├── lib
│ └── libMyCalc.a
├── main.c
└── src
├── add.c
├── div.c
├── mul.c
├── sub.c
命名格式
lib
開頭。.a
結尾。
示例 : libMyCalc.a
描述
制作
得到與位置有關的*.o
cd ~/myClac/src
gcc *.c -c -I ../include
將生成的*.o
文件打包成靜態庫libMyCalc.a
ar rcs libMyCalc.a *.o
ar工具不包含在一gcc中。
參數:
r 將文件夾插入到靜態庫中。
c 創建靜態庫,不管庫是否存在。
s 寫入一個目標文件索引到庫中,或者更新一個存在的目標文件。
制作好以後移動到lib目錄中
mv libMyCalc.a ../lib
查看庫中的符號(函數)
nm libMyCalc.a
發布和使用靜態庫
include
和lib
目錄打包給用戶。使用
在main.c
中包含頭文件
#inlcude "head.h"
兩種編譯方式
gcc main.c lib/libMyCalc.a -I include -o myapp
gcc main.c -I include -L lib -l MyCalc -o myapp
執行myapp
./myapp
准備
目錄結構
myCalc
├── include
│ └── head.h
├── lib
│ └── libMyCalc.so
├── main.c
└── src
├── add.c
├── div.c
├── mul.c
├── sub.c
命名格式
lib
開頭。.so
結尾。
示例 : libMyCalc.so
描述
制作
生成與位置無關的*.o
cd ~/myClac/src
gcc -fPIC *.c -c -I ../include
將生成的*.o
文件打包成共享庫(動態庫)libMyCalc.so
gcc -shared -o libMyCalc.so *.o -I ../include
制作好以後移動到lib目錄中
mv libMyCalc.so ../lib
查看庫中的符號(函數)
nm libMyCalc.so
發布和使用靜態庫
include
和lib
目錄打包給用戶。使用
在main.c
中包含頭文件
#inlcude "head.h"
兩種編譯方式
gcc main.c lib/libMyCalc.so -I include -o myapp
gcc main.c -I include -L lib -l MyCalc -o myapp
執行myapp
./myapp
查看可執行文件夾所依賴的動態庫
ldd myapp
解決依賴的動態庫無法加載的問題
把libMyCalc.so
拷貝到/lib
目錄下(不推薦使用,容易與系統庫沖突)
cp lib/libMyCalc.so /lib
設置環境變量LD_LIBRARY_PATH(測試時使用)
export LD_LIBRARY_PATH=./lib 只對當前會話有效
設置環境變量LD_LIBRARY_PATH到~/.bashrc中(測試時使用)
vi ~/.bashrc
export LD_LIBRARY_PATH=/home/super/myCalc/lib 會話每次開啟就會生效
設置配置文件/etc/ld.so.conf
(推薦使用),重啟終端
編輯動態連接器的配置文件
vi /etc/ld.so.conf
動態庫的路徑寫到配置文件中
/home/super/myCalc/lib
更新動態庫
ldconfig -v
1.1、啟動gdb
gdb app
1.2、查看代碼
>>>(gdb) l #list
>>>(gdb) l 行號或函數名
>>>(gdb) l 文件名:行號或函數名
1.3、設置斷點
設置當前文件斷點
>>>(gdb) b #break
>>>(gdb) b 行號或函數名
>>>(gdb) b 文件名:行號或函數名
設置條件斷點
>>>(gdb) b 10 if value==19
刪除斷點
>>>(gdb) d 斷點的編號 #delete或del
1.4、查看設置的斷點
>>>(gdb) i b #info, 可以獲取斷點的編號,刪除斷點時用
1.5、開始執行gdb調試
>>>(gdb) start #只執行一步
>>>(gdb) c #continue,直接停在斷點的位置
>>>(gdb) run #有斷點會停在斷點處,沒有會直接跑完程序,較少用
1.6、單步調試
>>>(gdb) s #進入函數體內部
>>>(gdb) finish #從函數體內部跳出
>>>(gdb) n #不進入函數體內部
>>>(gdb) u #退出當前循環
1.7、查看變量的值
>>>(gdb) p print
1.8、查看變量的類型
>>>(gdb) ptype 變量名
1.9、設置變量的值
>>>(gdb) set var 變量=值
1.10、設置追蹤變量
>>>(gdb) display 變量 #設置追蹤變量
>>>(gdb) info display #獲取變量的編號
>>>(gdb) undisplay 編號 #取消追蹤變量
1.10、退出gdb調試
>>>(gdb) quit
makefile
Makefile
注:兩種任選其中一種,其他名稱不行。
規則中的三要素:目標、依賴、命令
makefile文件內容格式
目標:依賴文件
命令
makefile文件內容簡單示例
app:main.c add.c sub.c mul.c div.c
gcc main.c add.c sub.c mul.c div.c -o app
第二行必須有一個tab縮進。
子目標和終極目標
示例
#終極目標
app:main.o add.o sub.o div.o
gcc main.o add.o sub.o div.o -o app
#子目標
main.o:main.c
gcc -c main.c
#子目標
add.o:add.c
gcc -c add.c
#子目標
sub.o:sub.c
gcc -c sub.c
#子目標
mul.o:mul.c
gcc -c mul.c
#子目標
div.o:div.c
gcc -c div.c
好處
更新目標的原則
wildcard
:取得目錄下的所有文件patsubst
:將目標下的所有文件作替換示例
#自定義變量
src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
target=app
#終極目標
$(target):$(obj)
gcc $(obj) -o $(target)
#子目標
%.o:%.c
gcc -c $< -o $@
普通變量
foo = $(obj)
CC
: 默認值是cc
CPPFLAGS
: 預處理器需要的選項,如:-I
CFLAGS
: 編譯的時候使用的參數 -Wall -g -c
LDFLAGS
: 鏈接庫使用的選項 -L -l
CC = gcc
自動變量
$<
規則中的第一個依賴條件$@
規則中的目標$^
規則中的所有依賴條件模式規則
示例
#自定義變量
src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
target=app
#makefile維護的變量
CC = gcc
CPPFLAGS = -I
#終極目標
$(target):$(obj)
$(CC) $^ -o $@
#子目標
%.o:%.c
$(CC) -c $< -o $@
#偽目標
.PHONY:clean
clean:
#命令前面加-表示,如果命令執行失敗則忽略這個命令
-makir /release
rm -f $(obj) $(target)
C庫IO函數工作流程
虛擬內存地址空間
pcb與文件描述符
庫函數與系統函數之間的關系
CPU為什麼要使用虛擬地址空間與物理地址空間映射?解決了什麼問題?
查看幫助文檔
man 2 open
man 3 printf
errno
/usr/include/error.h
中
/usr/include/asm-generic/errno-base.h
/usr/include/asm-generic/errno.h
stdio.h
void perror(const char * s)
函數定義
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能
打開文件。
參數
pathname 文件路徑,如./hello.c
flags 文件訪問模式,O_RDONLY, O_WRONLY, O_RDWR, 更多見man 2 open
mode 文件權限設置,實際結果是mode & umask
返回值
返回一個文件描述fd,-1表示打開文件時發生錯誤。
示例
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int fd;
//打開文件
fd = open("hello.c", O_RDWR);
//打開文件,不存在則創建並設置權限為:755 & umask
fd = open("hello.c", O_RDWR | O_CREAT, 0755);
//打開文件,不存在則創建並設置權限為:755 & umask,另判斷文件是否存在
fd = open("hello.c", O_RDWR | O_CREAT | O_EXCL, 0755);
//打開文件並清空文件裡的內容
fd = open("hello.c", O_RDWR | O_TRUNC);
printf("fd = %d\n", fd);
//打開失敗則打印錯誤並退出程序
if(fd == -1)
{
perror("open file failure");
exit(1);
}
int ret = close(fd);
printf("ret = %d\n", ret);
//關閉失敗則打印錯誤並退出程序
if(ret == -1)
{
perror("close file failure");
exit(1);
}
return 0;
}
函數定義
ssize_t read(int fd, void *buf, size_t count);
功能
讀取文件。
參數
fd 文件描述符
buf 緩沖區
count 讀取多少字節數
返回值
有符號int型值
-1 表示讀文件失敗
0 表示文件讀完了
>0 表示讀取的字節數
函數定義
ssize_t write(int fd, const void *buf, size_t count);
功能
寫入文件。
參數
fd 文件描述符
buf 緩沖區
count 讀取多少字節數
返回值
有符號int型值
-1 表示寫文件失敗
0 表示什麼都沒寫
>0 表示寫了多少字節數
示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
//以只讀方式找開文件
int fd = open("english.txt", O_RDONLY);
if(fd == -1)
{
perror("open");
exit(1);
}
//以寫的方式找開文件,文件不存在則創建
int fd1 = open("newfile", O_CREAT | O_WRONLY, 0664);
//打開失敗,打印錯誤並退出程序
if(fd1 == -1)
{
perror("open1");
exit(1);
}
char buf[2048] = {0};
//每次讀取2048字節
int count = read(fd, buf, sizeof(buf));
//讀取失敗,打印錯誤並退出程序
if(count == -1)
{
perror("read");
exit(1);
}
while(count)
{
//寫入文件
int ret = write(fd1, buf, count);
printf("write bytes %d\n", ret);
//繼續讀取內容
count = read(fd, buf, sizeof(buf));
}
//關閉文件
close(fd);
close(fd1);
return 0;
}
函數定義
int close(int fd);
功能
關閉文件。
參數
fd 文件描述符
返回值
0 表示關閉成功
-1 表示關閉失敗
函數定義
off_t lseek(int fd, off_t offset, int whence);
功能
1、獲取文件大小。
2、移動文件指針。
3、文件拓展。
參數
fd 文件描述符
offset 文件指針偏移量
whence 來源,主要值有:SEEK_SET、SEEK_CUR、SEEK_END等
返回值
有符號int型值
-1 表示讀文件失敗
0 表示文件讀完了
>0 表示讀取的字節數
示例
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd = open("aa", O_RDWR);
if(fd == -1)
{
perror("open file");
exit(1);
}
int ret = lseek(fd, 0, SEEK_END);
printf("file length = %d\n", ret);
//文件拓展
ret = lseek(fd, 2000, SEEK_END);
printf("return value = %d\n", ret);
//實現文件拓展,需要再最後做一次寫操作
write(fd, "a", 1);
close(fd);
return 0;
}
函數定義
int stat(const char *pathname, struct stat *buf);
功能
獲取文件屬性(從inode上獲取)。
參數
pathname 文件名
buf 結構體指針stat
返回值
0 成功
-1 失敗
文件屬性
struct stat
{
dev_t st_dev; /* 文件的設備編號 */
ino_t st_ino; /* 節點 */
mode_t st_mode; /* 文件的類型和存取的權限 */
nlink_t st_nlink; /* 鏈接到該文件的硬鏈接數目,剛建立的文件值為1 */
uid_t st_uid; /* 用戶ID */
gid_t st_gid; /* 組ID */
dev_t st_rdev; /* (設備類型)若此文件為設備文件,則為其設備編號 */
off_t st_size; /* 文件字節數(文件大小) */
blksize_t st_blksize; /* 塊大小(文件系統的I/O, 緩沖區的大小) */
blkcnt_t st_blocks; /* 塊數 */
struct timespec st_atim; /* 最後一次訪問時間 */
struct timespec st_mtim; /* 最後一次修改時間 */
struct timespec st_ctim; /* 最後一次改變時間(屬性) */
}
特性
示例
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("./a.out filename\n");
exit(1);
}
struct stat st;
int ret = stat(argv[1], &st);
if(ret == -1)
{
perror("stat");
exit(1);
}
//存儲文件類型和訪問權限
char perms[11] = {0};
//判斷文件類型
switch(st.st_mode & S_IFMT)
{
case S_IFLNK:
perms[0] = 'l';
break;
case S_IFDIR:
perms[0] = 'd';
break;
case S_IFREG:
perms[0] = '-';
break;
case S_IFBLK:
perms[0] = 'b';
break;
case S_IFCHR:
perms[0] = 'c';
break;
case S_IFSOCK:
perms[0] = 's';
break;
case S_IFIFO:
perms[0] = 'p';
break;
default:
perms[0] = '?';
break;
}
//判斷文件的訪問權限
//文件所有者
perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';
perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';
//文件所屬組
perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';
perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';
//其他人
perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';
perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';
//硬鏈接計數
int linkNum = st.st_nlink;
//文件所有者
char * fileUser = getpwuid(st.st_uid)->pw_name;
//文件所屬組
char * fileGrp = getgrgid(st.st_gid)->gr_name;
//文件大小
int filesize = (int)st.st_size;
//修改時間
char * time = ctime(&st.st_mtime);
char mtime[512] = {0};
strncpy(mtime, time, strlen(time) - 1);
char buf[1024];
sprintf(buf, "%s %d %s %s %d %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);
printf("%s\n", buf);
return 0;
}
st_mode
其他人權限(0-2 bit)
S_IROTH 00004 讀權限
S_IWOTH 00002 寫權限
S_IXOTH 00001 執行權限
S_IRWXO 00007 掩碼
所屬組權限(3-5 bit)
S_IRGRP 00040 讀權限
S_IWGRP 00020 寫權限
S_IXGRP 00010 執行權限
S_IRWXG 00070 掩碼
文件所有者權限(6-8 bit)
S_IRUSR 00400 讀權限
S_IWUSR 00200 寫權限
S_IXUSR 00100 執行權限
S_IRWXU 00700 掩碼
特殊權限位(9-11 bit),很少用
S_ISUID 0004000 設置用戶ID
S_ISGID 0002000 設置組ID
S_ISVTX 0001000 黏住位
文件類型(12-15 bit)
S_IFSOCK 0140000 套接字
S_IFLNK 0120000 符號鏈接(軟鏈接)
S_IFREG 0100000 普通文件
S_IFBLK 0060000 塊設備
S_IFDIR 0040000 目錄
S_IFCHR 0020000 字符設備
S_IFIFO 0010000 管道
S_IFMT 0170000 掩碼
函數定義
int access(const char *pathname, int mode);
功能
測試指定文件是否擁有某種權限。
參數
pathname 文件名
mode 權限類別
R_OK 是否有讀權限
W_OK 是否有寫權限
X_OK 是否有執行權限
F_OK 測試一個文件是否存在
返回值
0 所有欲查核的權限都通過了檢查
-1 有權限被禁止
示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("access filename\n");
exit(1);
}
int ret = access(argv[1], W_OK);
if(ret == -1)
{
perror("access");
exit(1);
}
printf("you can write this file.\n");
return 0;
}
函數定義
int chmod(const char *pathname, mode_t mode);
功能
改變文件的權限
參數
pathname 文件名
mode 權限,必須是一個8進制數字,轉換用strtol函數
返回值
0 改變成功
-1 失敗
示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("chmod filename\n");
exit(1);
}
int ret = chmod(argv[1], 0755);
if(ret == -1)
{
perror("chmod");
exit(1);
}
return 0;
}
函數定義
int chown(const char *pathname, uid_t owner, gid_t group);
功能
改變文件的所有者
參數
pathname 文件名
owner 文件所有者ID
group 文件所屬組ID
查看UID和GID:/etc/passwd
返回值
0 成功
-1 失敗
示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("chown filename\n");
exit(1);
}
int ret = chown(argv[1], 116, 125);
if(ret == -1)
{
perror("chown");
exit(1);
}
return 0;
}
函數定義
int truncate(const char *path, off_t length);
功能
將參數path指定的文件大小改為參數length指定的大小。如果原來的文件大小比參數length大,則超過部分會被刪去。
參數
path 文件路徑
length 指定文件的大小
返回值
0 成功
-1 失敗
link函數
函數定義
int link(const char *oldpath, const char *newpath);
功能
創建一個硬鏈接。
symlink函數
函數定義
int symlink(const char *target, const char *linkpath);
功能
創建一個軟鏈接。
readlink函數
函數定義
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
功能
讀軟鏈接對應的文件名,而不是讀內容。
示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("readlink filename\n");
exit(1);
}
char buf[512];
int ret = readlink(argv[1], buf, sizeof(buf));
if(ret == -1)
{
perror("readlink");
exit(1);
}
buf[ret] = 0;
printf("buf = %s\n", buf);
return 0;
}
unlink函數
函數定義
int unlink(const char *pathname);
功能
刪除一個文件的目錄並減少它的鏈接數,若成功則返回0,否則返回-1,錯誤原因存於errno。
如果想調用這個函數來成功刪除文件,你就必須擁有這個文件的所屬目錄的寫和執行權限。
使用
如果是符號鏈接,刪除符號鏈接。
如果是硬鏈接,硬鏈接數減1,,當減為0時,釋放數據塊和inode。
如果文件硬鏈接數為0,但有進程已打開該文件,並持有文件描述符,則等該進程關閉該文件時,kernel才真正去刪除該文件。
示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
int main()
{
int fd = open("tempfile", O_CREAT | O_RDWR, 0664);
if(fd == -1)
{
perror("open");
exit(1);
}
//刪除臨時文件
int ret = unlink("tempfile");
//write file
write(fd, "hello\n", 5);
//重置文件指針
lssek(fd, 0, SEEK_SET);
//read file
char buf[24] = {0};
int len = read(fd, buf, sizeof(buf));
//將讀出的內容寫在屏幕上
write(1, buf, len);
//close file
close(fd);
return 0;
}
函數定義
int rename(const char *oldpath, const char *newpath);
功能
文件重命名。
函數定義
int chdir(const char *path);
功能
修改當前進程的路徑。
函數定義
char *getcwd(char *buf, size_t size);
功能
獲取當前進程工作目錄。
函數定義
int mkdir(const char *pathname, mode_t mode);
功能
創建目錄。
注意:創建的目錄需要有執行權限,否則無法進入目錄。
函數定義
int rmdir(const char *pathname);
功能
刪除一個空目錄。
函數定義
DIR *opendir(const char *name);
功能
打開一個目錄。
函數定義
struct dirent *readdir(DIR *dirp);
功能
讀目錄。
返回值
struct dirent {
ino_t d_ino; /* 此目錄進入點的inode */
off_t d_off; /* 目錄文件開頭至此目錄進入點的位移 */
unsigned short d_reclen; /* d_name的長度,不包含NULL字符 */
unsigned char d_type; /* d_name所指的文件類型 */
char d_name[256]; /* 文件名 */
};
d_type:
DT_BLK This is a block device.
DT_CHR This is a character device.
DT_DIR This is a directory.
DT_FIFO This is a named pipe (FIFO).
DT_LNK This is a symbolic link.
DT_REG This is a regular file.
DT_SOCK This is a UNIX domain socket.
DT_UNKNOWN The file type is unknown.
-D_BSD_SOURCE 編譯時添加宏定義
函數定義
int closedir(DIR *dirp);
功能
關閉目錄。
示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
int get_file_count(char * root)
{
DIR * dir = NULL;
dir = opendir(root);
if(dir == NULL)
{
perror("opendir");
exit(1);
}
struct dirent * ptr = NULL;
char path[1024] = {0};
int total = 0;
while(ptr = readdir(dir) != NULL)
{
//過濾.和..
if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
{
continue;
}
//如果是目錄
if(ptr->d_type == DT_DIR)
{
sprintf(path, "%s/%s", root, ptr->d_name);
total += getFileNum(path);
}
//如果是文件
if(ptr->d_type == DT_REG)
{
total++;
}
}
closedir(dir);
return total;
}
int main(int argc, char * argv[])
{
if(argc < 2)
{
printf("./a.out dir\n");
exit(1);
}
int total = get_file_count(argv[1]);
printf("%s has file numbers %d\n", argv[1], total);
return 0;
}
函數定義
int fcntl(int fd, int cmd, ... /* arg */ );
功能
改變已經打開的文件的屬性。
1、復制一個現有的描述符 -- cmd
F_DUPFD
2、獲取/設置文件描述符標記 -- cmd
F_GETFD
F_SETFD
3、獲取/設置文件狀態標記 -- cmd
F_GETFL
O_RDONLY 只讀打開
O_WRONLY 只寫打開
O_RDWR 讀寫打開
O_EXEC 執行打開
O_SEARCH 搜索打開目錄
O_APPEND 追加寫
O_NONBLOCK 非阻塞模式
F_SETFL, 可更改的幾個標識
O_APPEND
O_NONBLOCK
4、獲取/設置異步I/O所有權 -- cmd
F_GETOWN
F_SETOWN
5、獲取/設置記錄鎖 -- cmd
F_GETLK
F_SETLK
F_SETLKW
示例
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char * argv[])
{
int fd;
int flag;
//測試字符串
char * p = "we are family!";
cahr * q = "yes, man.";
//只寫的方式找開文件
fd = open("test.txt", O_WRONLY);
if(fd == -1)
{
perror("open");
exit(1);
}
//輸入新的內容,該部分會覆蓋原來舊的內容
if(write(fd, p, strlen(p)) == -1)
{
perror("write");
exit(1);
}
//使用F_GETFL命令得到文件狀態標志
flag = fcntl(fd, F_GETFL, 0);
if(flag == -1)
{
perror("fcntl");
exit(1);
}
//將文件狀態標志添加“追加寫”選項
flag |= O_APPEND;
//將文件狀態修改為追加寫
if(fcntl(fd, F_SETFL, flag) == -1)
{
perror("fcntl -- append write");
exit(1);
}
//再次輸入新內容,該內容會追加到舊內容的後面
if(write(fd, q, strlen(q)) == -1)
{
perror("write again");
exit(1);
}
//關閉文件
close(fd);
return 0;
}
函數定義
int dup(int oldfd);
int dup2(int oldfd, int newfd);
功能
復制現有的文件描述符。
返回值
dup返回的是文件描述符中沒有被占用的最小的文件描述符
注意事項
dup2兩種情況:
1、old --> new, 如果new是一個被打開的文件描述符,在拷貝前先關掉new。
2、old和new是同一個文件描述符,不會關掉new,直接返回old。
dup示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("a.txt", O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
printf("file open fd = %d\n", fd);
//找到進程文件描述表中==第一個==可用的文件描述符
//將參數指定的文件復制到該描述符後,返回這個描述符
int ret = dup(fd);
if(ret == -1)
{
perror("dup");
exit(1);
}
printf("dup fd = %d\n", ret);
char * buf = "你是猴子派來的救兵嗎???\n";
char * buf1 = "你大爺的,我是程序猿!!!\n";
write(fd, buf, strlen(buf));
write(ret, buf1, strlen(buf1));
close(fd);
return 0;
}
dup2示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd = open("english.txt", O_RDWR);
if(fd == -1)
{
perror("open");
exit(1);
}
int fd1 = open("a.txt", O_RDWR);
if(fd1 == -1)
{
perror("open");
exit(1);
}
printf("file open fd = %d\n", fd);
printf("file open fd1 = %d\n", fd1);
//調用dup2後,fd1和fd同時指向了a.txt
int ret = dup2(fd1, fd);
if(ret == -1)
{
perror("dup2");
exit(1);
}
printf("current fd = %d\n", ret);
char * buf = "主要看氣質^_^!!!!!!!!!!!\n";
write(fd, buf, strlen(buf));
write(fd1, "hello, world!", 13);
close(fd);
close(fd1);
return 0;
}
解決gcc編譯過程中c99語法報錯的問題
alias gcc='gcc -std=gnu99'
索引節點inode:保存的其實是實際的數據的一些信息,這些信息稱為“元數據”(也就是對文件屬性的描述)。例如:文件大小,設備標識符,用戶標識符,用戶組標識符,文件模式,擴展屬性,文件讀取或修改的時間戳,鏈接數量,指向存儲內容的磁盤區塊的指針,文件分類等等。(注意數據分成:元數據+數據本身)
注意inode怎樣生成的:每個inode節點的大小,一般是128字節或256字節。inode節點的總數,在格式化時就給定(現代OS可以動態變化),一般每2KB就設置一個inode。一般文件系統中很少有文件小於2KB的,所以預定按照2KB分,一般inode是用不完的。所以inode在文件系統安裝的時候會有一個默認數量,後期會根據實際的需要發生變化。
注意inode號:inode號是唯一的,表示不同的文件。其實在Linux內部的時候,訪問文件都是通過inode號來進行的,所謂文件名僅僅是給用戶容易使用的。當我們打開一個文件的時候,首先,系統找到這個文件名對應的inode號;然後通過inode號,得到inode信息,最後,由inode找到文件數據所在的block,現在可以處理文件數據了。
inode與文件的關系:當創建一個文件的時候,就給文件分配了一個inode。一個inode只對應一個實際文件,一個文件也會只有一個inode。inode最大數量就是文件的最大數量。