主頁 >  其他 > Linux下高級C編程(學習總結)

Linux下高級C編程(學習總結)

2020-10-21 14:11:44 其他

Linux下高級C編程

第一章 unix/linux系統的基本概念
第二章 unix/linux系統下的編程基礎和開發方式
第三章 unix/linux系統下的記憶體管理
第四章 unix/linux系統下的檔案管理和目錄操作
第五章 unix/linux系統下的行程管理
第六章 unix/linux系統下的信號處理
第七章 unix/linux系統下的行程間通信
第八章 unix/linux系統下的網路編程
第九章 unix/linux系統下的多執行緒編程


文章目錄

  • Linux下高級C編程
  • 前言
  • 一、linux系統的基本概念
    • 1.linux系統簡介
    • 2.gcc/cc基本使用
    • 3.常見的編譯選項
    • 4.常用的C程式檔案后綴
    • 5.多檔案編程
    • 6.預定義宏
    • 7.環境變數的概念和使用
  • 二、linux系統下的編程基礎和開發方式
    • 1.庫檔案的概念和使用
    • 2.靜態庫的生成和呼叫
    • 3.共享庫的生成和呼叫
    • 4.共享庫動態加載
    • 5.C語言的錯誤處理
    • 6.環境表的概念和使用
  • 三、linux系統下的記憶體管理
    • 1.程式和行程的概念
    • 2.行程中的記憶體區域劃分 (記憶體地址從小到大,其中堆和堆疊沒有明確的分割線,可以適當的調整)
    • 3.字串存盤形式之間的比較
    • 4.虛擬記憶體管理技術
    • 5.段錯誤的由來
    • 6.使用malloc 申請動態記憶體的特性
    • 7.使用free 釋放動態記憶體的特性
    • 8.記憶體處理的相關函式
  • 四、linux系統下的檔案管理和目錄操作
    • 1.基本概念
    • 2.檔案的相關處理函式
    • 3.檔案描述符
    • 4.檔案的非讀寫函式
    • 5.目錄管理
  • 五、linux系統下的行程管理
    • 1. 基本概念
    • 2. 基本命令
    • 3.各種ID的獲取
    • 4.行程相關函式
    • 中斷的概念:
  • 六、linux系統下的信號處理
    • 1.信號的基本概念和分類
    • 2.信號的處理方式
    • 3.信號的處理函式
    • 4.計時器
  • 七、linux系統下的行程間通信
    • 1.概念:
    • 2.行程間通信的方式
    • 3.使用訊息佇列實作行程間通信
    • 4.使用管道實作行程間通信
    • 5.使用共享記憶體實作行程間通信
    • 6.使用信號量集實作行程間通信
  • 八、linux系統下的網路編程
    • 1. 網路的基本常識
    • 2.基于socket的一對一通信模型
    • 3.基于TCP的協議的通信模型
    • 4.基于UDP協議的通信模型
    • TCP協議和UDP協議的比較
  • 九、linux系統下的多執行緒編程
    • 1.基本概念
    • 2.執行緒的相關函式
    • 3.執行緒的同步問題
    • 4.使用信號量 實作執行緒的同步問題
    • 5.使用條件變數實作執行緒的同步問題
  • 總結


前言

主要學習unix/linux系統下的API編程

一、linux系統的基本概念

1.linux系統簡介

2.gcc/cc基本使用

gcc/cc xxx.c 可以編譯鏈接C源程式生成一個可執行檔案 a.out
整個流程分4步:
	  (1) 預處理/預編譯 (包含頭檔案的擴展,以及執行宏替換等,生成 .i 檔案)
	  (2) 編譯 (將高級語言程式翻譯成匯編語言,得到匯編檔案,生成 .s 檔案)
	  (3) 匯編 (將匯編語言翻譯成機器指令,得到目標檔案,生成 .o 檔案)
	  (4) 鏈接 (將目標檔案和標準庫鏈接,得到可執行檔案)

3.常見的編譯選項

-E    實作預處理的執行,默認將處理輸出到控制臺,可以通過 -o 選項指定輸出到 xxx.i 檔案中,預處理檔案中包含很多頭檔案,型別別名,以及各種函式宣告等
-S    實作編譯處理,得到一個 .s 為后綴的匯編檔案
-c    實作編譯處理,得到一個 .o 為后綴的目標檔案
-v    查看編譯器的版本資訊
-std    指定執行的C標準
-wall   盡可能的產生警告資訊
-werror 將警告當做錯誤進行處理
-g    產生除錯資訊,采用GDB進行單步除錯
-O    進行具體的優化
-x    指定源代碼的具體編程語言

4.常用的C程式檔案后綴

.h   頭檔案  包含結構體的定義,變數和函式的宣告
.c   源檔案  包含變數和函式的定義
.i   預處理檔案
.s   匯編檔案
.o   目標檔案
.a   靜態庫檔案  對功能函式打包
.so  共享庫檔案  對功能函式打包

5.多檔案編程

預處理:
	#include  表示將指定檔案的內容包含進來
	#define   表示一個宏
	#undef    表示取消一個宏
	#if       表示如果
	#ifdef    表示如果定義
	#ifndef   表示如果沒有定義
	#else     表示否則
	#elif     表示否則如果
	#endif    表示結束判斷
常用指令:
	#line 整數n      表示修改代碼的行數/指定行號,修改下一行行號為n
	#error 字串    表示產生一個錯誤資訊
	#warning 字串  表示產生一個警告
	#pragma GCC dependency 檔案名  表示當前檔案依賴于指定的檔案,如果當前檔案的最后一次修改時間早于依賴的檔案,則產生警告資訊
	#pargma GCC poison 識別符號  表示將后面的標識設定成毒藥的意思,一旦使用識別符號,則產生錯誤或者警告資訊
	#pargma pack (整數n) 表示按照整數n的倍數進行對齊補齊,必須按照2的最小次方對齊補齊

6.預定義宏

__FILE__  表示獲取所在的檔案名(使用 %s 列印輸出)
__BASE_FILE__  表示獲取正在編譯的原檔案名(使用 %s 列印輸出)
__LINE__  表示獲取所在行號(使用 %d 列印輸出)
__FUNCTION__/__func__  表示獲取所在函式名稱(使用 %s 列印輸出)
__DATE__  獲取日期資訊(使用 %s 列印輸出)
__TIME__  獲取時間資訊(使用 %s 列印輸出)

7.環境變數的概念和使用

環境變數: 存放和編程環境/系統環境相關資訊的變數
PATH/path 就是一個環境變數,存放各種路徑,在 PATH/path 中存放路徑的程式不需要在增加路徑就可以直接運行
編程相關的環境變數:
	CPATH/C_INCLUDE_PATH  主要表示C語言中頭檔案的所在路徑
	CPLUS_INCLUDE_PAHT  主要表示C++頭檔案所在路徑
	LIBRARY_PATH  編譯鏈接時查找靜態庫和共享庫的路徑
	LD_LIBRARY_PATH  運行時查找共享庫的路徑
查找頭檔案的方式:
	(1) #include <>
		表示去系統默認的路徑中查找指定的頭檔案
	(2) #include ""
		表示去當前作業目錄中進行查找
	(3) 配置環境變數 CPATH 進行查找
		export CPATH=$CPATH:頭檔案所在路徑
	(4) 使用編譯選項進行查找(重點)
		gcc/cc  xxx.c  -l  頭檔案所在的路徑

二、linux系統下的編程基礎和開發方式

1.庫檔案的概念和使用

(1)靜態庫
	靜態庫檔案在使用時,直接將呼叫的功能代碼復制到目標檔案
	缺點:造成目標檔案變大,不利于修改和維護
	優點:不需要跳轉,所以效率比較高,不依賴于靜態庫檔案
(2)共享庫
	共享庫檔案在使用時,將所呼叫功能代碼在共享庫檔案中的地址拷貝到目標檔案中
	缺點:需要跳轉,所以效率比較低,依賴于共享庫檔案的存在
	優點:目標檔案比較小,修改和維護比較方便

2.靜態庫的生成和呼叫

靜態庫檔案的生成步驟:
	(1) 撰寫原始碼程式 xxx.c(例如 add.c)
	(2) 只編譯不連接,生成目標檔案 xxx.o(例如 add.o)
	(3) 使用 ar -r 命令生成靜態庫檔案
		ar -r  lib庫名.a  目標檔案1  目標檔案2  ...
		lib庫名.a  叫做靜態庫檔案名
		例如:  ar -r  libadd.a  add.o
靜態庫檔案的呼叫步驟:
	(1) 撰寫呼叫庫檔案的原始碼 xxx.c(例如 main.c)
	(2) 只編譯不鏈接生成目標檔案 xxx.o(例如 mian.o)
	(3) 鏈接測驗程式和庫檔案,方法有三種:
		1) 直接鏈接
			gcc/cc  main.o  libadd.o
		2) 通過編譯器選項進行間接鏈接
			gcc/cc  main.o  -l  庫名  -L  庫檔案所在的路徑
		3) 配置環境變數 LIBRARY_PAHT 進行鏈接
			export LIBRARY_PATH=$LIBRARY_PAHT:.
			gcc/cc  main.o  -l  庫名

3.共享庫的生成和呼叫

共享庫檔案的生成步驟
	(1) 撰寫源程式 xxx.c(例如 add.c)
	(2) 只編譯不鏈接,生成目標檔案 xxx.o(例如 add.o)
		gcc/cc  [-fpic]/*小模式選項,希望目標檔案越小越好*/  add.c
	(3) 生成共享庫檔案
		gcc/cc  -shared  xxx.o  -o  lib庫名.so
		例如: gcc/cc  -shared  xxx.o  -o  libadd.so  
