1. 程式人生 > >國嵌linux視訊課件整理(1)

國嵌linux視訊課件整理(1)

Linux系統管理

Linux與Linux之間通過NFS(network file system)實現共享;
windows與windows之間通過共享目錄實現共享;
Linux與windows之間通過Samba實現共享。
Wireshark抓包軟體,分析網路協議。
shell程式設計:
1)#!/bin/bash ,符號#!用來指定該指令碼檔案的解析程式。
2)# 開頭表示該行是註釋。
3)所有變數都是由字串組成,並且不需要預先對變數進行宣告。使用變數需在變數名前$。有時候變數名很容易與其他文字混淆,這時需要用{}將變數名括起來。
4)預設變數:
$#:傳入指令碼的命令列引數個數
$*:所有命令列引數值,在各個引數之間留有空格
$0:命令本身(shell檔名)
$1:第一個命令列引數
$2:第二個命令列引數
5)區域性變數,在變數首次賦值時加local可以宣告一個區域性變數。
6)變數注意事項:
變數賦值時“=”號左右兩邊都不能空格
語句結尾不加“;”
7)if語句
if [ expression ]
then
#code block
fi 
if [ expression ]
then
#code block
else
#code block
fi
比較操作 整數 字串
相同 -eq =
不同 -ne !=
大於 -gt >
小於 -lt <
小於等於 -le 
大於等於 -ge
為空 -z
不為空 -n 
注意:
在“[”和“]”符號的左右都留有空格
“=”左右都有空格
判斷:
-e 檔案已經存在
-f 檔案是普通檔案
-s 檔案大小不為0
-d 檔案是一個目錄
-r 檔案對當前使用者可以讀取
-w 檔案對當前使用者可以寫入
-x 檔案對當前使用者可以執行
8)for迴圈和while迴圈
for var in [list]
do
# code
done
注意:
for所在那行變數是沒有加“$”的,而在迴圈體內,變數是要加“$”的
list如果用“”括起來是被當作一個值賦給var
while [ condition ]
do
#code
done
until [ condition ] 條件為假時執行
do
#code
done
9)case語句
case "$var" in
condition1)
;;
condition2)


;;
*)
#default statments;;
esac

gcc學習

Linux系統下的gcc(GNU C Compiler)是GNU推出的功能強大、性
能優越的多平臺編譯器,是GNU的代表作之一。gcc可以在多種硬體平臺上編譯出可執行程式,其執行效率與一般的編譯器相比平均效率要高20%~30%。
GCC編譯器能將C,C++語言源程式,彙編程式編譯,連結成可執行檔案。Linux通過屬性來決定檔案的可執行性。
GCC編譯4個階段:
預處理(pre-processing),編譯(compling),彙編(assembing),
連結(linking)
處理的輸入檔案類別:.c.a.C.h.i.ii.o.s.S
gcc最基本的用法是:
gcc [options] [filename]
options:
-o output_filename:指定輸出的可執行檔名稱。
-c:只編譯,不連線成為可執行檔案,編譯器只是由輸入的.c等原始碼檔案生成.o為字尾的目標檔案。
-g:產生除錯工具(GNU的gdb)所必要的符號資訊,要想對編譯出的程式進行除錯,就必須加入這個選項。
-O:對程式進行優化編譯、連結,採用這個選項,整個原始碼會在編譯、連線過程中進行優化處理,這樣產生的可執行檔案的執行效率可以提高,但是,編譯、連線的速度就相應地要慢一些。
-O2,比-O更好的優化編譯、連線,當然整個編譯、連線過程會更慢。
-I dirname: 將dirname所指出的目錄加入到程式標頭檔案目錄列表
中。C程式中的標頭檔案包含兩種情況∶
#include <A.h>和#include “B.h”對於<>,預處理程式cpp在系統預設的標頭檔案目錄(如/usr/include)中搜尋相應的檔案;而對於””,cpp在當前目錄中搜尋標頭檔案。這個選項的作用是告訴cpp,如果在當前目錄
中沒有找到需要的檔案,就到指定的dirname目錄中去尋找。
-L dirname:將dirname所指出的目錄加入到庫檔案的目錄列表中。在預設狀態下,連線程式ld在系統的預設路徑中(如/usr/lib)尋找所需要的庫檔案,這個選項告訴連線程式,首先到-L指定的目錄中去尋找,然後再到系統預設路徑中尋找。
-l name:在連線時,裝載名字為“libname.a”的函式庫,該函式庫位於
系統預設的目錄或者由-L選項確定的目錄下。例如,-l m表示連線名為
“libm.a”的數學函式庫。
-static:靜態連結庫檔案 例:gcc –static hello.c -o hello
庫有動態與靜態兩種,動態通常用.so為字尾,靜態用.a為字尾。例如:libhello.so libhello.a。當使用靜態庫時,聯結器找出程式所需的函式,然後將它們拷貝到可執行檔案,一旦連線成功,靜態程式庫也就不再需要了。然 而,對動態庫而言,就不是這樣,動態庫會在執行程式內留下一個標記‘指明當程式執行時,首先必須載入這個庫。由於動態庫節省空間,linux下進行連線的預設操作是首先連線動態庫。
-Wall:生成所有警告資訊
-w:不生成任何警告資訊
-DMACRO: 定義 MACRO 巨集,等效於在程式中使用#define MACRO


