Linux複習——總結篇

本篇涵蓋課程《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)字符特殊文件:見33)塊特殊文件:特殊文件代表硬件或邏輯設備,通常在/dev中;字符特殊文件通常是裝置文件中的串行端口設備,如鍵盤、鼠標等一次性讀取設備;塊特殊文件表示裝置文件中的可供存儲的接口設備(可隨機存取裝置);
4socket,即套接口文件/數據接口文件: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 116 19:26 nohup.html
-rwxrw-r--. 1 zfh zfh 672 116 18:43 OnlineExam項目說明文檔.html
lrwxrwxrwx. 1 zfh zfh 7 48 21:39 s.sql -> ./b.sql
-rw-rw-r--. 1 zfh zfh 25 48 11:51 test.sh
-rw-------. 3 zfh zfh 2722 116 19:26 x2.html

如上,解釋如下:

1)第一列,第一個符號表示文件類型,-表示文件,d表示目錄,l表示符號鏈接文件,b表示塊特殊文件,c表示字符特殊文件,其他的還有socket文件(s)和管道文件(p)——具體參照7;
   後面的九個字符依次表示文件所有者、所有者所在用戶組、其他用戶對這個文件的權限,rwx分別表示readwrite,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,顯示當前權限掩碼,如0245umask -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,常用的有三個,0stdin,標準輸入)、1stdout,標準輸出)、2stderr,標準錯誤輸出),默認與keyborad、monitor有關;
  用<來改變讀進的數據信道(stdin),使之從指定的檔案讀進;用>來改變送出的數據信道(stdout,stderr),使之輸出到指定的檔案;
  0是<的默認值,因此<與0<是一樣的;同理,>與1>是一樣的;
  在IO重定向中,stdoutstderr的管道會先準備好,纔會從stdin讀進資料;
 基本IO:
    cmd > filestdout重定向到file文件中;
    cmd > > filestdout重定向到file文件中(追加);
    cmd 1> filestdout重定向到file文件中;
    cmd > file 2>&1stdoutstderr一起重定向到file文件中;
    cmd 2> filestderr重定向到file文件中;
    cmd 2>> filestderr重定向到file文件中(追加);
    cmd >> file 2>&1stdoutstderr一起重定向到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

4echo命令
 read命令:讀取輸入;
 read選項:-p表示後面的輸出提示字符,不會換行;-n後面的數字表示輸入的字符長度限制;-t限時,-s隱藏輸入內容;

5.要看的:參數、條件、case循環、雜項命令(break、continue、exit….)、函數(好像不考,建議一看)、算術擴展和參數擴展(好好看一看)

1ifforwhile、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*結構進行的操作;

1open/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

  1. 重定向是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"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章