共享庫檔案的呼叫步驟
	(1) 撰寫呼叫庫檔案的源程式 xxx.c(例如: main.c)
	(2) 只編譯不鏈接,生成目標檔案 xxx.o(例如: main.o)
		gcc/cc  -c  main.c
	(3) 鏈接測驗程式和庫檔案,方法有三種:
		1) 直接鏈接
			gcc/cc  main.o  libadd.so
		2) 通過編譯器選項進行間接鏈接
			gcc/cc  main.o  -l  庫名  -L  庫檔案所在的路徑
		3) 配置環境變數 LIBRARY_PATH 進行鏈接
			export  LIBRARY_PATH=$LIBRARY_PATH:.
			gcc/cc  main.o  -l  庫名

4.共享庫動態加載

(1)dlopen 函式
	打開共享庫檔案
	函式: void * dlopen( const char * pathname, int mode);
	引數一: 字串形式的共享庫檔案名
	引數二: 加載標志
		RTLD_LAZY 延遲加載
		RTLD_NOW 立即加載
	回傳值: 
		失敗回傳: NULL
		成功回傳: 該共享庫對應的句柄/地址
(2)dlerror 函式
	排查顯示出錯的資訊
	函式: char * dlerror(void);
	回傳值: 
		當元件操作函式執行失敗時,dlerror可以回傳出錯資訊,回傳值為NULL時表示操作函式執行成功
(3)dlsym 函式
	根據引數指定的句柄和函式名,回傳函式名所對應的記憶體地址
	函式: void * dlsym(void*handle,constchar*symbol);
	引數一: 共享庫句柄,dlopen的回傳值
	引數二: 字串型別的符號,也就是函式名
	回傳值:
		函式的地址
(4)dlclose 函式
	關閉引數指定的共享庫句柄,也就是關閉共享庫
	函式: int dlclose (void *handle);

5.C語言的錯誤處理

return  0;   表示程式正常結束
return  -1;   表示程式不正常結束
 
1.錯誤表示的一般規則(是否出錯)
	C語言中通過使用回傳值來表示是否出錯,根據回傳值來進行具體的錯誤處理
   	(1) 如果回傳值型別是int型,并且回傳的值不可能是負數時則使用回傳值-1代表出錯,其他資料型別表示正常回傳
   	(2) 如果回傳值型別是int型,并且回傳值可能是負數時,則需要使用指標取出回傳的資料,回傳值僅僅表示是否出錯,-1 表示出錯,0 表示正常回傳
   	(3) 如果回傳值型別是指標型別,則回傳NULL代表出錯
   	(4) 如果不考慮是否出錯,回傳值型別使用void即可
   	
2.錯誤編號和錯誤資訊(為什么錯了)
	#include<errno.h> 頭檔案
	errno 是一個全域變數,當函式呼叫失敗時,會將具體的錯誤編號設定到errno中可以在通過error來獲取錯的原因
	
3.錯誤資訊
	(1) strerror函式  表示字串錯誤,這個函式主要用于將引數指定的錯誤編號翻譯成對應的錯誤資訊回傳
	(2) perror函式  表示最后一個錯誤資訊大印出來,引數s不為空時原樣輸出,后面追加一個冒號和空格,再跟著錯誤資訊以及換行
	(3) printf函式  printf("%m");  列印錯誤資訊

注意:
判斷函式的呼叫是否成功,還是需要根據回傳值進行判斷,而在確定已經呼叫失敗的情況下,這時可以通過errno來獲取錯誤的原因,也就是不能直接使用error來判斷函式的呼叫是否成功

6.環境表的概念和使用

1.環境表的概念
	環境表 是指環境變數的集合,而每個行程都擁有一張獨立的環境表,來保存和當前行程相關的環境變數資訊
	環境表采用字符指標陣列來存盤所有的環境變數,使用全域變數 char** environ 來記錄環境表的首地址,使用NULL來代表環境表的結束,所以訪問環境表則需要借助 environ 變數
	
2.環境表相關的處理

	(1) getenv 函式 
	函式: char *getenv(const char *name);
	表示根據引數指定的環境變數名去環境表中進行查找,回傳該環境變數所對應的環境值,查找失敗則回傳NULL

	(2) setenv 函式  
	函式: int setenv(const char *name, const char *value, int overwrite);
	第一引數 環境變數名 
	第二引數 環境變數值 
	第三引數 是否修改,如果引數指定的環境變數不存在則增加,如果存在并且overwrite 是非0,則修改環境變數值,是否環境變數不變

	(3) putenv 函式 
	函式: int putenv(char *string);
	表示按照引數的內容增加/修改環境變數,其中string的格式為: name=value, 如果不存在則添加,存在則修改

	(4) unsetenv 函式 
	函式: int unsetenv(const char *name);
	表示根據引數指定的環境變數去環境表中進行洗掉

	(5) clearenv 函式 
	函式: int clearenv(void);
	表示清空整個環境表

3.主函式的原型
	int main(int argc,char* argv[],char* envp[]){}
	第一個引數:命令列引數的個數
	第二個引數:命令列引數的地址資訊
	第三個引數:環境表的首地址

三、linux系統下的記憶體管理

1.程式和行程的概念

	程式:表示存放在硬碟上的可執行檔案
	行程:表示在記憶體中正在運行的程式

2.行程中的記憶體區域劃分 (記憶體地址從小到大,其中堆和堆疊沒有明確的分割線,可以適當的調整)

	(1) 代碼區       存放程式的功能代碼的區域  例如:函式名
	(2) 只讀常量區   主要存放字串常量和const修飾的全域變數
	(3) 全域區       主要存放已經初始化的全域變數和static修飾的區域變數
	(4) BSS段        主要存放沒有初始化的全域變數和static修飾的區域變數
	(5) 堆區         主要表示使用 malloc/calloc/realloc 等手動申請的動態記憶體空間,記憶體由程式員手動申請手動釋放
	(6) 堆疊區         主要存放區域變數(包括函式的形參),const修飾的區域變數,以及塊變數,該記憶體區域由作業系統自動管理

3.字串存盤形式之間的比較

	對于一個存盤常量字串的字符指標和字符陣列來說,字符指標可以改變指向,不可以改變指向的內容,而字符陣列可以改變指向的內容,不可以改變指向
	對于一個存盤常量字串的動態記憶體空間來說,其中指向該記憶體空間的指標,既可以改變指向,又可以改變內容

4.虛擬記憶體管理技術

	unix/Linux系統的記憶體都是采用虛擬記憶體管理技術來進行管理的,
	即:每個行程都有0~4G的記憶體地址 (虛擬的,并不是真實存在的),由作業系統負責把記憶體地址和真實的物理記憶體映射起來.
	因此,不同行程的記憶體地址看起來是一樣的,但是所對應的物理記憶體是不一樣的
	每個行程中0~4G的虛擬地址空間分為: 用戶空間和內核空間. 
	用戶空間指0~3G虛擬地址空間,而內核空間指3G~4G的虛擬地址空間. 
	用戶程式運行在用戶空間,內核空間只有系統內核才能訪問,用戶程式不能直接訪問內核空間,
	不過系統內核提供了一些系統函式負責從用戶空間切換到記憶體空間
	記憶體地址的基本單位是位元組,記憶體映射的基本單位是記憶體頁,目前主流的作業系統中一個記憶體頁是4kb (4096位元組)
	1Tb=1024Gb
	1Gb=1024Mb
	1Mb=1024Kb
	1Kb=1024byte (位元組) 1位元組= 8位 
	1byte=8個bit (二進制位)

5.段錯誤的由來

	(1) 使用scanf函式時缺少 &
	(2) 空指標/野指標的使用
	(3) 試圖使用一個沒有經過映射的虛擬地址可能引發段錯誤

	STL(標準模版庫)   - 申請/釋放動態記憶體
	new/delete       - 申請/釋放動態記憶體,c++語言中的運算子
	malloc()/free()  - 申請/釋放動態記憶體,標c函式
	sbrk()/brk()     - 申請/釋放動態記憶體,UC函式
	mmap()/munmap()  - 建立/解除 到記憶體的映射

6.使用malloc 申請動態記憶體的特性

	(1) 使用malloc 申請記憶體的注意事項
		使用malloc申請動態記憶體時,可能還需要額外的12個位元組來存盤一些用于管理動態記憶體的資訊,比如記憶體的大小等
		malloc底層采用鏈表的形式去處理多個記憶體塊,也就是需要保存有關 下一個記憶體塊/上一個記憶體塊 的資訊
		使用malloc申請的動態記憶體,千萬不要越界訪問,因為極有可能破壞管理資訊,從而引發段錯誤
	(2) 使用malloc 申請記憶體的一般映射規則
		一般來說,使用malloc申請比較小的動態記憶體時,作業系統會一次性分配33個記憶體頁,從而提高效率

7.使用free 釋放動態記憶體的特性

	一般來說,使用malloc申請比較大的記憶體時,系統會默認分配34個記憶體頁,
	當申請的記憶體超過34個記憶體頁時,則系統會再次分配33個記憶體頁(也就是按照33個記憶體頁的整數倍進行配)
	使用free釋放動態記憶體時,釋放多少則在動態記憶體總數中減去多少,
	當所有的記憶體釋放完畢時,行程還保留33個記憶體頁備用,知道行程結束,主要是為了提高效率