GDB程式除錯

GDB是GNU釋出的一款功能強大的程式除錯工具。GDB主要完成下面三個方面的功能:

1、啟動被除錯程式。

2、讓被除錯的程式在指定的位置停住。

3、當程式被停住時,可以檢查程式狀態

(如變數值)。

GDB除錯的一般步驟:

1.編譯生成可執行檔案:

gcc -g tst.c -o tst

2.啟動GDB

gdb tst

3. 在main函式處設定斷點

break main

4. 執行程式

run

5. 單步執行

next

6. 繼續執行

continue

常用GDB命令:

list(l) 檢視程式

break(b) 函式名 在某函式入口處新增斷點

break(b) 行號 在指定行新增斷點

break(b) 檔名:行號在指定檔案的指定行新增斷點

break(b) 行號 if 條件當條件為真時,指定行號處斷點生效,例b 5 if i=10,當i等於10時第5行斷點生效

info break 檢視所有設定的斷點

delete 斷點編號 刪除斷點

run(r) 開始執行程式

next(n) 單步執行程式(不進入子函式)

step(s) 單步執行程式(進入子函式)

continue(c) 繼續執行程式

print(p) 變數名 檢視指定變數值

finish 執行程式,直到當前函式結束

watch 變數名 對指定變數進行監控

quit(q) 退出gdb

Makefile工程管理

Linux程式設計師必須學會使用GNU make來構建和管理自己的軟體工程。GNU 的make能夠使整個軟體工程的編譯、連結只需要一個命令就可

以完成。

make在執行時, 需要一個命名為Makefile的檔案。Makefile檔案描述了整個工程的編譯,連線等規則。其中包括:工程中的哪些原始檔需要編譯以及如何編譯;需要建立那些庫檔案以及如何建立這些庫檔案、如何最後產生我們想要得可執行檔案。

makefile規則:用於說明如何生成一個或多個目標檔案,

規則格式如下:

targets :prerequisites

command

目標 依賴 命令

main.o : main.c

gcc –c main.c

**命令需要以【TAB】鍵開始**

目標:在Makefile 中,規則的順序是很重要的,因為,Makefile中只應該有一個最終目標,其它的目標都是被這個目標所連帶出來的,所以一定要讓make知道你的最終目標是什麼。一般來說,定義在Makefile中的目標可能會有很多,但是第一條規則中的目標將被確立為最終的目標。

檔名:make命令預設在當前目錄下尋找名字為makefile或者Makefile的工程檔案,當名字不為這兩者之一時,可以使用如下方法指定:

make –f 檔名

偽目標:Makefile中把那些沒有任何依賴只有執行動作的目標稱為“偽目標”(phony targets)。

.PHONY : clean

clean :

rm –f hello main.ofunc1.o func2.o

“.PHONY” 將“clean”目標宣告為偽目標。

變數的使用:obj=main.o func1.o func2.o func3.o

hello: $(obj)

