本篇涵蓋課程《Linux程序設計》考點,分爲三部分,如下:
第一部分:Linux歷史、基礎知識、shell、Linux編程等內容
第二部分:部分常見的系統調用和I/O庫函數
第三部分:部分編程複習題,包括了shell編程和c編程
第一部分——複習總綱
一、基礎
1.Linux是誰開發的、是用什麼語言開發的、Unix的開源精神——這些
1991年Linus Torvalds(林納斯.託瓦茲)寫出Linux內核的第一個版本;
1992年第一個發行版出現;
GNU/Linux系統=Linux內核+GNU;發行版有:Red Hat,Debain,Suse,Mandrake,Redflag...
GNU:即革奴計劃,由理查德.斯托曼發起,目標是創建一套完全自由的操作系統;
其他:EMACS、Copyleft
2.分區的基本知識(今年不考?)
瞭解的話直接看筆記就ok;
3.文件系統
操作系統中負責存取和管理文件的部分;
文件和文件的某些元素的集合,它爲鏈接到文件的文件序列號提供了一個命名空間;
1)Linux文件系統類型:VFS / EXT2,EXT3,FAT32
VFS:virtual file system,虛擬文件系統。一個位於異構文件系統之上的軟件粘合層,爲訪問文件系統的系統調用提供一個統一的抽象接口;它的作用就是採用標準的Unix調用讀寫位於不同物理介質上的不同文件系統。
2)Linux文件夾結構(常用結構要知道,如boot,root,home,dev這些)
在Linux中,所有的文件和目錄都被組織成一個根節點開始的倒置的樹狀結構;
/bin:binary,存放最常使用的命令;
/boot:啓動Linux時使用的一些核心文件,包括一些連接文件和鏡像文件;
/dev:device,存放Linux的外部設備;在Linux中,訪問設備和訪問文件的方式是相同的;
/etc:存放所有的系統管理所需要的配置文件和子目錄;
/home:用戶的主目錄
/lib:存放着系統最基本的動態連接共享庫;
/media:Linux系統會自動識別一些設備,如U盤、光驅等,識別後,Linux會把被識別的設備掛載到這個目錄下;
/mnt:爲了讓用戶臨時掛載別的文件系統用,如可以將光驅掛載在/mnt上,然後進入該目錄就可以查看光驅裏的內容了;
/root:系統管理員的用戶主目錄;
/tmp:存放一些臨時文件
/usr:用戶的很多應用程序和文件
/var:存放在不斷擴充着的東西,習慣性將那些經常被修改的文件放到這個目錄下, 包括各種日誌文件;
3)啓動過程(理解即可,不用考)
BIOS--MBR--Boot loader--Init process
BIOS檢查設備、加載並啓動MBR----MBR中的bootloader(常見有LILO和GRUB兩種)加載和啓動Linux內核--現在控制權就交給內核了。
4.安裝軟件的方式(簡單看一下,apt-get要知道,其他不用)
apt-get command
*:apt-get是Debian、Ubuntu發行版的包管理工具,與Redhat中yum工具類似;一般需要root權限:
apt-cache search string:在軟件包列表中搜索字符串
apt-get install packagename:安裝一個新的軟件包
apt-get update; apt-get remove packagename; apt-get remove --purge packagename; apt-get autoremove packagename; apt-get autoclean;.....
apt屬於Debian系,rpm屬於Redhat系;
5.命令:常用的命令
passwd:改變密碼;
mkpasswd:生成隨機密碼;
date:顯示當前日期和時間;
cal:顯示日曆;
who/finger:顯示當前系統的active用戶(finger需要另外安裝,如在Ubuntu中sudo apt install finger)
clear:清空屏幕;
echo:直接輸出echo後面的文本;
write:向指定登錄用戶終端發送消息;
wall:向系統當前所有打開的終端發送消息;
talk:和指定用戶聊天;
msg:用於設置其他用戶是否可以直接向當前用戶終端發送消息,msg y表示允許,msg n表示禁止;
6.文件類型——七種
1)常規文件:文本或code數據,沒有特殊的內部結構;
2)字符特殊文件:見3)
3)塊特殊文件:特殊文件代表硬件或邏輯設備,通常在/dev中;字符特殊文件通常是裝置文件中的串行端口設備,如鍵盤、鼠標等一次性讀取設備;塊特殊文件表示裝置文件中的可供存儲的接口設備(可隨機存取裝置);
4)socket,即套接口文件/數據接口文件:socket,又名“套接口”,用於描述IP地址和端口,應用程序是通過套接字向網絡發送請求或者應答網絡請求;例如啓動mysql服務器時會產生一個mysql.sock文件;
5)符號鏈接文件:symbolic link,類似Windows中的快捷方式
6)目錄:內容的表;目錄內文件的列表;
7)管道文件:fifo
7.基本命令——文件系統相關(過一遍)
1)目錄
pwd:顯示當前目錄
cd:切換目錄
mkdir:創建目錄;options:-m<權限>,創建目錄時同時設置權限;-p:一併建立上層目錄(如果不存在);
rmdir:刪除目錄(最好是空目錄,否則用-r遞歸刪除其下的子目錄和文件——但是這樣做有危險;即先用rm刪除目標目錄下的文件,再用rmdir刪除這個目錄)
ls:以列表形式顯示目錄內容,有-l,-a,-R等選項——這個命令很重要,參考8;
2)文件
touch:更新文件權限或最後修改時間(創建文件同樣使用這個命令,格式爲:touch filename)
cp:複製文件;cp [options] 源文件 目標文件;options:-r/R遞歸、-l對源文件建立硬鏈接而非複製文件;-s建立符號鏈接;
mv:移動和重命名文件/目錄; mv source target
ln:鏈接文件;默認創建硬鏈接,使用-s選項創建符號鏈接(軟鏈接);------參照8
rm:刪除文件
cat:輸出文件內容
more/less:逐頁顯示文件;more以全屏幕的方式按頁顯示文本文件的內容;less與more類似,不同的是more只能往前(即往下)翻頁,而less既允許用戶向前,也允許向後瀏覽文件;
7.硬鏈接和符號鏈接:
1)爲文件創建硬鏈接:ln,但不能爲目錄創建硬鏈接;創建硬鏈接後,文件的Inode會被多個文件項公用。文件的硬鏈接數可以在ls -l後的列表的第二列看到,無額外鏈接的文件的連接數爲1
硬鏈接可以理解爲多個文件指向同一個物理地址,所以不能對目錄做硬鏈接,也不可以在不同的文件系統之間做硬鏈接;
2)軟鏈接/符號鏈接:ln -s,將一個路徑名鏈接到一個文件。這些創建出來的軟鏈接文件是一種特別類型的文件,實際上它只是一個文本文件,其中包含了鏈接時的源文件的路徑名,而源文件纔是實際包含所有數據的文件;軟鏈接產生的這個文件在ls -l中第一列會顯示一個l,即表示符號鏈接文件(而硬鏈接的第一列依然是-,即文件);
軟鏈接可以理解爲快捷方式(也就是通過它飛快地找到源文件,而不是直接去找物理地址),它本身確實是一個新的文件,它的大小就是符號鏈接中路徑的字節數;所以它具有和源文件不同的inode號,而硬鏈接並沒有建立新文件;此外,軟鏈接可以對目錄進行,也可以在不同的文件系統之間做符號鏈接;
注:如果遞歸地做軟鏈接,ln -s產生的文件會全部指向源文件(即真正的文件);而cp -s複製產生的符號鏈接文件只會指向上一個文件(可能是符號鏈接,也可能就是文件,具體要看源文件的類型)
軟鏈接時推薦源文件使用絕對路徑,如果使用相對路徑,則軟鏈接文件(即目標文件)必須與源文件在同一級目錄下;
8.文件屬性(ls -l,很重要噠)
ls -l: 文件類型 權限 硬鏈接數目 所有者 用戶組 文件大小 修改時間 文件
Example:
-rw-------. 3 zfh zfh 2722 1月 16 19:26 nohup.html
-rwxrw-r--. 1 zfh zfh 672 1月 16 18:43 OnlineExam項目說明文檔.html
lrwxrwxrwx. 1 zfh zfh 7 4月 8 21:39 s.sql -> ./b.sql
-rw-rw-r--. 1 zfh zfh 25 4月 8 11:51 test.sh
-rw-------. 3 zfh zfh 2722 1月 16 19:26 x2.html
如上,解釋如下:
1)第一列,第一個符號表示文件類型,-表示文件,d表示目錄,l表示符號鏈接文件,b表示塊特殊文件,c表示字符特殊文件,其他的還有socket文件(s)和管道文件(p)——具體參照7;
後面的九個字符依次表示文件所有者、所有者所在用戶組、其他用戶對這個文件的權限,rwx分別表示read,write,execute,如果是-則表示沒有這項權限;
2)第二列,硬鏈接的數量,如果沒有硬鏈接,默認是1
3)第三列,文件所有者
4)第四列,文件所有者所在的用戶組
5)第五列,文件大小,單位是字節,如果是特殊文件(即設備),那麼這一列指主設備號(第六列就會是次設備號),如果是目錄,那麼指目錄大小(目錄內的inode列表所佔空間,而不是裏面所有文件的總和大小)
6)第六列,文件的創建日期或最近修改日期(centos中依次是月、日、時間,Ubuntu中依次是)
7)第七列,文件名
9.文件屬性修改(chmod, chown, chgrp)
對於8中的文件屬性,如權限、用戶、用戶組,依次使用chmod, chown, chgrp命令修改;
1)更改文件權限:chmod,兩種方式——數字或符號;
對於符號,chmod u/g/o/a +/-/= r/w/x 文件或目錄;其中u表示user,g表示group,o表示others,a表示all;(注意:用戶、操作符、權限必須要連起來寫)
對於數字,chmod [-R] xyz 文件或目錄,-R表示遞歸,xyz分別由三組權限屬性值對應的數字累加而成,其中r=4,w=2,x=1,如chmod 761 f.txt,就表示f.txt的權限被改成了rwx rw- --x
2)更改文件所有者或組:chown [-R] user:[group] filename
3)更改文件所在組:chgrp [-R] group filename;
chown和chgrp需要在root權限下執行;且上面的user和group既可以是名字也可以是ID
10.umask命令與默認權限
umask命令用來設置限制新建文件權限的掩碼。當新文件創建時,其最初的權限由默認權限與umask掩碼共同決定。文件的默認權限是666,即rw-rw-rw-,目錄的默認權限是777,即rwxrwxrwx。而在此基礎之上,umask設置的掩碼將會從以上權限中把相應位置的權限拿走(即刪去指定位的權限)
如umask設置的掩碼爲022,那麼新文件的權限上用戶組和其他用戶的write權限就會被拿走,也就是文件權限變成了644,即rw-r-r-,而新建文件夾的權限也變成了rwxr-xr-x,即755.
再umask設置的掩碼爲245,即分別拿走屬主、用戶組、其他用戶的寫、讀、讀和執行權限,也就是說新建文件權限變成r---w--w-,即422,而文件夾的權限變成了r-x-wx--w-,即532.
綜上,umask掩碼的作用即是“拿走”相應位置上的權限(如果有的話——總之,這個位置沒有權限了。)
umask語法:
umask,顯示當前權限掩碼,如0245;umask -S,以符號方式顯示當前權限掩碼,如u=rx,g=wx,o=w
(數字表示的是刪掉的權限,符號表示的是剩下的權限)
11.進程概念(進程的信息不考、開始和結束進程不考)
進程是一個任務,是一個正在執行的程序實例。它由執行程序、它的當前值、狀態信息以及通過操作系統管理此進程執行情況的資源組成;
從更小的角度看,進程是由一個地址空間和在這個地址空間內執行的一個或多個線程,以及這些線程所需要的系統資源組成;
所有的進程都是由其他進程啓動的(除了init,它是由Linux內核啓動的),這是一個樹層次結構,可以用pstree查看;
12.內核和外圍程序構成(要理解)
shell是用戶和操作系統的接口;
二、命令
1.重定向和管道(重點;還有,用shell怎麼實現重定向?;管道要理解)
1)重定向:Linux重定向是指修改原來默認的一些東西,對原來系統命令的默認執行方式進行改變,比如說將原本會在顯示器上顯示的輸出輸出到某一文件中。
I/O重定向通常與FD(File Descriptor)有關,shell的FD通常爲10個,即0-9,常用的有三個,0(stdin,標準輸入)、1(stdout,標準輸出)、2(stderr,標準錯誤輸出),默認與keyborad、monitor有關;
用<來改變讀進的數據信道(stdin),使之從指定的檔案讀進;用>來改變送出的數據信道(stdout,stderr),使之輸出到指定的檔案;
0是<的默認值,因此<與0<是一樣的;同理,>與1>是一樣的;
在IO重定向中,stdout與stderr的管道會先準備好,纔會從stdin讀進資料;
基本IO:
cmd > file 把stdout重定向到file文件中;
cmd > > file 把stdout重定向到file文件中(追加);
cmd 1> file 把stdout重定向到file文件中;
cmd > file 2>&1 把stdout與stderr一起重定向到file文件中;
cmd 2> file 把stderr重定向到file文件中;
cmd 2>> file 把stderr重定向到file文件中(追加);
cmd >> file 2>&1 把stdout與stderr一起重定向到file文件中(追加);
cmd < file >file2:cmd命令以file文件作爲stdin,以file2文件作爲stdout;
cat <> file 以讀寫的方式打開file;
cmd < file:命令以file文件作爲stdin;
cmd << delimiter Here document,從stdin中讀入,直到遇到delimiter分界符;
2)管道: 管道"|"(pipe line):上一個命令的stdout接到下一個命令的stdin;
一個進程的輸出作爲另一個進程的輸入;
例如:ls | wc -l ; ls | grep 'txt';
2.PATH環境變量:echo/env/set要知道
1)概念:環境變量是在操作系統中一個具有特定名字的對象,它 包含了一個或者多個應用程序所將使用到的信息。環境變量相對於給系統或用戶應用程序設置的一些變量。比如在Windows或DOS操作系統中的path變量,當要求系統運行一個程序而沒有告訴它程序所在的完整路徑時,系統除了在當前目錄下面尋找此程序外,還應到path中指定的路徑去找;
2)命令——查看和設置環境變量:
echo:使用echo查看單個環境變量,如:echo $PATH,輸出:
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
env:使用env查看所有環境變量
set:使用set查看所有本地定義的環境變量(看起來像是一個個函數)
shell中:在shell中使用【export 變量名=$環境變量名】,可以自定義shell變量,它的值就是環境變量的值。該變量只在當前的shell或其子shell中有效,shell關閉了,變量也就失效了,例如:
code:
#!/bin/bash
pa=$PATH
echo "path=$pa"
execute,輸出:path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
3.三個神器——find、sed、grep(基本概念知道就行,sed後面是正則表達式,大概是幹嘛的,grep是幹嘛的)、正則表達式不考
1)find:用來在指定目錄下查找文件,參數是查找文件的起始目錄,根據文件或正則表達式進行匹配;
具體參照:https://man.linuxde.net/find
2)sed:流編輯器,處理時,把當前處理的行存儲在臨時緩衝區中,稱爲“模式空間”(pattern space),接着用sed命令處理緩衝區的內容,然後輸出到屏幕,接着處理下一行,直到文件末尾;文件的內容並未改變,除非使用重定向存儲輸出;sed主要用於自動編輯一個或多個文件;簡化對文件的反覆操作;編寫轉換程序等;
具體參照:https://man.linuxde.net/sed
3)grep:global search regular expression(RE) and print out the line,全面搜索正則表達式並把行打印出來,是一種強大的文本搜索工具,它能使用正則表達式搜索文件,並把匹配的行打印出來;
常見用法:在文件中搜索一個單詞,命令會返回一個包含“match_pattern”的文本行:
grep match_pattern file_name / grep “match_pattern” file_name
也可以使用管道,cat file_name | grep “match_pattern”,cat的參數也可以是一串字符串,這樣後面的grep就是在這個字符串中尋找匹配;
參照:http://man.linuxde.net/grep
三、shell編程(一定要掌握,有編程題)
A command interpreter and programming environment.
shell是用戶與操作系統之間的接口;
1.shell不同的類型(瞭解)
2.執行腳本的方法:三種,要看!
如腳本x.sh
1)作爲可執行程序:
chmod +x ./x.sh 使腳本具有可執行權限
./x.sh 執行腳本
2)作爲解釋器參數
sh x.sh 或 /bin/sh x.sh
注:這種方式不需要在腳本第一行指定解釋器參數,即#!/bin/bash
3)source x.sh 或 . x.sh
3.用戶變量、環境變量(不單獨考,可能有path和home):參數變量和內部變量要知道
用戶變量:shell中自定義的變量
環境變量:操作系統變量,爲OS或應用程序服務,如$PATH;shell也可以自定義;
參數變量:運行shell時傳入的參數,以及額外產生的一些變量
內部變量:shell中的用戶變量只能在當前shell中使用,即內部變量,而不能被shell運行的其他命令或shell程序使用,此時使用export命令可以將局部變量/內部變量編程全局變量(也可以稱爲環境變量,在shell運行結束後失效);
三種定義全局變量/環境變量的方式:
1)export name=value
2)name=value;export name
3)declare -x name=value
4.read shell不會考怎麼用、引號的用法要清楚
1)shell中的引號:
單引號:單引號中的任何字符都會原樣輸出,轉義失敗,變量也是無效的;
雙引號:裏面可以有變量,也可以出現轉義字符(即$ `` \將分別被bash解釋)
2)shell用戶變量:
字符串:${#name}得到長度;${name:2:3}從第三個字符開始提取三個字符;`expr index "${name}" objectStr`在name中查找objectStr子字符串;x\
數組:
#!/bin/bash
array=(v0 v1 v2 "v3")
array[1000]="m_number"
#print all elements
echo ${array[@]}
echo ${array[*]}
#print array length
echo ${#array[@]}
echo ${#array[*]}
#print a element
echo ${array[1000]}
#print length of a element
echo ${#array[2]} 輸出: [zfh@localhost ss]$ ./x.sh
v0 v1 v2 v3 m_number
v0 v1 v2 v3 m_number
5
5
m_number
2
3)運算符:
算術運算 `expr $a + $b ` (+、-、\* 、/ 、%)
條件表達式:用方括號[]包含在內,兩端需要留空格;如
[ $a == $b ]
關係運算:[ $a -gt $b ] (-eq -gt -ne -lg -ge -le)
布爾運算:[ !false ]、[ true -o false]、 [true -a true]
邏輯運算:[[ true && false ]]、 [ true || false ]
字符串運算:[ $a = $b ](!= -z -n),還有[ $a ]檢測字符串a是否爲空
文件測試運算:[ -b $file ]是否爲塊設備文件(-c, -d, -f, -p, -r , -w, -x, -s, -e)
注:test命令可以起到和方括號類似的作用,如test $a -eq $b
4)echo命令
read命令:讀取輸入;
read選項:-p表示後面的輸出提示字符,不會換行;-n後面的數字表示輸入的字符長度限制;-t限時,-s隱藏輸入內容;
5.要看的:參數、條件、case循環、雜項命令(break、continue、exit….)、函數(好像不考,建議一看)、算術擴展和參數擴展(好好看一看)
1)if、for、while、util、case
注意:
let "x++"命令,是bash中用於計算的工具,使用變量不需要$
read命令:如read FILM,讀取鍵盤輸入並命名爲FILM變量
2)shell函數:稍微看了一遍
3)shell文件包含:包含外部的腳本用於封裝公用的代碼
. filename #注意點號和filename之間有一個空格
或者:source filename
4)雜項命令:
參照:http://blog.163.com/bobile45@126/blog/static/96061992201311712658570/
exit n:以退出碼n退出腳本運行;即在exit位置退出當前shell,退出碼爲n,退出後可以使用$?來獲得上一個命令的退出碼。退出碼:0表示成功,非0表示失敗,2表示用法不當,127表示命令沒有找到,126表示不是可執行的,>=128信號產生;
export:定義環境變量(參照上面三種定義環境變量的方式);在一個腳本定義了環境變量後,如果在另一個腳本中運行這個腳本,那麼兩個腳本都可以使用這個被定義的環境變量,直至腳本運行結束;
set:爲shell設置參數變量(目前看只能set value,然後$1的值就會變成value)
unset:從環境中刪除變量或函數(如unset name,那麼字符串變量name就被刪除了)
trap:trap "command" exit;退出時執行command命令
":":冒號,空命令
".":點號或source:在當前shell中執行命令——如執行其他腳本,比如在x.sh中寫source test.sh,就會在執行到這一行的時候去執行test.sh腳本;
5)捕獲命令輸出:即執行命令,然後通過shell去獲得命令執行的結果
$(command) 或 `command`
如:echo $(ls) 或 echo `ls`
6)算術擴展——即shell算術運算和條件判斷的另一種寫法
$((...))
如:x=$(($x+1)),等價於高級語言裏的x++
又如:(( $x>= 2 )),等價於[ $x -ge 2 ]
注意:雙層括號與方括號不一樣之處在於中間不需要空格來分割;此外,下面這個示例也可以用`expr ...`的形式;
7)參數擴展——即針對參數進行一些操作
參數擴展 描述
${param:-default} 如果param爲空,就設置它爲default的值
${#param} 給出param的長度
${param%word} 從param的尾部開始刪除與word匹配的最小部分,然後返回剩餘部分
${param%%word} 從param的尾部開始刪除與word匹配的最長部分,然後返回剩餘部分
${param#word} 從param的頭部開始刪除與word匹配的最小部分,然後返回剩餘部分
${param##word} 從param的頭部開始刪除與word匹配的最長部分,然後返回剩餘部分
8)即時文檔——輸入輸出重定向的一種,理解爲將shell中的變量作爲命令的輸入;
command << delimiter
document
delimiter
例如:
#!/bin/bash
cat >> file.txt << !fs!
Hello, this is a here document.
!fs!
它將中間的文本作爲cat命令的輸入,然後將cat命令的輸出重定向到了file.txt中;
總結一下,概括來說呢,可以把Linux的命令都看成是shell的內容(因爲它們都可以在shell裏面使用),然後通過輸入輸出重定向、函數、流程控制等等使得shell變成了一個編程語言;
四、程序部分
1.編程題——記得要看作業
2.文件系統的編程——先了解文件系統,再看這裏的編程
3.基本概念瞭解:c庫在用戶態
4.gcc gdb(gdb不考)
5.編譯鏈接的過程(看一下,具體的過程不會考)
其他:
預處理;
爲什麼要鏈接?
靜態庫與動態庫、靜態鏈接方式與動態鏈接方式
6.gcc的參數(看一下)、擴展名不看
1) gcc -c 編譯
gcc 鏈接 或 編譯+鏈接
g++ (C++對應的命令,其實是換了前端)
2)gcc [options] [filename]
-E:預處理
-S:預處理+編譯
-c:預處理+編譯+彙編(不鏈接)
-o output_file:指定輸出文件名
-g:調用調試工具必須的符號信息
-O/On:在程序編譯、鏈接過程中進行優化處理
-Wall:顯示所有的警告信息
-Idir:指定額外的頭文件搜索路徑(這裏是i的大寫)
-Ldir:指定額外的庫文件搜索路徑(這裏是L的大寫)
-lname:鏈接時搜索指定的庫文件(這裏是L的小寫)
-DMACRO[=DEFN]:定義MACRO宏
補充:
創建靜態庫(.a):g++ -c StaticMath.cpp,生成目標文件StaticMath.o,然後ar打包ar -crv libstaticmath.a StaticMath.o,這樣就生成了靜態庫libstaticmath.a
創建動態庫((.so):g++ -fPIC -c DynamicMath.cpp生成目標文件,然後g++ -shared -o libdynmath.so,這樣就生成了動態庫libdynmath.so,注意Linux動態庫是libxxx.so形式;
7.Makefile(原理,給一個Makefile要能看得懂)
1)makefile描述模塊間的依賴關係,定義了整個工程的編譯規則,實現了自動化編譯(make命令執行Makefile腳本)
make命令根據makefile對程序進行管理和維護;make判斷被維護文件的時序關係;
參照:https://blog.csdn.net/haoel/article/details/2886/
2)makefile語法:
target ... : prerequisites...
command
.....
target是目標文件,可以是Object file,也可以是可執行文件;prerequisites是生成target所需要的文件(源文件、目標文件、頭文件);command是make要執行的命令,就是使用上面的prerequisites文件生成target的。
實際上就是文件之間的依賴關係,target這一個或多個目標文件依賴於prerequisites中的文件,其中生成規則在command中。說白一點就是:prerequisites中如果有一個以上的文件比target文件要新的話,command所定義的命令就會被執行;
舉例:
hello : main.o kbd.o
gcc -o hello main.o kbd.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
clean :
rm edit main.o kbd.o
注意:command之前是一個Tab鍵;
8.多目標(不考)、使用函數(不考)、軟件設計原則(不考)
9.GCC編譯器爲啥要分前端後端?
如下圖,將編譯器分爲前端和後端,前端的功能在於產生一個可以讓後端處理的語法樹,後端翻譯語法樹成爲GCC的暫存器轉換語言(RTL),這樣使得前後端獨立,使得後端無須考慮多種源語言和目標語言而專注於其他工作,消除了重複開發的工作量,提高了編譯系統的開發效率;
五、程序部分2——文件系統
1.文件、文件系統
文件:文件是可以讀寫、包含類型和權限的對象;
文件系統:組織文件的方式;文件和某些屬性的集合。 它爲引用這些文件的文件序列號提供了一個名稱空間。
文件系統的多種含義:
- 一種特定的文件格式
- 按特定格式進行了“格式化”的存儲介質
- 操作系統(通常在內核中)用來管理文件系統以及對文件進行操作的機制及其實現——這是本章的主要話題;
2.文件類型–參照第一部分基礎6
Linux文件結構:字節流
3.VFS:作用、功能,會在內核產生四種對象:vfs對象的具體含義
1)VFS的作用和功能:
- 爲各類文件系統提供了一個統一的操作界面和應用編程接口
- 文件的統一管理與抽象都由VFS實現
- VFS將用戶的文件操作轉換爲對應的驅動級別的操作(即統一的系統調用轉換爲各自驅動級別的操作)
2)VFS模型:
打開一個文件後,VFS會在內存中創建4個對象
- 超級塊:用於描述當前的文件系統
- 索引節點對象(inode):用於唯一標識文件
- 文件對象:代表一個打開的文件,進程相關
- 目錄項:用於描述文件的目錄關係
4.硬軟鏈接(重點)
可參照:https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html,也可以參照第一章的第8小節
硬鏈接:不同的文件名對應同一個inode,不能跨越文件系統,對應系統調用link
軟鏈接:存儲被鏈接文件的文件名與路徑,可跨越文件系統,對應系統調用symlink
5.系統調用和庫函數的區別,如:open和fopen怎麼用,區別是什麼
系統調用和庫函數都以C函數的形式出現;
1)系統調用:
- Linux內核的對外接口
- 用戶程序與內核之間的唯一接口
- 提供最小接口
2)庫函數
- 依賴於系統調用
- 提供較複雜功能
例如標準I/O庫
3)基本I/O系統調用
open/create,close,read,write,lseek
dup/dup2
fcntl
ioctl
系統調用函數參照:https://blog.csdn.net/yuan892173701/article/details/8687590
6.文件描述符的類型、含義
在Linux系統中,打開文件就會獲得文件描述符,它是:一個很小的非負整數int fd
Linux內核在打開文件時分配一個文件對象,文件描述符指向內核中的文件描述符表元素,此元素再指向文件對象;
每個進程啓動後至少分配3個文件描述符:標準輸入、標準輸出、標準錯誤,文件描述符依次爲0,1,2,定義與unistd.h。
基本步驟:open -> read/write -> [lseek] -> close
7.標準I/O庫函數(PPT32-57,之後是高級系統調用,目錄有關的函數)
1)文件流
流與FILE結構:FILE* fp;預定義的指針:stdin,stdout,stderr;
緩衝I/O:三種類型——全緩衝、行緩衝、無緩衝
2)標準I/O函數
流open/close
流read/write
- 每次一個字符的I/O
- 讀取一個字符
- 輸出一個字符
- 每次一行的I/O
- 讀一行(從流——即文件)
- 輸出一行至流(文件)
- 直接I/O(二進制I/O)
- fread和fwrite——不懂誒
- 格式化I/O
- scanf、fscanf、sscanf
- printf、fprintf、sprintf
流復位
- fseek、ftell、rewind
- fgetpos、fsetpos
流刷新
- 刷新文件流。把流裏的數據立刻寫入文件
#include <stdio.h>
int fflush(FILE *stream);
8.文件系統編程的函數
比如用c寫重定向要知道調用什麼函數;fcntl大概瞭解、知道標誌位就好;ioctl不考,和驅動相關直接調用驅動代碼
9.緩存I/O的三種模式:
- 全緩存:由庫函數提供緩存,刷新時才寫入
- 行緩存:完成一行後寫入
- 無緩存
10.文件鎖
鎖起的作用:
- 幾個進程同時操作一個文件
文件鎖的分類:
- 記錄鎖
- 勸告鎖:檢查,加鎖有應用程序自己控制
- 強制鎖:檢查,加鎖由內核控制;影響open() read() write()等系統調用
- 共享鎖
- 排他鎖
fcntl記錄鎖——即fcntl來進行鎖相關的操作
- 用於記錄鎖的fcntl函數原型
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, struct flock *lock)
flock是一個struct,裏面保存了鎖的類型、鎖開始的位移、鎖的字節長度、阻塞鎖的進度PID
cmd參數:F_GETLK獲得鎖信息;F_SETLK設置鎖信息;F_SETLKW同設置鎖信息,wait方式;
11.安全性:防護等級大概知道每一級保護到什麼程序、緩衝區溢出會考(讀代碼、找溢出)
六、內核
1.內核主要功能、一般不考編譯內核的細節
操作系統是一系列程序的集合,其中最重要的部分構成了內核
單內核/微內核:
- 單內核是一個很大的進程,內部可以分爲若干模塊,運行時是一個獨立的二進制的文件,模塊間通訊通過直接調用函數實現;
- 微內核中大部分內核作爲獨立的進程在特權下運行,通過消息傳遞進行通訊;
Linux內核的能力:
- 內存管理,文件系統,進程管理,多線程支持,搶佔式,多處理器支持
2.驅動
- 許多常見驅動的源代碼集中在內核源碼中
- 也有第三方開發的驅動,可以單獨編譯成模塊.ko
- 編譯需要內核頭文件的支持
此外,所有驅動需要以內核態運行開發驅動的注意事項:
- 不能使用c庫來開發驅動程序
- 沒有內存保護機制(內核態)
- 小內核棧
- 併發上的考慮(大量線程隨機運行時驅動的運行情況是否正確)模塊之間的通訊:
- 模塊是爲了完成某種特定任務而設計的,其功能比較的單一,爲了豐富系統的功能,所以模塊之間常常進行通信。其之間可以共享變量,數據結構,也已調用對方提供的功能函數;
模塊相關命令:
- 底層命令
- insmod //加載模塊
- rmmod //卸載模塊
- 高層命令
- modprobe
- modprobe -r //釋放模塊
- moddep //查詢模塊依賴的所有其他模塊
- lsmod //列出已經裝載的模塊列表
- modinfo //顯示模塊信息
3.BootLoader Linux要看、初始化不要、用戶態內核態的區別
用戶態與內核態:
當一個任務(進程)執行系統調用而陷入內核代碼中執行時,我們就稱進程處於內核運行態(簡稱內核態)。此時處理器處於特權級最高的0級(x86的特權級分爲4級,0級最高,3級最低)。當進程處於內核態時,執行的內核代碼會使用當前進程的內核棧。每個進程都有自己的內核棧。
當進程執行用戶自己的代碼時,處於用戶態,特權級爲3.進入內核態:
- 系統調用
- 中斷處理
- 異常
第二部分 系統調用與C庫I/O函數
FD:file descriptor,一個很小的正整數,打開文件時獲得
在unistd.h中,有STDIN_FILENO(0),STDOUT_FILENO(1),STDERR_FILENO(2);
一、系統調用
1.open/creat
#include <fcntl.h>
int open(const char *pathname, int flags)
int open(const char *pathname, int falgs, mode_t mode)
int creat(const char *pathname, mode_t mode)
(return: a new file descriptor if success; -1 if failure)
參數 "falgs"
- flags:文件權限
- O_RDONLY,O_WRONLY,O_RDWR,即只讀、只寫、讀/寫;還有O_CREAT表示如果不存在即創建文件;O_APPEND追加模式,O_TRUNC,O_EXCL
- creat函數等價於open使用O_CREAT|O_WRONLY|O_TRUNC
參數"mode"
- 用於創建新文件的時指定權限
2.close函數
關閉一個文件描述符
#include <unistd.h>
int close(int fd);
(return 0 if success, -1 if failure)
3.read/write函數
#include <unistd.h>
ssized_t read(int fd, void *buf, size_t count)——即從fd對應的文件中讀count個字節的數據到buf數組裏;
(返回讀到的字節數,若已到文件尾爲0,若出錯爲1)
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count)——即從buf數組中讀count個字節的數據寫到fd對應的文件中;
(若成功返回已寫的字節數,若出錯爲-1)
4.dup/dup2——複製文件描述符
#include <unistd.h>
int dup(int oldfd)
int dup2(int oldfd, int newfd)
(return: the new file descriptor if success; -1 if failure)
作用:例如重定向,參照試卷shell重定向的實現
5.fcntl——文件控制
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd)
int fcntl(int fd, int cmd, long arg)
int fcntl(ing fd, int cmd, struct flock *lock)——操作鎖
(返回值:若成功依賴於cmd,若出錯返回-1)
cmd參數:
F_DUPFD:複製文件描述符
F_GETFD/F_SETFD
F_GETFL/F_SETFL:獲得/設置FD flags,即權限
F_GETOWN/F_SETOWN
F_GETLK/F_SETLK/F_SETLKW:獲得/設置文件鎖,W表示等待
二、標準I/O庫函數——全部位於#include
1.文件流(FILE *)
FILE* fp;
緩衝IO:全緩衝、行緩衝、無緩衝
2.標準I/O庫函數
都是針對流,即FILE*結構進行的操作;
1)open/close
FILE *fopen(const char *filename, const char *mode)
int fclose(FILE *stream)
mode參數:r, w, a, r+, w+, a+分別表示讀、寫、追加、讀和寫、讀寫創建、讀追加創建
2)read/write
每次一個字符的I/O
int getc(File * fp)
int fgetc(File *fp)
int getchar(void)
返回值時字符轉換的int,EOF(end of file,用feof(char)來判斷),error(ferror(char)判斷)
int putc(int c, File *fp)
int fputc(int c,File *fp)
int putchar(int c)
返回char如果成功,失敗返回-1
每次一行的I/O——從流中讀size放到數組中,或把數組寫到流中
char *fgets(char *s, int size, FILE *stream)
讀最多size-1個字符,第size爲換行(\0),或EOF
int fputs(const char *s, FILE *stream)
直接I/O(二進制I/O)
fread和fwrite
格式化I/O
scanf, fscanf,sscanf
printf, fprintf, sprintf
3)流復位
4)流刷新
刷新文件流。把流裏的數據立即寫入文件
int fflush(FILE *stream)
5)流與文件描述符的相互轉換
int fileno(FILE *fp) ——確定流使用的底層文件描述符
FILE *fdopen(int fd)——根據已打開的文件描述符創建一個流
三、高級系統調用——位於#include
1.權限函數
#include <unistd.h>
int access(const char *pathname, int mode)返回0成功,-1失敗
mode:R_OK,W_OK,X_OK,F_OK
2.chmod/fchmod函數——改變文件權限
#include <sys/types.h>
#include <sys/stat.h>
int chmod(const char *path, mode_t mode)
int fchmod(int fildes, mode_t mode)
(return 0 if success, -1 if failure)
3.chown/fchown/lchown函數——改變文件屬主和用戶組
#include <sys/types.h>
#inculde <unistd.h>
int chown(const char *path, uid_t owner, gid_t group)
int fchown(int fd, uid_owner, gid_t group)
int lchown(const char *path, uid_t owner, gid_t group)
``
4.link/unlink函數
創建文件的鏈接:
#include <unistd.h>
int link(const char *oldpath, const char *newpath)——對應了硬鏈接
刪除一個名詞,以及它可能引用的名稱:
int unlink(const char *pathname)
5.symlink/readlink函數
創建新鏈接(包含了oldpath的新文件)
int symlink(const char *oldpath, const char *newpath)
讀符號鏈接的值:
int readlink(const char *path, ch)
第三部分 編程複習題
卷2014
- 重定向是Linux中的重要機制。試分析其使用方法、應用實例,並簡述實現機制。(15分)
shell中使用<輸入重定向,>輸出重定向。
如:ls -l > x.txt
cat < x.txt
實現機制:使用dup2系統調用實現重定向,如下列程序將標準輸出重定向至文件:
2.Linux中文件描述符和文件指針FILE*的區別是什麼?
文件描述符:在Linux系統中打開文件就會獲得文件描述符,它是一個很小的正整數。每個進程在PCB(process control block)中保存着一份文件描述符表,文件描述符就是這個表的索引,每個表項都有一個指向已打開文件的指針;
文件指針FILE*:C語言中使用文件指針FILE*作爲I/O的句柄。文件指針指向進程用戶區的一個被稱爲FILE結構的數據結構.FILE結構包括一個緩衝區和一個文件描述符,而文件描述符是文件描述符表的一個索引,因此某種意義上說文件指針就是句柄的句柄。
3.使用C的庫函數,編寫一個函數void bindiff(char *file1,char *file2,char *fileo),將文件從file1、file2對應的路徑中讀取並逐字節比對,將相同的字節輸出到fileo對應的文件中。(25分)
#include <stdio.h>
void bindiff(char *file1,char *file2, char * fileo);
int main()
{
bindiff("1.txt","2.txt","3.txt");
}
void bindiff(char *file1,char *file2,char *fileo)
{
FILE *fp1 = 0, *fp2=0, *fp0=0;
char ch1,ch2;
fp1 = fopen(file1, "r");
fp2 = fopen(file2, "r");
fpo = fopen(fileo, "w");
while(1)
{
ch1 = (char)fgetc(fp1);
ch2 = (char)fgetc(fp2);
if(feof(fp1) || feof(fp2))
{
break;
}
if(ch1==ch2)
{
fputc(ch2,fpo);
}
}
fclose(fp1);
fclose(fp2);
fclose(fpo);
}
注:使用C庫函數fopen,fgetc,fputc,feof
卷2015
一、選擇題 (5*6=30)
(1)用戶與內核的接口是什麼:系統調用(注意:用戶與操作系統的接口是shell)
(2)刪除文件夾的命令:rmdir
(3)重定向-輸出文件內容:command > file
(4)切換用戶的命令:su
(5)null
二、簡答題(2*10=20)
1、爲什麼Linux引入makefile?和其他腳本的區別?使用makefile編譯系統有哪些?特點?
自動化編譯
2、硬鏈接與軟鏈接的區別?(至少三點)用shell命令和函數如何創建?
這個參考複習內容
三、編程題(15+20+15=50)
1、看代碼,是否有緩衝區溢出?如何改進?
今年應該不考
2、用系統調用實現輸出給定文件夾中所有文件的名字 用空格隔開,並在文件夾及文本文件的輸出後註上“(文件夾)”“(文本文件)”
這個明天看作業,應該就是ls命令
思路:
1)用一個bool數組來填充在命令行中輸入的參數選項,分別接收-a,-l,-R,-i-d;同時使用getopt()函數解析輸入
2)對於輸入的每個文件或目錄,循環執行ls()自定義函數
3)查閱相關資料,可根據st_mode & S_IFMT的結果來判斷文件類型,並根據st_mode中1的位置來判斷文件權限;
3、shell腳本編程,獲得用戶輸入的100個整數,並輸出其最大值,最小值,總和。
#!/bin/bash
i=0
min=10000
max=-10000
while (($i<100))
do
read thisNum
if(($thisNum<=$min))
then
min=$thisNum
fi
if(($thisNum>=$max))
then
max=$thisNum
fi
let i++
done
echo "maxNum:$max"
echo "minNum:$min"