8.記憶體處理的相關函式

	(1) getpagesize函式
		函式: int getpagesize(void);
		主要用于獲取系統中一個記憶體頁的大小,一般為4kb
		
	(2) sbrk 函式
		函式: void *sbrk(intptr_t increment);
		主要用于按照引數指定的大小來調整記憶體塊的大小,
		如果引數大于0表示申請記憶體,如果引數等于0表示獲取記憶體塊的當前位置,
		如果引數小于0表示釋放記憶體,成功回傳之前記憶體塊的地址,失敗回傳-1
		sbrk操作記憶體的一般規則:
		申請比較小的記憶體時,一般會默認分配1個記憶體頁,
		申請的記憶體超過1個記憶體頁時,會再次分配1個記憶體頁,
		釋放記憶體時,釋放完畢后剩余的記憶體如果在一個記憶體頁內,則一次性釋放1個記憶體頁
		
	(3) brk 函式
		函式: int brk(void *addr);
		表示操作記憶體的末尾地址到引數指定的位置,
		如果引數指定的位置大于當前的末尾位置,則申請記憶體,如果引數指定的位置小于當前的末尾位置,則釋放記憶體
		
	(4) mmap 函式
		函式: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
		第一個引數:建立映射的起始地址,給NULL 由系統內核選擇
		第二個引數:建立映射的大小 
		第三個引數:映射的權限
        	PROT_EXEC  - 可執行
        	PROT_READ  - 可讀
       		PROT_WRITE - 可寫
        	PROT_NONE  - 不可訪問
    	第四個引數: 映射的模式
        	MAP_SHARED    - 共享的
        	MAP_PRIVATE   - 私有的
        	MAP_ANONYMOUS - 映射到物理記憶體
    	第五個引數:檔案描述符,映射物理記憶體給0即可
    	第六個引數:檔案偏移量,映射物理記憶體給0即可
    	回傳值 :成功回傳映射的地址,失敗回傳MAP_FAILED (-1)
    	函式功能:建立檔案/設備  到記憶體映射
 
	(5) munmap函式
		函式: int munmap(void *addr, size_t length);
		第一個引數:映射的地址
		第二個引數:映射的大小
		函式功能:洗掉指定的映射

四、linux系統下的檔案管理和目錄操作

1.基本概念

	linux/unix系統中,幾乎所有的一切都可以統稱檔案,因此,對于檔案的操作幾乎適合所有的設備等等,目錄也可以看作檔案處理
	/dev/null				空設備
	echo  字串				表示原樣輸出字串內容
    echo 字串>檔案名   	表示寫入字串到檔案
    echo 字串>/dev/null	表示丟棄結果資訊
    cat  /dev/null>檔案名	表示清空檔案
    /dev/tty				輸入輸出設備,一般默認為終端(了解)
    echo 字串>/dev/tty		表示輸出到輸入輸出設備
    cat  /dev/tty			表示讀取/列印輸入輸出設備內容

2.檔案的相關處理函式

	(1) open 函式
		函式: int open(const char *pathname, int flags, mode_t mode);
         第一個引數:字串形式的路徑和檔案名
         第二個引數:操作標志 必須包含以下訪問權限中的一個:
         	O_RDONLY - 只讀
         	O_WRONLY - 只寫
         	O_RDWR   - 可讀可寫
         還可以按位或上以下標志中的一個:
         	O_CREAT   - 檔案存在則打開,不存在則創建
         	O_EXCL    - 與O_CREAT搭配使用,如果存在則創建失敗
         	O_TRUNC   - 檔案存在,是個規則檔案,打開方式有寫權限,則清空檔案
         	O_APPEND  - 追加
         第三個引數:操作模式用于指定創建的新檔案權限,如:0644   查找權限  ls -l 檔案名
         回傳值: 成功回傳一個新的檔案描述符,失敗回傳-1,檔案描述符就是一個非負整數,用于代表一個打開的檔案
    (2) close 函式
    	函式: int close(int fd);
    	引數: 檔案描述符  
    (3) read 函式
    	函式: ssize_t read(int fd, void *buf, size_t count);
    	第一個引數:檔案描述符 (資料從哪里讀取)
    	第二個引數:緩沖區的首地址 (資料存到哪里去)
    	第三個引數:讀取的資料大小
    	回傳值:成功回傳讀取到的資料大小,失敗回傳-1
    (4) write 函式
    	函式: ssize_t write(int fd, const void *buf, size_t nbyte);
    	第一個引數:檔案描述
    	第二個引數:偏移量
    	第三個引數:從什么地方開始偏移
        	SEEK_SET  -  檔案的起始位置
            SEEK_CUR  -  檔案的當前位置
            SEEK_END  -  檔案的尾部位置
        回傳值: 成功回傳當前位置距離檔案頭的偏移量,失敗回傳-1

3.檔案描述符

	檔案描述符本質就是一個整數,可以代表一個打開檔案.
	但是檔案的資訊并不是保存在檔案描述符中,而是存在檔案表等結構中,使用open函式打開一個檔案時,會把檔案愛的資訊放入檔案表等結構中,
	但是處于安全和效率等因素的考慮,檔案表等結構不適合直接操作,而是給檔案表對應一個編號,使用編號進行操作,這個編號就是檔案描述符
	系統還會管理檔案描述符,在每個行程中都會有一張描述符總表,當有新的檔案描述符需要時,會去總表中查找未使用的最小值并且回傳.
	檔案描述符本質就是非負整數,也就是從0開始,一直OPEN_MAX(在linux系統中一般是255),其中0 1 2被系統占用,分別代表標準輸入,標準輸出以及標準錯誤
	
	注意:
		打開不同的檔案時,對應的問價表和v節點表資訊都不同,而多次打開相同檔案時,v節點表資訊相同,檔案表資訊不同close()函式的作業方式:
	先把檔案描述符與檔案表的對應關系解除,不一定會洗掉檔案表,只有當檔案表沒有與其他描述符對應時才會洗掉檔案表(一個檔案表可以對應多個描述符),close()函式也不會修改描述符的整數值,但是會讓一個描述符無法代表一個檔案 