gcc $(obj) -o hello

在makefile中,存在系統預設的自動化變數

$^:代表所有的依賴檔案

[email protected]:代表目標

$<:代表第一個依賴檔案

Makefile中“#”字元後的內容被視作註釋。

@:取消回顯

hello: hello.c

@gcc hello.c –ohello

linux檔案程式設計

Linux系統呼叫

系統呼叫-建立

int creat(const char*filename,mode_t mode)

vfilename:要建立的檔名(包含路徑,預設為當前路徑)

vmode:建立模式,常見建立模式:

S_IRUSR 可讀

S_IWUSR 可寫

S_IXUSR 可執行

S_IRWXU 可讀、寫、執行

除了可以使用上述巨集以外,還可以直接使用數字來表示檔案的訪問許可權:

v可執行 -> 1

v可寫 -> 2

v可讀 -> 4

v上述值的和,如可寫可讀 -> 6

v無任何許可權 -> 0

檔案描述

在Linux系統中,所有開啟的檔案都對應一個檔案描述符。檔案描述符的本質是一個非負整數。當開啟一個檔案時,該整數由系統來分

配。檔案描述符的範圍是0 - OPEN_MAX 。早期的UNIX版本OPEN_MAX =19,即允許每個程序同時開啟20個檔案,現在很多系統則將其增加至1024。

系統呼叫-開啟

int open(const char*pathname, int flags)

int open(const char*pathname, int flags,mode_t mode)

pathname:要開啟的檔名(包含路徑,預設為當前路徑)

flags:開啟標誌,常見的開啟標誌:

O_RDONLY 只讀方式開啟

O_WRONLY 只寫方式開啟

O_RDWR 讀寫方式開啟

O_APPEND 追加方式開啟

O_CREAT 建立一個檔案

O_NOBLOCK 非阻塞方式開啟

如果使用了O_CREATE標誌,則使用的函式是:

int open(const char*pathname,int flags,mode_t mode);

這時需要指定mode來表示檔案的訪問許可權。

當我們操作完檔案以後,需要關閉檔案:

int close(int fd) ,fd: 檔案描述符

系統呼叫-讀

int read(int fd,const void *buf, size_t length)

功能:從檔案描述符fd所指定的檔案中讀取length個位元組到buf所指向的緩衝區中,返回值為實際讀取的位元組數。

系統呼叫-寫

int write(int fd,const void *buf, size_t length)

功能:把length個位元組從buf指向的緩衝區中寫到檔案描述符fd所指向的檔案中,返回值為實際寫入的位元組數。

系統呼叫-定位

int lseek(int fd,offset_t offset, int whence)

功能:將檔案讀寫指標相對whence移動offset個位元組。操作成功時,返回檔案指標相對於檔案頭的位置。

whence可使用下述值:

SEEK_SET:相對檔案開頭

SEEK_CUR:相對檔案讀寫指標的當前位置

SEEK_END:相對檔案末尾

offset可取負值,表示向前移動。例如下述呼叫可將檔案指標相對當前位置向前移動5個位元組:

lseek(fd, -5,SEEK_CUR)

由於lseek函式的返回值為檔案指標相對於檔案頭的位置,因此下面呼叫的返回值就是檔案的長度:

lseek(fd, 0,SEEK_END)

系統呼叫-訪問判斷

有時我們需要判斷檔案是否可以進行某種操作(讀,寫

等),這時可以使用access函式:

int access(constchar*pathname,int mode)

pathname:檔名稱

mode:要判斷的訪問許可權。可以取以下值或者是他們的組合。R_OK:檔案可讀,W_OK:檔案可寫,X_OK:檔案可執行,F_OK檔案存在。

返回值:當我們測試成功時,函式返回0,否則如果一個條件不符時,返回-1。

C語言庫函式

C庫函式的檔案操作是獨立於具體的作業系統平臺的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函式。

庫函式-建立和開啟

FILE *fopen(constchar *filename, const char *mode)

filename:開啟的檔名(包含路徑,預設為當前路徑)

mode:開啟模式

常見開啟模式:

r, rb 只讀方式開啟

w, wb 只寫方式開啟,如果檔案不存在,則建立該檔案

a, ab 追加方式開啟,如果檔案不存 在,則建立該檔案

r+, r+b, rb+讀寫方式開啟

w+, w+b, wh+ 讀寫方式開啟,如果檔案不存在,則建立該檔案

a+, a+b, ab+讀和追加方式開啟。如果檔案不存在,則建立該檔案

b用於區分二進位制檔案和文字檔案,這一點在DOS、Windows系統中是有區分的,但Linux不區分二進位制檔案和文字檔案。

庫函式-讀

size_t fread(void*ptr, size_t size, size_t n, FILE *stream)

功能:從stream指向的檔案中讀取n個欄位,每個欄位為size位元組,並將讀取的資料放入ptr所指的字元陣列中,返回實際已讀取的位元組數。

庫函式-寫

size_t fwrite (constvoid *ptr, size_t size, size_t n,FILE *stream)

功能:從緩衝區ptr所指的陣列中把n個欄位寫到stream指向的檔案中,每個欄位長為size個位元組,返回實際寫入的欄位數。

庫函式-讀字元

int fgetc(FILE*stream)

庫函式-寫字元

int fputc(int c,FILE *stream)

庫函式-格式化讀

fscanf(FILE *stream,char *format[,argument...])

從一個流中進行格式化輸入,fscanf(stdin, "%d", &i)

庫函式-格式化寫

int fprintf(FILE*stream, char* format[,argument,...])

格式化輸出到一個流中,printf( stream, "%d\n", i );

庫函式-定位

int fseek(FILE*stream, long offset, int whence)

whence :

SEEK_SET 從檔案的開始處開始搜尋

SEEK_CUR 從當前位置開始搜尋

SEEK_END 從檔案的結束處開始搜尋

路徑獲取

在編寫程式的時候,有時候需要得到當前路徑。C庫函式提供了getcwd來解決這個問題。

char *getcwd(char*buffer,size_t size)

我們提供一個size大小的buffer,getcwd會把當前的路徑名copy 到buffer中.如果buffer太小,函式會返回-1。

建立目錄

#include<sys/stat.h>

int mkdir(char *dir, int mode)

功能:建立一個新目錄。

返回值:0表示成功,-1表述出錯。

linux時間程式設計

時間型別

CoordinatedUniversal Time(UTC):世界標準時間,也就是大家所熟知的格林威治標準時間(Greenwich Mean Time,GMT)。

Calendar Time:日曆時間,是用“從一個標準時間點(如:1970年1月1日0點)到此時經過的秒數”來表示的時間。

時間獲取

#include<time.h>

time_t time(time_t*tloc)

功能:獲取日曆時間,即從1970年1月1日0點到現在所經歷的秒數。

/* typedef longtime_t */

時間轉化

struct tm*gmtime(const time_t *timep)

功能:將日曆時間轉化為格林威治標準時間,並儲存至TM結構。

struct tm*localtime(const time_t *timep)

功能:將日曆時間轉化為本地時間,並儲存至TM結構。

時間儲存

struct tm {

int tm_sec; //秒值

int tm_min;

//分鐘值

int tm_hour; //小時值

int tm_mday; //本月第幾日

int tm_mon;

//本年第幾月

int tm_year;//tm_year + 1900 = 哪一年

int tm_wday; //本週第幾日

int tm_yday; //本年第幾日

int tm_isdst; //日光節約時間

};

時間顯示

char *asctime(conststruct tm *tm)

功能:將tm格式的時間轉化為字串,如: Sat Jul 30 08:43:03 2005

char *ctime(consttime_t *timep)

功能:將日曆時間轉化為本地時間的字串形式。

獲取時間

intgettimeofday(struct timeval *tv,struct timezone *tz)

功能:獲取從今日凌晨到現在的時間差,常用於計算事件耗時。

struct timeval {

int tv_sec; //秒數

int tv_usec; //微妙數

};

延時執行

unsigned intsleep(unsigned int seconds)

功能:使程式睡眠seconds秒。

void usleep(unsignedlong usec)

功能:使程式睡眠usec微秒。

程序控制

程序控制理論