4.檔案的非讀寫函式

	(1) dup 函式
		函式: int dup(int oldfd);
		表示根據引數指定的檔案描述符進行拷貝,成功回傳新的檔案描述符,失敗回傳-1
		
	(2) dup2 函式
		函式:int dup2(int oldfd, int newfd);
		表示將引數newfd作為引數oldfd的拷貝,如果有必要,則先關閉newfd,成功回傳新描述符,也就是newfd,失敗回傳-1
		
	(3) fcntl 函式  
	根據檔案描述符對檔案執行的操作:
    	a. 復制檔案描述符
        b. 設定/獲取檔案描述符的標志(了解)
        c. 設定/獲取檔案狀態的標志(了解)
        d. 實作檔案鎖的功能(掌握)
	函式: int fcntl(int fd, int cmd, ... /* arg */ );
		第一個引數:檔案描述符
		第二個引數: 操作的命令
        	F_DUPFD - 復制檔案描述符的功能,尋找最小的有效的大于等于第三個引數arg的描述符作為新的描述符,與dup2()函式所不同的是,不會強制關閉已經被占用的描述符       fcntl(fd,F_DUPFD,5);
        	F_GETFD/F_SETFD  -  獲取/設定檔案描述符的標志
        	F_GETFL/F_SETFL  -  獲取/設定檔案狀態的標志
       		F_SETLK/F_SETLKW/F_GETLK - 加鎖/解鎖/測驗鎖是否存在
		第三個引數:可變長引數,引數是否需要,主要取決于引數cmd
		回傳值:
			F_DUPFD  - 成功回傳新的檔案描述
			F_GETFD  - 成功回傳檔案描述符的標志值
			F_GETFL  - 成功回傳檔案狀態的標志值
			其他操作成功回傳0,所有的操作失敗回傳-1

	(4)使用fcntl 函式實作檔案鎖功能
		當使用多個行程同時讀寫檔案時,可能會引發檔案的混亂,如果左右的行程都是讀檔案,則可以同時進行,但是只要有一個進行程執行寫操作,則多個行程應該串行操作而不是并行,使用檔案鎖實作上面的想法,檔案鎖就是讀寫鎖,一把讀鎖和一把寫鎖,其中讀鎖是一把共享鎖,允許其他行程加讀鎖,不允許加寫鎖,寫鎖是一把互斥鎖,不允許其他行程加讀鎖和寫鎖
		使用檔案鎖的功能時:
			第二個引數的取值
				F_SETLK/F_SETLKW/F_GETLK  - 加鎖/解鎖/測驗鎖是否存在 
			第三個引數取值:指定以下結構體型別的指標(一般使用的時候用 &取結構體的地址)
		struct flock 
		{         ...
		    short l_type;    /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */ /*鎖的型別*/
		    short l_whence;  /* How to interpret l_start:SEEK_SET, SEEK_CUR, SEEK_END */  /*表示從什么地發開始*/
		    off_t l_start;   /* Starting offset for lock *//*偏移量*/
		    off_t l_len;     /* Number of bytes to lock *//*鎖定的位元組數*/
		    pid_t l_pid;     /* PID of process blocking our lock(F_GETLK only) *//*加鎖的行程號 , 給 -1  */
		               ...
		 };

		1)F_SETLK 的使用    主要用于加鎖/解鎖 的功能	
	 		測驗結果:加完讀鎖之后,還是可以向檔案寫入資料的,結果說明鎖是獨立于檔案的,并沒有真正鎖定對檔案的讀寫操作,也就是說鎖只能鎖定其他的鎖換句話說,如果加了一把鎖,可以導第二個加鎖失敗(兩個讀鎖除外)
		如何使用檔案鎖來控制是否可以對檔案進行讀寫操作,
	  	實作方案:在執行讀操作之前嘗試加讀鎖,在執行寫操作之前嘗試加寫鎖,根據能不能枷鎖成功來決定是否進行讀寫操作即可,      
	    	釋放檔案鎖:
	    	a.行程結束,自動釋放所有檔案鎖
	    	b.將檔案鎖的型別設定為F_UNLCK,使用fcntl 重新設定來實作解鎖的效果
		2)F_SETLKW 的使用   功能與F_SETLK類似,所不同的是,加不上鎖會等待,直到鎖能加上為止
		3)F_GETLK 的使用   測驗一下引數鎖能否加上,如果能加上,則不會去加鎖,而是將鎖的型別改成F_UNLCK;如果不能加上,則見將檔案中已經存在的鎖的資訊通過引數鎖帶出來,并且將l_pid設定為真正給檔案枷鎖的行程號,所以可以使用l_pid判斷鎖是否能加上

	(5)stat/fstat函式
		函式: int stat(const char *pathname, struct stat *statbuf);
		函式: int fstat(int fd, struct stat *statbuf);
		函式功能:獲取指定檔案的狀態資訊
		第一個引數:檔案的路徑/檔案描述符
		第二個引數:結構體指標,結構體變數的地址
		  struct stat 
		   {
		    ...
		     mode_t  st_mode;  /*檔案的型別和權限*/
		     off_t   st_size;  /*檔案的大小*/
		     time_t  st_mtine; /*檔案的最后一次修改時間*/
		    ...
		   };
	   
		  擴展:
		  #include<time.h>
		  char *ctime(const time_t *timep);     =>主要用于將整數型別的時間轉換為字串形式的時間 
		  struct  tm *localtime(const time_t *time);    =>主要用于將整數形式的時間轉換為結構體的指標型別
		  結構體的型別:
		  struct tm {
		               int tm_sec;         /* seconds 秒*/
		               int tm_min;         /* minutes 分鐘*/
		               int tm_hour;        /* hours 小時*/
		               int tm_mday;        /* day of the month 日*/
		               int tm_mon;         /* month 月    +1     */
		               int tm_year;        /* year 年     +1900  */
		               int tm_wday;        /* day of the week 星期幾*/
		               int tm_yday;        /* day in the year 年中的第幾天  +1*/
		               int tm_isdst;       /* daylight saving time  夏令時 */
		           }; 
	           
	  (6)access函式 
		函式:int access(const char *pathname, int mode);  
		函式功能:主要用于檔案是否存在以及對應的權限
    	第一個引數:檔案的路徑和檔案名
    	第二個引數:操作模式
              F_OK  判斷檔案是否存在
              R_OK  判斷檔案是否可讀
              W_OK 判斷檔案是否可寫
              X_OK  判斷檔案是否可執行 

	(7)chmod 函式 
     	函式功能:主要用于將引數指定的檔案權限修改為引數二指定的值
 	
	(8)truncate 函式  
    	函式功能: 主要用于將引數一指定的檔案大小截取到引數二指定的大小,如果檔案變小則多余資料丟失,如果檔案變大則擴展出來的區域用"\0"填充
	
	(9)umask 函式   
	    函式功能: 主要用于設定創建檔案時需要屏蔽的權限,回傳之前屏蔽的權限

	(10)其他處理函式:
	    link()    主要用于創建硬鏈接
	    unlink()  主要用于洗掉硬鏈接 
	    rename()  主要用于重命名
	    remove()  主要用于洗掉指定的檔案

5.目錄管理

	常用的函式
        (1) opendir 函式   
        	函式: DIR *opendir(const char *name);
        	函式功能: 主要用于打開引數指定目錄,并且回傳該目錄所在地址,
        (2) readdir 函式    
        	函式: struct dirent *readdir(DIR *dirp);
        	函式功能: 主要用與讀取引數指定的目錄中內容,回傳結構體指標,
            struct dirent {
             	ino_t    d_ino;       /* inode number i節點的編號*/
             	off_t     d_off;       /* offset to the next dirent 距離下一個子項的偏移量*/
             	unsigned short d_reclen;    /* length of this record 記錄的長度*/
             	unsigned char  d_type;     /* type of file; not supportedby all file system types 檔案的一個型別*/
             	char    d_name[256];     /* filename 檔案名*/
          	};
          	
       (3) closedir 函式  
           函式功能: 主要用于關閉引數指定的目錄,
       
       (4) 其他函式:
        	mkdir() 創建一個目錄
        	rmdir() 洗掉一個目錄
            chdir() 切換所在的目錄
            getcwd () 獲取當前程式所在的作業目錄

五、linux系統下的行程管理

1. 基本概念

     行程 表示在記憶體中運行的程式
     程式 表示在磁盤上運行的可執行檔案

2. 基本命令

	ps  表示察看當前終端上啟動的行程(行程的快照)
	ps 命令的執行結果如下:
		PID - 行程號(重點)
		TTY - 終端的編號
		TIME - 消耗cpu的時間
		CMD - 命令的名稱和引數   
		          
	ps - aux          表示顯示所有包含其他使用者的行程 
	ps - aux | more    表示將ps - aux 的結果進行分屏顯示 
	ps - aus |more 執行的結果如下:
		USER   行程的屬主(熟悉)
		PID    行程編號(掌握)
		%CPU   占用CPU的百分比
		%MEM   占用記憶體的百分比
		VSZ    虛擬記憶體的大小
		RSS    物理記憶體的大小
		TTY    終端編號
		STAT   行程的狀態資訊(熟悉)
		START  行程的啟動時間
		TIME   消耗CPU的時間
		CMD    命令的路徑和名稱以及引數(掌握)

	ps - ef 表示以全格式的方式顯示當前所有的行程
	ps - ef | more 分屏顯示命令的執行結果
	ps - ef | more的執行結果:
		PPID - 父行程的行程號 
	常見的行程狀態:
		S 休眠狀態
		s 行程的領導者(擁有子行程)
		Z 僵尸行程
		R 正在運行的行程
		O 可運行的行程
		T 掛起狀態
		< 優先級高
		N 優先級低
		...
	目前主流的作業系統都支持多行程,如果行程A啟動了行程B,那么行程A叫做行程B的父行程,而行程B叫做A的子行程 
	行程0是系統內部的行程,負責啟動行程1(init),也會啟動行程2,而且其他所有的行程都是 行程1/行程2,直接/間接 地啟動起來

3.各種ID的獲取

	PID   - 行程號,是行程的唯一標識,作業系統采用延遲重用的策略來管理行程號,保證在每一個時刻PID都唯一
	PPID  - 父行程號,與行程號的使用策略相同
	關于ID 的函式:
		getpid()  - 獲取行程號
		getppid() - 獲取副行程號
		getuid()  - 獲取用戶ID
		getgid()  - 獲取用戶組ID

4.行程相關函式

	創建:
		(1) fork函式  
			函式功能:主要用于以復制正在呼叫行程的方式去創建一個新的行程,新行程叫做子行程原來的行程叫做父行程,成功時父行程回傳子行程的ID,子行程回傳0,失敗時回傳-1 
        fork 創建子行程的代碼執行方式是:
			a.  fork 之前的代碼,父行程執行一次
			b.  fork 之后的代碼,父子行程各自執行一次
			c.  fork 函式的回傳值,父子行程各自回傳一次
        注意事項:fork 創建成功子行程之后,父子行程各自獨立,并沒有明確的先后執行順序
        父子行程的關系:
			a. 父行程啟動了子行程,父行程同時啟動,如果子行程先結束,則父行程負責幫助回收子行程的資源
			b.如果父行程先結束,子行程會變成孤兒行程,子行程變更父行程(重新認定父行程,一般選擇 init(1) 行程作為父行程), init行程也叫做孤兒院
			c.如果子行程先結束,但是父行程由于各種原因沒有回收子行程的資源,子行程變成僵尸行程
        父子行程中記憶體資源的關系:
        	使用fork創建的子行程,會復制父行程中除了代碼區之外的其他記憶體區域,代碼區和父行程共享  
    	
    擴展:
        a.如何創建出4個行程?
			fork();
			fork();
			4個行程: 1個父行程,2個子行程,1個孫子行程
		b.如何創建出3個行程?
			pid_t pid = fork();
			if(0 !=  pid)  //父行程
			{
				fork();
			} 
			3個行程:1個父行程 + 2 個子行程
		c. 俗稱 fork 炸彈
			while(1)
			{
				fork();
			}
			
		行程的一個終止:
			正常終止行程的方式:
				a. 在main函式中執行了return0;
				b. 呼叫exit()函式終止行程 
				c. 呼叫_exit()/_Exit()函式
				d. 最后一個執行緒回傳
				e. 最后一個執行緒呼叫了pthrread_exit()函式
			非正常終止的方式:
				a. 采用信號終止行程
				b. 最后一個執行緒被其他執行緒取消
			
	退出:
		(2) _exit/_Exit 函式(uc的函式/標c的函式)  
			函式功能:這兩個函式都用于立即終止正在呼叫的行程,引數作為回傳值回傳給父行程,來代表行程的退出狀態,可以使用wait 系列函式獲取推出狀態
			
		_exit 函式  
			函式功能:主要用于引起正常行程的終止,引數status中的低8位作為退出狀態資訊回傳給父行程,該函式在終止行程期間會呼叫atexit()/on_exit()函式注冊過的函式
		
		atexit 函式  
			函式功能:主要用于按照引數指定的函式進行注冊,注冊過的函式會在正常行程終止時被呼叫
		
	等待:
		(3) wait 函式   
			函式功能:主要用于掛起正在運行的行程進入組塞狀態,直到有一個子行程終止,引數用于獲取終止行程的退出狀態,成功回傳終止行程的行程號,失敗回傳-1
		WIFEXITED(*status) 判斷是否正常終止
		WEXITSTATUS(*status) 獲取行程退出狀態的資訊
		
		(4) waitpid 函式    
			函式功能:掛起當前正在運行的行程,直到指定行程的狀態發生改變為止
			第一個引數:行程號 
             	< -1 表示等待行程的組ID為pid絕對值的任意一個子行程(了解)
                -1   表示等待任意一個子行程
                0    表示等待和呼叫行程在同一個行程組的任意一個子行程(了解)
                > 0  表示等待行程號為pid的行程
            第二個引數: 指標引數,獲取行程的推出狀態資訊
            第三個引數: 選項 默認給0即可
            回傳值: 成功回傳狀態發生改變的行程號,失敗回傳-1
            
		(5) 其他處理函式
			vfork 函式  
				函式功能:功能與fork函式基本一樣,所不同的是不會拷貝父行程的記憶體區域,而是直接占用,導致父行程進入阻塞狀態,直到子行程終止,或者呼叫exec系列函式跳出為止,對于子行程的終止建議使用_exit()函式
			exec系列函式: 
			execl 函式   函式功能:主要用于實作跳轉的功能 
				第一個引數:執行的檔案路徑及檔案名
				第二個引數:執行的選項,一般給可執行檔案的執行方式
				第三個引數:可變長引數
		注意:
		vfork 函式本身沒有太大的實際意義,一般與exec系列函式搭配使用,
		fork 函式也可以和exec系列函式搭配使用,但是基本不會這樣用,
		system 函式   
			函式功能:  主要用于執行指定的shell命令,以及shell腳本

		shell 腳本撰寫流程:
			a.  vi xxx.sh  檔案
			b.  撰寫shell指令到檔案中
			c.  給xxx.sh 檔案增加執行權限   chmod a+x shell.sh
			d.  執行xxx.sh檔案 

中斷的概念:

	中斷指暫時停止當前程式的執行,轉而去執行新的程式,或者處理出現的意外情況
	中斷分為兩種:軟體中斷 和 硬體中斷

六、linux系統下的信號處理

1.信號的基本概念和分類

	(1)概念:
		信號本質上就是軟體中斷,信號既可以作為行程間通信的一種機制,更重要的是,信號總是中斷一個行程的正常運行,而信號更多的用于處理一些非正常情況
		
	(2)特點:
		a. 信號是異步的,行程并不知道信號什么時候會到來
		b. 行程即可以發送信號,也可以處理信號
		c. 每個信號都有一個名字,這些名字以SIG開頭
		
    (3)命令和分類:
		使用命令: kill -l 用于察看當前作業系統所支持的信號
		
	掌握信號:
		信號2   SIGINT   使用ctrl + c 產生此信號
		信號3   SIGQUIT  使用ctrl + \ 產生此信號
		信號9   SIGKILL   使用kill -9 行程號發送此信號(該信號不能被用戶捕捉)
		一般來說, 在linux系統中信號是從1~ 64, 不保證連續, 其中1~31之間的信號, 叫做不可靠信號, 也就是信號不支持排隊, 可能會丟失. 其中34~64 之間的信號叫做可靠信號, 也就是信號支持排隊, 不會丟失.
		不可靠信號有叫做非實時信號,可靠信號又叫做事實信號

2.信號的處理方式

	(1)默認處理,絕大多數信號的處理方式都是終止行程
	(2)忽略處理
	(3)自定義處理

3.信號的處理函式

	(1)signal 函式    
		函式的功能:  設定指定信號的指定處理方式
			#include <signal.h>
			typedef void (*sighandler_t)(int);   
				=> 給函式指標其個別名 叫做 sighandler_t
				=> typedef void (*p) (int) sighandler_t;  
			sighandler_t signal(int signum, sighandler_t handler);
				展開后是這樣 =>  
			void (*)(int) signal(int signum,void(*)(int)handler);     
				繼續展開后是這樣 =>  
			void (*)(int) signal(int signum,void(*hander)(int)); 
				最后展開后是這樣 =>  
			void (*signal(int signum,void(*hander)(int)))(int);

			首先 signal 是一個函式,具有兩個引數的函式,第一個引數是int型別,第二個引數是函式指標型別
			函式的回傳值型別也是函式指標型別
			函式指標型別是一個
			指向具有int型別引數和void作為回傳值型別的函式的指標

	    函式功能決議:
			第一個引數:信號值/信號名稱(處理那個信號)
			第二個引數:信號的處理方式(如何進行處理)
				SIG_IGN  忽略處理
				SIG_DFL  默認處理
				自定義函式地址   自定義處理
			回傳值: 成功回傳之前的處理方式,失敗回傳SIG_ERR 
 
		父子行程對信號的處理方式:
			對于fork函式創建的父子行程來說,子行程完全按照父行程的對信號的處理方式,也就是父行程忽略則子行程忽略,父行程自定義處理,則子行程自定義處理,父行程默認處理,則子行程默認處理

	采用系統函式發送信號
	(2) alarm 函式
		函式功能:主要用于設定引數指定的秒數之后發送SIGALRM,如果引數為0表示沒有設定新的鬧鐘.成功回傳上一個鬧鐘沒有來得及走的秒數,如果之前沒有鬧鐘,則回傳0

		信號集
        信號集:信號的集合用于存盤多個信號
        在linux系統中,信號的數值范圍:1~64,采用最省記憶體的方式來表示所有的信號,采用什么樣的資料資料型別呢?

		信號集的資料型別是:
			sigset_t 型別 底層還是采用每一個二進制代表一個信號的方式存盤多個信號 
			查找sigset_t 的步驟  cc -E 02set.c -o 02set.i  
		
			typedef struct
			{
				unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
			} __sigset_t; 

		信號集的基本操作:  
			sigemptyset()   清空信號集
			sigfillset()    填滿信號集
			sigaddset()     增加信號到信號集      
			sigdelset()     洗掉信號幾中的指定信號
			sigismember()   判斷信號是否存在
			
		信號的屏蔽
			sigprocmask 函式    
				函式功能: 主要用于檢查和改變要屏蔽的信號集
				第一個引數: 用什么養的方式屏蔽
					SIG_BLOCK: ABC+CDE =>ABCDE 
					SIG_UNBLOCK: ABC-CDE =>AB   
					SIG_SETMASK: ABC  CDE  =>CDE 
				第二個引數: 新的信號集
				第三個引數: 舊的信號集 用于帶出之前屏蔽的信號集

			sigpending 函式  
				函式的功能: 主要用于獲取在信號屏蔽的期間來過的信號,通過引數將來過的信號帶進去

			sigaction 函式 => signal函式的增強版  
				函式功能: 主要用于設定/改變信號的處理方式
					第一個引數: 信號值/信號的名稱 (設定哪個信號)
					(信號SIGKILL和SIGSTOP不能使用)
					第二個引數: 針對信號的新處理方式 
				
				struct sigaction {
					void (*sa_handler)(int);
					=> 函式指標用于設定信號的處理方式,
					=> 與signal函式中第二個引數相同, SIG_IGN  SIG_DFL 函式名
									
					void (*sa_sigaction)(int, siginfo_t *, void *);
					=> 函式指標,作為第二種處理信號的方式
					=> 是否使用該處理方式,依賴于sa_flags的值
 
					sigset_t  sa_mask;
					=> 用于設定在信號處理函式執行期間需要屏蔽的信號
					=> 自動屏蔽與正在處理的信號相同的信號
             
					int sa_flags;
					=> 處理標志
					=> 寫入 SA_SIGINFO 表示采用第二個函式指標處理信號
					=> 寫入 SA_NODEFER 表示解除對相同信號的屏蔽
					=> 寫入 SA_RESETHAND 表示自定義處理信號之后恢復默認處理方式

					void (*sa_restorer)(void);
					=>  保留成員,暫時不使用
				};
				
				第三個引數: 舊的處理方式(用于帶出針對信號之前的處理方式)
				SIGKILL和SIGSTOP兩個信號是不能自定義處理的,只能默認處理
				
				其中第二個函式指標的第二個引數型別如下:
				siginfo_t {
					int      si_signo;       /* Signal number */
					int      si_errno;       /* An errno value */
					int      si_code;        /* Signal code */
					int      si_trapno;      /* Trap number that caused  hardware-generated signal(unused on most architectures) */
					pid_t    si_pid;         /* Sending process ID *//發送信號的行程ID           
					uid_t    si_uid;         /* Real user ID of sending process */
					int      si_status;       /* Exit value or signal */
					clock_t  si_utime;        /* User time consumed */
					clock_t  si_stime;        /* System time consumed */
					sigval_t  si_value;        /* Signal value *//發送信號時的附加資料
					int      si_int;          /* POSIX.1b signal */
					void    *si_ptr;         /* POSIX.1b signal */
					int      si_overrun;     /* Timer overrun count; POSIX.1b timers */
					int      si_timerid;      /* Timer ID; POSIX.1b timers */
					void    *si_addr;        /* Memory location which caused fault */
					long     si_band;        /* Band event (was int in glibc 2.3.2 and earlier) */
					int      si_fd;          /* File descriptor */
					short    si_addr_lsb;     /* Least significant bit of address (since kernel 2.6.32) */
				} 

		sigqueue 函式          
			函式功能: 表示指向的行程發送指定的信號和附加資料
			第一個引數: 行程號(給誰發信號)
			第二個引數: 信號值(發送什么樣的信號) 
			第三個引數: 聯合型別,附加資料
			union sigval {
				int   sival_int; //整數
				void *sival_ptr; //地址 
			};