定義:

程序是一個具有一定獨立功能的程式的一次執行活動。

特點:

動態性

併發性

獨立性

非同步性

狀態

程序ID

程序ID(PID):標識程序的唯一數字

父程序的ID(PPID)

啟動程序的使用者ID(UID)

程序互斥

程序互斥是指當有若干程序都要使用某一共享資源時,任何時刻最多允許一個

程序使用,其他要使用該資源的程序必須等待,直到佔用該資源者釋放了該資源

為止。

臨界資源

作業系統中將一次只允許一個程序訪問的資源稱為臨界資源。

臨界區

程序中訪問臨界資源的那段程式程式碼稱為臨界區。為實現對臨界資源的互斥訪

問,應保證諸程序互斥地進入各自的臨界區。

程序同步

一組併發程序按一定的順序執行的過程稱為程序間的同步。具有同步關係

的一組併發程序稱為合作程序,合作程序間互相傳送的訊號稱為訊息或事件。

程序排程

概念:

按一定演算法,從一組待執行的程序中選出一個來佔有CPU執行。

排程方式:

• 搶佔式

• 非搶佔式

排程演算法:

先來先服務排程演算法

短程序優先排程演算法

高優先順序優先排程演算法

時間片輪轉法

死鎖

多個程序因競爭資源而形成一種僵局,若無外力作用,這些程序都將永

遠不能再向前推進。

程序建立

獲取ID

#include<sys/types.h>

#include<unistd.h>

pid_t getpid(void) 獲取本程序ID。

pid_t getppid(void) 獲取父程序ID。

程序建立-fork

#include<unistd.h>

pid_t fork(void)

功能:建立子程序

fork的奇妙之處在於它被呼叫一次,卻返回兩次,它可能有三種不同的返回值:

1. 在父程序中,fork返回新建立的子程序的PID;

2. 在子程序中,fork返回0;

3. 如果出現錯誤,fork返回一個負值

在pid=fork()之前,只有一個程序在執行,但在這條語句執行之後,就變成兩個

程序在執行了,這兩個程序的共享程式碼段,將要執行的下一條語句都是if(pid==0)。

兩個程序中,原來就存在的那個程序被稱作“父程序”,新出現的那個程序被稱作“子程序”,父子程序的區別在於程序識別符號(PID)不同。

子程序的資料空間、堆疊空間都會從父程序得到一個拷貝,而不是共享。在子

程序中對count進行加1的操作,並沒有影響到父程序中的count值,父程序中的

count值仍然為0。

程序建立-vfork

#include<sys/types.h>

#include<unistd.h>

pid_t vfork(void)

功能:建立子程序。

區別:

1. fork:子程序拷貝父程序的資料段

vfork:子程序與父程序共享資料段

2. fork:父、子程序的執行次序不確定

vfork:子程序先執行,父程序後執行

exec函式族

exec用被執行的程式替換呼叫它的程式。

區別:

fork建立一個新的程序,產生一個新的PID。exec啟動一個新程式,替換原有的程序,因此程序的PID不會改變。

#include<unistd.h>

intexecl(const char * path,const char * arg1, ....)

引數:

path:被執行程式名(含完整路徑)。

arg1 – argn: 被執行程式所需的命令列引數,含程式名。以空指標(NULL)結束。

例:execl.c

#include<unistd.h>

main()

{

execl(“/bin/ls”,”ls”,”-al”,”/etc/passwd”,(char* )0);

}

#include<unistd.h>

intexeclp(const char * path,const char * arg1, ...)

引數:

path:被執行程式名(不含路徑,將從path環境變數中查詢該程式)。

arg1 – argn: 被執行程式所需的命令列引數,含程式名。以空指標(NULL)結束。

例:execlp.c

#include<unistd.h>

main()

{

execlp(”ls”,”ls”,”-al”,”/etc/passwd”,(char*)0);

}

#include<unistd.h>

int execv(const char * path, char * const argv[ ])

引數:

path:被執行程式名(含完整路徑)。

argv[]: 被執行程式所需的命令列引數陣列。

例:execv.c

#include<unistd.h>

main()