4.計時器

	在UNIX/linux系統中,作業系統會為每一個行程維護三種計時器:
	真實計時器,虛擬計時器,實用計時器;
	一般采用真實計時器進行作業,真實計時器采用發送SIGALRM信號進行作業的
	
	#include <sys/time.h>
	int getitimer(int which, struct itimerval *curr_value);
	int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
	
	第一個引數: 計時器的型別
		ITIMER_REAL     真實計時器,主要描述行程運行的真實時間,通過產生SIGALRM信號作業
		ITIMER_VIRTUAL  虛擬計時器,主要描述行程在用戶空間消耗的時間,通過產生SIGVTALRM信號作業
		ITIMER_PROF     實用計時器,主要描述行程在用戶空間和內核空間共同消耗的時間,通過產生SIGPROF信號作業
	
	第二個引數: 計時器的新值 
        struct itimerval 
        {
         	struct timeval it_interval;  /* next value */     間隔時間
         	struct timeval it_value;  /* current value */  啟動時間
        };
        struct timeval 
        {
         	long tv_sec;    /* seconds */       秒數
         	long tv_usec;   /* microseconds */  微秒(到秒為 10^6)
        };
        
	第三個引數: 用于獲取計時器的舊值
	函式功能: 用于獲取/設定計時器的數值

七、linux系統下的行程間通信

1.概念:

	兩個/多個行程間的資料的交換,叫做行程間的通信

2.行程間通信的方式

	(1)檔案
	(2)信號
	(3)管道
	(4)共享記憶體
	(5)訊息佇列(重點)
	(6)信號量集
	(7)網路 (重點)
	...
    其中 (4) (5) (6) 統稱為XSI IPC通信方式
	(X/open system interface Inter-process commucation)

3.使用訊息佇列實作行程間通信

	(1)概念:
		使用不同的行程將發送的資料打包成具體個格式的訊息,然后將訊息放入到訊息中,使用其他行程從訊息中取出訊息,從而實作行程間的通信
		
	(2) 使用訊息佇列通信的流程
		a.獲取key值 使用ftok函式
		b.創建/獲取訊息佇列,使用msgget函式
		c.發送訊息/接受訊息,使用msgsnd和msgrcv函式
		d.如果不再使用訊息佇列,使用msgctl函式洗掉訊息佇列
    
    (3) 相關函式決議
		ftok 函式  
			函式功能: 根據路徑和專案ID 來生成一個key_t型別的key值,生成的key提供給后續函式使用
			第一個引數: 字串形式的路徑要求存在并且可以訪問
			第二個引數: 專案ID 要求非0
			注意: 使用相同的路徑和相同的專案ID 會生成相同的key值
			
		msgget 函式  
			函式功能: 主要用于創建/獲取訊息佇列,回傳佇列的ID
			第一個引數:key值,ftok的回傳值
			第二個引數:標志
				IPC_CREAT  - 創建
				IPC_WXCL   - 與IPC_CREAT搭配使用,如果存在則創建失敗
				0          - 獲取已存在的訊息佇列
			注意: 如果需要創建一個新的訊息佇列時,那么需要在引數msgflg中指定新佇列的權限,如0644
			
		msgsnd函式 
			函式功能:主要用于將指定的訊息發送到指定的訊息佇列中
			第一個引數: 訊息佇列的ID msgget函式的回傳值
			第二個引數: 訊息的首地址(訊息從哪里來) 
				struct msgbuf {
					long mtype;       /* 訊息的型別, must be > 0 */
					char mtext[1];     /* 訊息的資料內容,可以是其他的結構 */
				};
			第三個引數: 訊息的大小 主要是指訊息內容的大小,不包括訊息的型別
			第四個引數: 發送訊息的標志,直接給0即可
			
		msgrcv 函式  
			函式功能: 從指定的訊息佇列中接受訊息
			第一個引數: 訊息佇列的ID msgget函式的回傳值
			第二個引數: 訊息的首地址(將接受的訊息存到哪里去) 
			第三個引數: 訊息的大小
			第四個引數: 訊息的型別
				0  表示讀取訊息佇列中的第一條訊息
				>0 表示讀取訊息佇列中第一個型別為msgtyp的訊息
				<0 表示讀取訊息佇列中訊息型別 <=msgtyp 絕對值的型別最小的訊息
			第五個引數: 訊息的標志,給0即可
			回傳值: 成功回傳實際讀取資料的大小,失敗回傳-1
			
		msgctl 函式 
			函式功能: 表示對指定的訊息佇列執行指定的操作
			第一個引數: 訊息佇列的ID   msgget函式的回傳值
			第二個引數: 具體的命令
				IPC_RMID  洗掉訊息佇列,此時第三個引數給NULL即可
			第三個引數: 結構體指標 
			相關的命令
				使用 ipcs -q      命令 表示察看當前系統中存在的訊息佇列
				使用 ipcrm -q ID  命令 表示洗掉指定的訊息佇列 

4.使用管道實作行程間通信

	(1)概念和分類 
		概念: 本質上是以檔案作為媒介來實作行程間的通信,該檔案比較特殊,叫做管道檔案   
		管道分為: 有名管道 和 無名管道  
		有名管道: 一般采用命令創建管道檔案,實作任意兩個行程之間的通信
		無名管道: 一般采用系統函式來創建管道檔案,用于父子行程之間的通信
		
	(2)使用有名管道進行行程間的通信
		如: touch 檔案名(創建普通檔案) 
		
		使用  mkfifo 管道檔案名.pipe => 創建管道檔案 
			例子: mkfifo a.pipe =>創建管道檔案a.pipe
			
		使用 echo hello > a.pipe =>寫入資料到管道檔案中 
			例子: cat a.pipe => 讀取管道檔案的資料
			
		注意: 管道檔案本身并不會存盤傳遞的資料
		
	(3)使用無名管道實作行程間的通信
		pipe 函式 創建無名管道  
			函式功能: 主要用于創建管道檔案,利用引數回傳兩個檔案描述符,其中pipefd[0]關聯管道的讀端,pipefd[1] 關聯管道的寫端.
			注意: 管道是比較古老的通信方式,現在很少使用(了解)

5.使用共享記憶體實作行程間通信

	(1)概念:
		本質上是由內核維護的一塊記憶體區域,共享在兩個/多個行程之間,然后兩個/多個行程分別對該記憶體區域進行讀寫操作,從而實作通信,是最快的IPC的通信方式
		
	(2)共享記憶體通信的基本流程
		a.獲取key值 使用ftok函式
		b.創建/獲取共享記憶體,從而得到ID,使用 shmget 函式
		c.掛接共享記憶體,使用 shmat 函式
		d.使用共享記憶體,行程讀寫操作等
		e.脫接共享記憶體,使用 shmdt 函式
		f.如果不再使用,使用 shmctl 函式洗掉共享記憶體
		
	(3)相關函式決議
		shmget 函式     
			函式功能: 主要用于創建/獲取一個共享記憶體,得到ID
			第一個引數: key值,ftok函式的回傳值
			第二個引數: 共享記憶體的大小  
			第三個引數: 操作的標志
				IPC_CREAT - 創建
				IPC_EXCL  -  與IPC_CREAT 搭配使用,存在則創建失敗
				0         -  獲取已經存在的共享記憶體
            注意: 當創建新的共享記憶體時,需要指定權限
        
        shmat 函式
          	函式功能: 主要用于將指定的共享記憶體掛接到正在運行的行程的地址空間中,成功回傳共享記憶體的地址,失敗回傳-1.
			第一個引數: 共享記憶體的ID,也就是 shmget 的回傳值
			第二個引數: 共享記憶體的掛接地址,給NULL由系統選擇
			第三個引數: 掛接標志,直接給 0 即可
			
		shmdt 函式     
			函式功能: 表示按照引數指定的共享記憶體的地址進行脫節,引數傳遞shmat函式的回傳值即可
		
		shmctl 函式     
			函式功能: 主要用于對指定的共享記憶體執行指定的操作
			第一個引數:共享記憶體的ID,也就是 shmget 的回傳值
			第二個引數:執行的操作命令
				IPC_RMID  洗掉共享記憶體 
			第三個引數:給NULL即可
			相關的基本命令    
				ipcs -m   察看系統中已經存在的共享記憶體
				ipcrm -m  共享記憶體ID 洗掉指定的共享記憶體

6.使用信號量集實作行程間通信

	(1)信號量和信號量集概念
		信號量概念:
			信號量本質就是一個計數器,用于控制同時訪問共享資源的行程數/執行緒數,也就是說解決有限資源的分配問題.
		信號量集概念:
			信號量集就是表示信號量的集合,也就是多個計數器的集合,用于控制同時訪問多種共享資源的行程數/執行緒數.
		
	(2)信號量作業方式
		a.先把信號量進行初始化,初始化為最大值
		b.如果有行程,申請到共享資源,那么信號量的值減1
		c.當信號量的值為0時,終止行程對共享資源的申請,讓申請共享資源的行程進入阻塞狀態
		d.如果有行程釋放資源,那么信號量的值加1
		e.當信號量的值大于0時,阻塞的行程可以繼續搶占資源,搶占不到資源的行程繼續進入阻塞狀態等等
		
	(3)使用信號量集通信流程
		a.獲取key值          使用ftok函式
		b.創建/獲取信號量集   使用semget函式
		c.初始化信號量集      使用semctl函式
		d.操作信號量集        使用semop函式
		e.如果不再使用則洗掉   使用semctl函式
		
	(4)相關函式決議
		semget函式     
			函式功能: 創建/獲取信號量集的ID
			第一個引數:key值 ,ftok函式的回傳值
			第二個引數:信號量集的大小,也就是信號量的個數
			第三個引數:操作的標志
				IPC_CREAT   創建
				IPC_EXECL   與IPC_CREAT 搭配使用,存在則創建失敗
				0           獲取已經存在的信號量集
			注意: 當創建新的信號量集是,需要指定權限,如0644
		
		semctl函式     
			函式功能: 主要用于對信號量集實作各種控制操作 
			第一個引數: 信號量集的ID 使用semget函式的回傳值
			第二個引數: 信號量集的下標,從0開始
			第三個引數: 具體的操作命令
				IPC_RMID 洗掉信號量集,引數semnum被忽略,不需要第四個引數
				SETVAL  使用第四個引數的值給信號量集中下標為semnum的信號量進行初始化
			第四個引數: 可變長引數,是否需要取決于cmd
			
			semop 函式     
				函式功能: 對信號量集中指定的信號量進行操作
				第一個引數: 信號量集的ID,semget函式的回傳值
				第二個引數: 結構體指標
					結構體引數包含:
					unsigned short sem_num;  /*   信號量的下標 */
					short  sem_op;   /* 信號量的操作,正數增加,負數減少 */
					short  sem_flg;  /* 操作的標志,給0即可 */
				第三個引數: 表示第二個引數所指定的結構體陣列的元素的個數
				基本的命令
					ipcs -s 察看系統中存在的信號量集
					ipcrm -s 信號量集的ID ,洗掉指定的信號量集
					ipcs -a 察看系統中所有的IPC結構 

八、linux系統下的網路編程

1. 網路的基本常識

	七層網路協議
		由ISO 將網路從邏輯上劃分為七層:
		應用層    主要將資料交給應用程式
		表示層    主要將資料按照統一的格式進行封裝   應用層 TELNET  FTP WWW
		會話層    主要控制對話的開始和結束等
		傳輸層    主要使用具體的傳輸協議檢查和傳輸資料   TCP和UDP
		網路層	  主要進行路徑的選擇和傳遞資料   IP和路由
		資料鏈路層 主要將資料轉換為高低電平信號   網卡驅動
		物理層     主要借助網卡驅動,交換機設備等傳輸

	常見的協議
		A.TCP協議  - 傳輸控制協議,一種面向連接的協議,類似打電話
		B.UDP協議  - 用戶資料報協議,一種非面向連接的協議,類似發短信
		C.IP協議   - 互聯網協議,是TCP/UDP的底層協議   IPX 協議
	
	IP 地址
		IP 地址    - 是互聯網中唯一的地址標識,本質上來講,就是一個32位的整數,使用(IPV4)目前也有IPV6(128位二進制)
		日常生活中采用點分十進制表示法來描述一個具體的IP地址,也就是說,將每一個位元組,計算出一個十進制整數,多個十進制之間采用小數點分隔
		
	IP 地址主要分為兩個部分:網路地址+主機地址
	IP 地址分以下4類
		A類: 0 +7 位網路地址 +  24位主機地址
		B類: 10 + 14 位網路地址 + 16位主機地址
		C類: 110 + 21 位網路地址 +  8位主機地址
		D類: 1110 + 28 位多播地址
		
	查看IP的命令
		Window 系統下         ipconfig    ipconfig/all
		Unix/linux作業系統    ifconfig    /sbin/ifconfig
	
	子網掩碼
		一般與IP地址搭配使用,主要用于指定一個IP地址中具體的網路地址和主機地址,也就是說判斷兩個IP地址是否在同一個子網中0~255
		如: IP地址 172.40.5.210 子網掩碼 255.255.255.0 
		把IP和子網掩碼按位與 &
        172.40.5  - 網路地址
        210       - 主機地址
        
	物理地址
		物理地址又叫做Mac地址,本質上就是硬體網卡的地址
		主要用于通過系結Mac地址來實作上網設備的控制
		
	埠號
		IP地址     主要用于定位具體的某一臺主機
		埠號     主要用于定位該主機中具體的某一個行程
		埠號的資料型別: unsigned short型別 ,取值范圍是:0 ~ 65535 其中 0 ~1024 之間的埠由系統占用,自己指定埠號從 1025 以上開始使用
		
	位元組序
		如: 0x12345678 
		小端系統: 低位記憶體地址存放低位資料的系統叫做小端系統 
		小端  地址從小到大 0x78 0x56 0x34 0x12
		大端系統:低位記憶體地址存放高位資料的系統叫做高位系統
		大端  地址從小到大 0x12 0x34 0x56 0x78      
		
	網路位元組序
		主要描述資料在網路中傳遞時的位元組順序,而網路位元組序本質上就是大端位元組序
		
	主機位元組序
		主要描述資料根據在本地系統中存放的位元組順序,
		當發送時,由主機位元組序轉化為網路位元組序時候發送,
		當接收時,由網路位元組序轉化為主機位元組序.

2.基于socket的一對一通信模型

	(1)基本概念 
		socket 英文中是插座的意思
		socket 網路通信的載體,使用socket可以實作了兩個行程/兩個主機之間的通信
		
	(2)通信的模型
		服務器端:
			a.創建socket            使用socket函式
			b.準備通信地址           使用結構體型別
			c.系結socket和通信地址   使用bind函式
			d.進行讀寫操作           使用read/write函式
			e.關閉socket            使用close函式
		客戶端: 
			a.創建socket            使用socket函式
			b.準備通信地址           使用結構體型別
			c.連接socket和通信地址   使用connect函式
			d.進行讀寫操作           使用read/write函式
			e.關閉socket            使用clode函式
			
	(3)相關函式決議
	socket 函式    
		函式功能: 主要用于創建一個通信點,成功回傳一個描述符
		第一個引數: 表示 域/協議族,決定本地通信還是網路通信
			Name                Purpose                          Man page
			AF_UNIX, AF_LOCAL   Local communication            unix(7)  本地通信
			AF_INET             IPv4 Internet protocols           ip(7)   基于IPV4的網路通信
			AF_INET6            IPv6 Internet protocols           ipv6(7) 基于IPV6的網路通信 
			AF_IPX              IPX - Novell protocols
			AF_NETLINK          Kernel user interface device       netlink(7)
			AF_X25              ITU-T X.25 / ISO-8208 protocol     x25(7)
			AF_AX25             Amateur radio AX.25 protocol
			AF_ATMPVC           Access to raw ATM PVCs
			AF_APPLETALK        Appletalk                        ddp(7)
			AF_PACKET           Low level packet interface           packet(7)

		第二個引數: 型別,決定采用何種協議進行通信
			SOCK_STREAM  資料流的方式,基于TCP的通信協議
			SOCK_DGRAM   資料報的方式,基于UDP的通信協議
			
		第三個引數:特殊協議的意思,給0即可

	通信地址的資料型別
		a. 通用的通信地址
			struct sockaddr
			{
				sa_family_t   sa_family;    //協議族
				char          sa_data[14];  //資料內容
			}
		注意: 給通信地址通常用于函式的引數型別,用于各種通信地址之間的轉換
		
       b. 本地通信的結構體型別 
			#include<sys/un.h>
			struct sockaddr_un
			{            
				sa_family_t  sun_family; //地址族,和socket引數一致即可
				char         sun_path[]; //socket檔案的路徑和檔案名
			};   
			
       c. 網路通信的結構體型別
			#include<netinet/in.h>      
			struct  sockaddr_in
			{
				sa_family_t      sin_family;    // AF_INET
				in_port_t        sin_port;     // 埠號 
				struct in_addr   sin_addr;      // IP地址
			}; 
			struct  in_addr 
			{
				in_addr_t  s_addr;
			};
			
	bind 函式  函式功能: 主要用與系結指定的socket和通信地址
		第一個引數:socket的描述符,就是socket函式的回傳值
		第二個引數:結構體型別的指標(&通信地址)
		第三個引數:通信地址的大小  

	connect 函式  函式功能:主要用于socket和通信地址之間的連接
		第一個引數:socket的描述符,就是socket函式的回傳值
		第二個引數:結構體型別的指標(&通信地址)
		第三個引數:通信地址的大小

	位元組序的轉換函式
		#include <arpa/inet.h>
		uint32_t htonl(uint32_t hostlong);   主要將unsigned int 的主機位元組序轉換為網路位元組序 
		uint16_t htons(uint16_t hostshort);  主要將unsigned short的主機位元組序轉換位網路位元組序
		uint32_t ntohl(uint32_t netlong);    主要將unsigned int的網路位元組序轉換為主機位元組序                                         
		uint16_t ntohs(uint16_t netshort);   主要將unsigned short的網路位元組序轉換為主機位元組序

	IP地址的轉換函式
		#include <sys/socket.h>
		#include <netinet/in.h>
		#include <arpa/inet.h>
		in_addr_t inet_addr(const char *cp);
		函式功能:主要將字串型別的IP地址轉換為整數