{

char * argv[]={“ls”,”-al”,”/etc/passwd”,(char*)0};

execv(“/bin/ls”,argv);

}

#include<stdlib.h>

intsystem( const char* string )

功能:

呼叫fork產生子程序,由子程序來呼叫/bin/sh -c string來執行引數string所代表

的命令。

例:system.c

#include<stdlib.h>

void main()

{

system(“ls -al/etc/passwd”);

}

程序等待

#include<sys/types.h>

#include<sys/wait.h>

pid_t wait (int *status)

功能:阻塞該程序,直到其某個(任意)子程序退出。

程序通訊

概述

為什麼程序間需要通訊?

1、資料傳輸

一個程序需要將它的資料傳送給另一個程序。

2、資源共享

多個程序之間共享同樣的資源。

3、通知事件

一個程序需要向另一個或一組程序傳送訊息,通知它們發生了某種事件。

4、程序控制

有些程序希望完全控制另一個程序的執行(如Debug程序),此時控制程序希望能夠攔截另一個程序的所有操作,並能夠及時知道它的狀態改變。

Linux程序間通訊(IPC)由以下幾部分發展而來:

1、UNIX程序間通訊

2、基於System V程序間通訊

3、POSIX程序間通訊

POSIX(PortableOperating System Interface)表示可移植作業系統介面。電氣和電子工程師協會(Institute of Electrical and ElectronicsEngineers,IEEE)最初開發 POSIX 標準,是為了提高 UNIX 環境下應用程式的可移植性。然而,POSIX 並不侷限於 UNIX,許多其它的作業系統,例如 DEC OpenVMS 和 Microsoft Windows,都支援 POSIX 標準。

System V,也被稱為 AT&T System V,是Unix作業系統眾多版本中的一支。

現在Linux使用的程序間通訊方式包括:

1、管道(pipe)和有名管道(FIFO)

2、訊號(signal)

3、訊息佇列

4、共享記憶體

5、訊號量

6、套接字(socket)

管道通訊

什麼是管道?

管道是單向的、先進先出的,它把一個程序的輸出和另一個程序的輸入連線在一起。一個程序(寫程序)在管道的尾部寫入資料,另一個程序(讀程序)從管道的頭部讀出資料。

資料被一個程序讀出後,將被從管道中刪除,其它讀程序將不能再讀到這些資料。管道提供了簡單的流控制機制,程序試圖讀空管道時,程序將阻塞。同樣,管道已經滿時,程序再試圖向管道寫入資料,程序將阻塞。

管道建立

管道包括無名管道和有名管道兩種,前者用於父程序和子程序間的通訊,後者可用於運行於同一系統中的任意兩個程序間的通訊。

無名管道由pipe()函式建立:

int pipe(int filedis[2]);

當一個管道建立時,它會建立兩個檔案描述符:filedis[0] 用於讀管道, filedis[1] 用於寫管道。

關閉管道只需將這兩個檔案描述符關閉即可,可以使用普通的close函式逐個關閉。

管道讀寫

管道用於不同程序間通訊。通常先建立一個管道,再通過fork函式建立一個子程序,該子程序會繼承父程序所建立的管道。

注意事項

必須在系統呼叫fork( )前呼叫pipe( ),否則子程序將不會繼承檔案描述符。

命名管道(FIFO)

命名管道和無名管道基本相同,但也有不同點:無名管道只能由父子程序使用;但是通過命名管道,不相關的程序也能交換資料。

建立

#include<sys/types.h>

#include<sys/stat.h>

int mkfifo(constchar * pathname, mode_t mode)

pathname:FIFO檔名

mode:屬性(見檔案操作章節)

一旦建立了一個FIFO,就可用open開啟它,一般的檔案訪問函式(close、read、write等)都可用於FIFO。

操作

當開啟FIFO時,非阻塞標誌(O_NONBLOCK)將對以後的讀寫產生如下影響:

1、沒有使用O_NONBLOCK:訪問要求無法滿足時程序將阻塞。如試圖讀取空的FIFO,將導致程序阻塞。

2、使用O_NONBLOCK:訪問要求無法滿足時不阻塞,立刻出錯返回,errno是ENXIO。