3.基于TCP的協議的通信模型

	(1)創建通信模型
		服務器:
			a創建socket ,使用socket函式    
			b準備通信地址,使用結構體型別
			c系結socket和通信地址,使用bind函式
			d進行監聽,使用listen函式
			e回應客戶端的連接請求,使用accept函式
			f進行通信,使用read/write函式
			g關閉socket使用close函式
		客戶端:
			a 創建socket    使用socket函式
			b準備通信地址
			c鏈接socket    使用sonnect函式
			d進行通信
			e關閉socket    使用close函式
	(2)函式決議
		listen 函式   
			函式功能: 主要用于監聽指定socket上的連接個數
			第一個引數:socket描述符,socket函式的回傳值
			第二個引數: 排隊等待被回應的最大連接數
		accept 函式   
			函式功能: 主要用于回應客戶端的連接請求
			第一個引數:socket描述符,socket函式的回傳值
			第二個引數: 結構體指標,用于存盤客戶端的通信地址
			第三個引數:指標,通信地址的大小
			回傳值: 成功回傳用于通信的描述符,失敗回傳-1 
        socket 函式回傳的描述符主要用于監聽使用
     	inet_ntoa 函式  
     		函式功能: 主要將結構體型別的IP地址轉換為字串型別

4.基于UDP協議的通信模型

	(1)創建通信模型
	服務器:
		a創建socket           使用socket函式
		b準備通信地址          使用結構體型別
		c系結socket和通信地址  使用bind函式
		d進行通信              使用sendto()/recvfrom()/send()/recv()函式
		e關閉socket函式        使用close函式
	客戶端: 
		a創建socket           使用socket函式
		b準備通信地址          服務器的地址
		c進行通信             使用sendto()/recvfrom()/send()/recv()函式
		d關閉socket           使用close函式
		
	(2)函式決議
		發送訊息的函式   
			函式功能: 主要用于向指定的地址發送指定的資料
			ssize_t send(int sockfd, const void *buf, size_t len, int flags);
			ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
			第一個引數:socket描述符,socket函式的回傳值
			第二個引數:被發送資料的首地址
			第三個引數:發送資料的大小
			第四個引數:發送標志,該0即可
			第五個引數:目標地址
			第六個引數:目標地址的大小
			回傳值:成功回傳實際發送資料的大小,失敗回傳-1
			
		接收訊息的函式   
			函式功能:表示接受指定資料并提供來電顯示功能
			ssize_t recv(int sockfd, void *buf, size_t len, int flags);
			ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
			第一個引數:socket描述福
			第二個引數:首地址(把接受到的資料存到哪里去)
			第三個參書:接收的的資料大小
			第四個引數:接收的標志,給0即可
			第五個引數:保存發送方的通信地址(資料從哪里來)
			第六個引數:發送方通信地址的大小
			回傳值: 成功回傳接受到的資料大小,失敗-1

TCP協議和UDP協議的比較

	TCP協議
		(1)概念: TCP 傳輸控制協議,面向連接的協議,傳遞的是資料流.
			建立連接=> 傳遞資料=> 斷開連接    
		(2)優點: 可以重發一切資料,可一保證資料的完整性和準確性,接收方可以通知發送方控制資料量
		(3)缺點: 服務器壓力比較大,資源占用率比較高       
	UDP協議
		(1)概念: UDP 用戶資料報協議,非面向連接的協議,發送資料報
		(2)優點: 不需要全程保持連接,服務器壓力比較小,資源占用率比較低
		(3)缺點: 不會重發錯誤資料,不保證資料的準確性和完整性,接受方不會通知發送方進行資料量的控制 

九、linux系統下的多執行緒編程

1.基本概念

	目前主流的作業系統支持多行程,而在每一個行程的內部,可以支持多執行緒,也就是說執行緒是行程中的程式流
	行程是重量級單位,每個行程都需要獨立的記憶體空間,啟動新的行程對資源的是很大的消耗,而執行緒是輕量級單位,執行緒共享所在的行程的記憶體空間,但是每個執行緒都有一塊很小的獨立堆疊區.

2.執行緒的相關函式

	pthread_create 函式   
		函式功能: 主要用于曾在運行的行程中啟動新的執行緒 
		第一個引數:用于存盤新執行緒的ID
		第二個引數: 執行緒的屬性,給NULL即可,表示默認屬性
		第三個引數: 函式指標,表示新執行緒執行的處理函式
		第四個引數: 作為第三個引數函式指標的引數
		回傳值: 成功回傳0,失敗直接回傳錯誤編號
		
	注意:
		a. 編譯鏈接時,記得加上選項 -pthread
		b. 當啟動新執行緒之后,子執行緒和主執行緒各自獨立運行,每個執行緒內部的代碼按照次序執行,也就是多執行緒之間相互獨立,又互相影響,主執行緒結束,導致行程結束,而行程結束導致行程中所有的子執行緒隨之結束

	pthread_self 函式  
		函式功能: 主要用于獲取正在運行的執行緒ID,通常都是成功的,通過回傳值回傳獲取到的ID

	pthread_join函式   
		函式功能: 主要用于等待一個執行緒的結束,并且獲取退出碼
		第一個引數: 執行緒的ID
		第二個引數: 二級指標,用于獲取執行緒的退出碼
		注意: 該函式根據引數thread指定的執行緒進行等待,將目標執行緒終止時的退出狀態資訊拷貝到 *retval 這個引數指定的位置上
		
	pthread_detach函式
		函式的功能: 主要將引數指定的執行緒標記為分離狀態,對于分離狀態的執行緒來說,當該執行緒終止后,會自動將資源釋放給系統,不需要其他執行緒的加入/等待,也就是說分離的執行緒無法被其他執行緒使用prhread_join進行等待
		
		建議: 對于新啟動的執行緒來說,要么使用pthread_detach設定為分離狀態,要么使用pthread_join設定為可加入狀態
      
	pthread_exit 函式   
		函式的功能: 主要用于終止正在運行的執行緒,通過引數retval來帶出執行緒的退出狀態資訊,在同一個行程中的其他執行緒可以通過呼叫pthread_join函式來獲取退出狀態資訊
		
	pthread_cancel 函式(執行緒的取消函式)   
		函式功能: 主要用于對引數指定的執行緒發送取消的請求,目標執行緒是否會被取消以及何時被取消,主要依賴兩個屬性:setcancelstate 和setcanceltype
		
	pthread_setcancelstate 函式    
		函式功能: 主要用于設定新的取消狀態,回傳之前的取消狀態
		第一個引數: 新的取消狀態
		PTHREAD_CANCEL_ENABLE   允許被取消(默認狀態)
		PTHREAD_CANCEL_DISABLE   不允許被取消
		第二個引數: 獲取之前的取消狀態,不想獲取給NULL即可
		
	pthread_setcanceltype 函式   
		函式功能: 主要用于設定新的取消型別,獲取之前取消的型別
		第一個引數:設定新的取消型別
			PTHREAD_CANCEL_DEFERRED  延遲取消(默認的取消型別)
			PTHREAD_CANCEL_ASYNCHRONOUS   立即取消 
		第二個引數:獲取舊的取銷型別,不獲取則給NULL即可

3.執行緒的同步問題

	(1)基本概念:
		多執行緒共享行程中的資源,多個執行緒同時訪問相同的共享資源時,需要相互的協調以避免出現資料的不一致和混亂問題,而執行緒之間的協調和通信叫做執行緒的同步問題
	(2)執行緒同步的思想: 
		多執行緒訪問共享資源時,應該進行串行,而不是并行
	(3)執行緒同步的解決方法: 
		執行緒中提供了互斥量(互斥鎖)的機制來實作執行緒的同步
	(4)互斥量的使用步驟
		a.定義互斥量
			pthread_mutex_t mutext;
		b.初始化互斥量
			pthread_mutex_init(&mutex,0);
		c.使用互斥量進行加鎖
			pthread_mutex_lock(&mutext);   
		d.使用共享資源
		e.使用互斥量進行解鎖
			pthjread_mutex_unlock(&mutext);
		f.如果不再使用,則銷毀互斥量
			pthread_mutex_destroy(&mutext);

4.使用信號量 實作執行緒的同步問題

	(1)基本概念 
		信號量 - 本質就是一個計數器,用于控制同時訪問共享資源的行程數/執行緒數  
		當信號量的值是1時,效果等同于互斥量.
		
	(2)信號量的使用流程
		a. 定義信號量 
			sem_t sem;
		b. 初始化信號量
			sem_init(&sem,0,最大值);//值 0 表示控制控制執行緒的個數
		c. 獲取一個信號量(減1)
			sem_wait(&sem);
		d. 使用共享資源
		e. 釋放一個信號量
			sem_post(&sem);
		f. 如果不再使用,則銷毀信號量
			sem_destroy(&sem);

5.使用條件變數實作執行緒的同步問題

	生產者和消費者模型(重點掌握)   

總結

以上是linux下的c開發的基礎知識,使用的是linux系統下的API函式介面,熟練使用這些介面,可以實作相應的簡單功能.

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/183884.html

標籤:其他

上一篇:Zabbix監控系統(基于CentOS7)

下一篇:如何在阿里云服務器上搭建WordPress

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more